0基础玩转C语言—初识C语言(下)

简介: 0基础玩转C语言—初识C语言(下)

本章为大家介绍的是初识C语言(下),如果对C语言感兴趣的话,可以看一下笔者的初始C语言(上)。因为是初识,所以下面要介绍的内容主要涉及简单的概念,以及一些基础的知识点。大家在学习这部分的时候也不要太过于纠结,只需简单理解,后续我还会对下面的知识点详细介绍(大家期待一下吧😊)。博主尽量做到每一篇文章都浅显易懂,句句重点✍️欢迎诸位指点斧正!

一、判断语句

1.什么是判断语句?

如果某些条件满足,才能做某件事情,而不满足时不允许做,这就是所谓的判断其实这里的判断语句有时候也被叫作条件语句、选择语句,无论叫什么名字,它的本质都是一样的,都具有一致的执行逻辑,如下图:

2.小试牛刀

如果在校期间代码数量超过1万行,那么恭喜你,你将会拿到一个好offer!如果在校期间代码少于1万行,那么很遗憾,你的技术未达到要求,你可能要失业了。显然这个例子比较尖锐,但这也是一个简单的判断语句,代码实现如下👇:

#include<stdio.h>
int main()
{
  int codes = 100001;//假设在校敲了10万零1行代码
  if (codes >= 100000)//判断是否达到要求
  {
    printf("你将会拿到一份好offer!\n");
  }
  else
  {
    printf("你的技术未达到要求,你可能要失业了\n");
  }
  return 0;
}

二、循环语句

1.什么是循环?

说起循环,大家肯定不陌生,其实循环的概念很简单,无非就是反复的做一件事。比如太阳的东升西落、春夏秋冬四季的变换、钟表的反复轮转等等,可以说循环无处不在!

循环的执行逻辑如下:

2. 小试牛刀

编写代码表示你在拿到满意的offer后,为祖国健康工作50年!其实这就是一个有限循环,代码实现如下👇:

#include<stdio.h>
int main()
{
  printf("我拿到了一份满意的offer!\n");
  int year = 1;
  while (year<=50)//循环条件
  {
    printf("你为祖国工作第%d年\n", year);//循环内容
    year++;                            //循环内容
  }
  return 0;
}

三、函数

对于函数可以这样说:函数是C程序的基本单位,即C程序由函数组成,函数存在的意思是简化代码,使代码可以复用。


函数主要分为两大类,分别是库函数自定义函数。对于函数模块之后会有详细介绍,这里就通过一个求和函数帮助大家简单理解函数👇:

//方法一:(直接法)
#include <stdio.h>
int main()
{
  int num1 = 0;
  int num2 = 0;
  int sum = 0;
  printf("输入两个操作数:>");
  scanf("%d %d", &num1, &num2);//&为取地址操作符,本章会有介绍
  sum = num1 + num2;
  printf("sum = %d\n", sum);
  return 0;
}
 
//上述代码,写成函数如下:
//方法二:(函数法)
#include <stdio.h>
//函数定义
//int-返回类型,Add-函数名,x,y-形参
int Add(int x, int y)
{
  int z = x + y;
  return z;
}
int main()
{
  int num1 = 0;
  int num2 = 0;
  int sum = 0;
  printf("输入两个操作数:>");
  scanf("%d %d", &num1, &num2);
  sum = Add(num1, num2);
  printf("sum = %d\n", sum);
  return 0;
}

四、数组

1.数组的定义

现在要存储1-10十个数字,该怎么存储?为了解决这类问题,C语言给出了数组的概念,数组:一类相同元素的集合。清楚了概念之后我们应该怎么定义数组呢?

//下面这行代码表示我们定义了一个整形数组:
int arr[10] = {1,2,3,4,5,6,7,8,9,10};

int-数组类型

arr-数组名

[10]-数组大小是10个整形

{1,2,3,4,5,6,7,8,9,10}-数组内容

2.数组的下标

C语言规定:数组的每个元素都有一个下标,下标是从0开始的。数组可以通过下标来访问的。

例如上述数组:int arr[10]={1,2,3,4,5,6,7,8,9,10}

下面介绍通过数组下标访问数组元素👇 :

3.数组的使用

#include <stdio.h>
int main()
{
 
  int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
 
  printf("%d\n", arr[0]);//输出1
  printf("%d\n", arr[9]);//输出10
  return 0;
}

五、运算符

C语言运算符也叫操作符,很多也很杂,在初识这部分,我就先将C语言中所有的运算符列举出来,然后挑选其中比较常用易混淆的运算符进行讲解,我们先点到为止,后期我还会更新操作符详解哦😊

1.算数运算符

这里假设A=10,B=20

运算符 描述 实例
+ 把两个操作数相加 A + B 将得到 30
- 从第一个操作数中减去第二个操作数 A - B 将得到 -10
* 把两个操作数相乘 A * B 将得到 200
/ 分子除以分母 B / A 将得到 2
% 取模运算符,整除后的余数 B % A 将得到 0
++ 自增运算符,整数值增加 1 A++ 将得到 11
-- 自减运算符,整数值减少 1 A-- 将得到 9

1.分子除分母-/

分子除分母运算符分为整数除法浮点数除法,详见代码:

#include<stdio.h>
int main()
{
  int a = 3 / 5;//整数除法,结果返回商
  float b = 3.0 / 5;//浮点数除法,结果返回浮点数
  printf("a=%d\n",a);
  printf("b=%f\n",b);
  return 0;
}
//输出a=0
//    b=0.600000


2.取模运算符-%

对于取模运算符-%,操作符的两个操作数必须为整数。返回的是整除之后的余数

详见代码:

#include<stdio.h>
int main()
{
  int a = 9 % 6;//取余
  printf("a=%d\n", a);
  return 0;
}
//输出a=3

3.自增运算符 ++

自增运算符分为两种:前置++,先++,后使用;后置++,先使用,后++

详见代码:

#include<stdio.h>
int main()
{
  int a = 10;
  int b = 10;
  printf("a=%d\n",++a);//前置++,先++,后使用
  printf("先使用:b=%d\n",b++);//后置++,先使用,后++
 
  //b使用后仍然会自增,再次打印b:
  printf("后自增:b=%d\n",b);
  return 0;
}
//输出:a=11
//      先使用:b=10
//      后自增:b=11

4.自减运算符 --

自减运算符与自增运算符原理相同,这里就不再赘述

2.移位运算符

假设A=60

运算符 描述 实例
<< 二进制左移运算符。将一个运算对象的各二进制位全部左移若干位(左边的二进制位丢弃,右边补0)。 A << 2 将得到 240,即为 1111 0000
>> 二进制右移运算符。将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 A >> 2 将得到 15,即为 0000 1111

3.位运算符

运算符 描述 实例
& 按位与运算符,按二进制进行“与”运算 0&0=0;0&1=0;1&0=0;1&1=1
| 按位或运算符,按二进制位进行"或"运算 0|0=0;0|1=1; 1|0=1;1|1=1;
^ 异或运算符,按二进制位进行"异或"运算。运算规则: 0^0=0;0^1=1; 1^0=1;1^1=0;
~ 取反运算符,按二进制位进行"取反"运算。运算规则: ~1=-2;~0=-1;

4.赋值运算符

运算符 描述 实例
= 简单的赋值运算符,把右边操作数的值赋给左边操作数 C = A + B 将把 A + B 的值赋给 C
+= 加且赋值运算符,把右边操作数加上左边操作数的结果赋值给左边操作数 C += A 相当于 C = C + A
-= 减且赋值运算符,把左边操作数减去右边操作数的结果赋值给左边操作数 C -= A 相当于 C = C - A
*= 乘且赋值运算符,把右边操作数乘以左边操作数的结果赋值给左边操作数 C *= A 相当于 C = C * A
/= 除且赋值运算符,把左边操作数除以右边操作数的结果赋值给左边操作数 C /= A 相当于 C = C / A
%= 求模且赋值运算符,求两个操作数的模赋值给左边操作数 C %= A 相当于 C = C % A
<<= 左移且赋值运算符 C <<= 2 等同于 C = C << 2
>>= 右移且赋值运算符 C >>= 2 等同于 C = C >> 2
&= 按位与且赋值运算符 C&=2等同于C=C&2
^= 按位异或且赋值运算符 C^=2等同于C=C^2
|= 按位或且赋值运算符 C|=2等同于C=C|2

像这种有两个运算符组成的赋值运算符也叫复合赋值符,这里讲解一个,大家类比理解,详见代码:

#include<stdio.h>
int main()
{
  int a = 10;
    //复合赋值符
  a += 10;//相当于a = a + 10;
  printf("a=%d\n",a);
  return 0;
}
//输出a=20

5.关系运算符

假设A=10,B=20

算符 描述 实例
== 检查两个操作数的值是否相等,如果相等则条件为真。 (A == B) 为假。
!= 检查两个操作数的值是否相等,如果不相等则条件为真。 (A != B) 为真。
> 检查左操作数的值是否大于右操作数的值,如果是则条件为真。 (A > B) 为假。
< 检查左操作数的值是否小于右操作数的值,如果是则条件为真。 (A < B) 为真。
>= 检查左操作数的值是否大于或等于右操作数的值,如果是则条件为真。 (A >= B) 为假。
<= 检查左操作数的值是否小于或等于右操作数的值,如果是则条件为真。 (A <= B) 为真。

关系运算符需要注意的是:==在C语言中表示判断;而=在C语言中表示赋值,注意不要混淆

6.逻辑运算符

C语言中规定0为假,非0为真。假设给定初始值:A=0;B=2

运算符 描述 实例
&& 称为逻辑与运算符。如果两个操作数都非零,则条件为真。 (A && B) 为假。
|| 称为逻辑或运算符。如果两个操作数中有任意一个非零,则条件为真。 (A || B) 为真。
! 称为逻辑非运算符。用来逆转操作数的逻辑状态。如果条件为真则逻辑非运算符将使其为假。 !(A && B) 为真。

详见代码:

#include<stdio.h>
int main()
{
  int A = 0;//C语言中规定0为假
  int B = 2;//非零为真
  printf("%d\n",A && B);
  printf("%d\n",A || B);
  printf("%d\n",!(A && B));
  return 0;
}
//输出 0 1 1//默认真为1

7.单目运算符

(1)什么是目?

🚩这里将单目操作符单独列出来,主要为了让大家理解“目”的概念。所以到底什么是目呢?其实目的概念说起也简单,只要记住目就是运算数,几目运算符就要求有几个运算数。比如常见的算数运算符(+ - * /)这些都是双目运算符,都要求必须要有两个运算数才能完成运算

(2)C语言单目运算符表

运算符 描述
逻辑非运算符
- 取负(不是减)
+ 取正(一般省略不写)(不是加)
& 取地址
sizeof 返回变量大小
~ 按位取反
-- 自减(上面介绍过)
++ 自增(上面介绍过)
* 解引用运算符
(类型) 强制类型转换运算符

1.这里的“+”、“-”表示取正负不表加减,通常取正省略不写

2.sizeof是返回变量或类型的大小,在初识C语言(上)中有使用

3.取地址运算符-&与解引用运算符-*在后面指针中介绍

下面简单介绍-强制类型转换运算符,详见代码👇:

#include<stdio.h>
 int main()
 {
   int a = (int)3.14;
   printf("%d\n", a);
   return 0;
 }
//输出3

(3)拓展

需要注意的是:相同的符号当操作数不同时具有不同的含义

例如:

符号 一个操作数(单目) 两个操作数(双目)
+ 取正运算符 相加运算符
- 取负运算符 相减运算符
* 解引用运算符 相乘运算符
& 取地址运算符 按位与运算符

8.条件运算符

条件运算符也叫三目运算符,它是C语言中唯一的三目运算符,使用时连接3个对象

形式:exp1 ? exp2: exp3

使用详见代码:👇

#include<stdio.h>
int main()
{
  int a = 10;
  int b = 20;
  int max = 0;
  max = (a > b ? a : b);//表示如果a>b为真返回a;否则返回b
  printf("max=%d\n", max);
  return 0;
}
//输出max=20
//上述代码与下面代码等价:
#include<stdio.h>
int main()
{
  int a = 10;
  int b = 20;
  int max = 0;
  if (a > b)
  {
    max = a;
  }
  else
  {
    max = b;
  }
  printf("max=%d",max);
  return 0;
}
输出max=20

9.逗号表达式

我们先看定义:逗号表达式就是用逗号隔开的一串表达式

形式:exp1,exp2,exp3,...expN

熟悉了这些后,那么逗号表达式的运算规则怎样的呢?我们这里给出:逗号表达式是从左向右以此计算的,整个表达式的结果是最后一个表达式的结果。下面我们举例说明:👇

#include<stdio.h>
int main()
{
  int a = 0;
  int b = 3;
  int c = 5;
        //a=5   c=1   b=3
  int d = (a = b + 2, c = a - 4, b = c + 2);
  printf("d=%d\n",d);
  return 0;
}
//输出d=3

10.下标引用、函数调用和结构成员

操作符 描述
[ ] 下标引用操作符,用于数组下标,例如arr[0]
( ) 函数调用操作符,用于函数名后,例如main()后的()
. 点操作符
-> 指针操作符

由于下标引用操作符以及函数调用操作符上述都有使用,这里就不再赘述。对于点操作符以及指针操作符会在本章后面的结构体讲解哦

六、关键字

1.常见关键字

auto  break  case  char  const  continue  default  do  double else  enum extern float  for goto if  int  long  register   return  short  signed sizeof  static struct  switch  typedef union unsigned  void  volatile  while

突然看到这么多的关键字,你有没有被吓到呢?😲,别担心,其实对于关键字我们并不需要现在就全部掌握,毕竟学习技术嘛,我们不需要死记硬背,其实关键字就好比我们的汉字,我们在学习汉字时也不是把全部的汉字都学一遍。当我们遇到时在去学习也是完全可以的,所以对于这种琐碎的知识,我并不建议大家一下全部学完,一边学习一边记忆会更有效果哦✍️下面我就开个头给大家先介绍两个哈!👇

2.关键字 register

(1)拓展

在介绍关键字 register 之前,我们先了解一下计算机中数据的存储,计算机的储存单元为寄存器——>内存——>硬盘,在计算机中为了适配CPU的处理速度出现了寄存器,在计算机的存储单元中,寄存器的读写速度是最快的。

我们来看计算机存储金字塔层次结构:

我们现在需要了解的是:CPU 并不会直接和每⼀种存储器设备直接打交道,⽽是每⼀种存储器设备只和它相邻的存储器设备打交道。当然了,话说回来,我们现在只需要知道在计算机的存储单元中,寄存器的读写速度是最快的。

(2)关键字 register的简单使用

现在我们已经知道寄存器的读写速度是非常快的,因此当我们想要处理大量且频繁被使用的数据时,就可以将其放到寄存器中,从而提高处理效率。例如下面代码:👇

#include<stdio.h>
int main()
{   //假设num被大量频繁使用
  register int num = 100;//将num放在寄存器中,提升效率
  return 0;
}

3.关键字 typedef

typedef 全称-type define顾名思义是类型定义,不过这里应该理解为类型重命名。它的主要作用是使复杂类型简单化,那么具体应该怎么去用呢?来,废话少说,上代码:

#include<stdio.h>
int main()
{
  //对于unsigned int 类型可能写起来不太方便,我们可以通过重命名
  //将unsigned int命名为u_int从而实现简化的目的
  typedef unsigned int u_int;
  unsigned int num = 20;
  u_int num2 = 20;//num1和num2两个类型一样
  return 0;
}

4. 关键字 static

在C语言中:

static是用来修饰变量和函数的,它主要三种使用形式,下面我们一一介绍:

(1) 修饰局部变量-称为静态局部变量

我们先看下图中的两个代码,他们都会输出些什么呢?

输出结果:

同样都是循环5次,为什么输出的结果不同呢?这里就引出了static修饰局部变量的作用:

在初识C语言(上)我们已经讲到局部变量的生命周期是:从进入作用域生命周期开始,出作用域生命周期结束。因此,程序1每次调用test函数都要经历变量的创建和销毁,所以每次打印出a的值都是2(1+1)。而对于程序2,test函数中的a变量被static修饰,而static关键字的作用是改变局部变量的生命周期。也就是说变量a的生命周期不在局限在test函数内部,而是整个程序,因此调用test函数a变量只创建一次,在程序结束时才会销毁,因此循环五次输出2,3,4,5

结论:static修饰局部变量改变了变量的生命周期,让静态局部变量出了作用域依然存在,到程序结束,生命周期才结束。(本质上:改变了变量的储存类型)

(2) 修饰全局变量-称为静态全局变量

我们已知全局变量的作用域是整个工程,调整整个工程中任何地方都能使用:

但是当我们用static关键字修饰全局变量,使得这个全局变量只能在本源文件中使用,在其他源文件中使用就会报错:

结论:一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其他源文件内使用(本质上:是因为全局变量具有外部连接属性,被static修饰后就变成了内部连接属性)

(3) 修饰函数-称为静态函数

其实static修饰全局变量和修饰函数原理的原理相同,详见下图:

结论:一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件内使用(本质上:static是将函数的外部链接属性变成了内部链接属性)

七、#define定义常量和宏

#define-叫做预处理指令,#define定义的常量博主有在初始C语言(上)讲解哦,不了解的小伙伴可以点击查看:初识C语言(上)

下面简单讲解#define定义的宏:

大家先看一段代码,你们认为这段代码会输出什么呢?

#define ADD(X, Y) X+Y
#include <stdio.h>
int main()
{
  int sum = ADD(2, 3);
  printf("sum1 = %d\n", sum);
 
  sum = 4 * ADD(2, 3);
  printf("sum2 = %d\n", sum);
 
  return 0;
}
//答案:
//输出:sum1=5    sum2=11

结果输出sum1=5  sum2=11 你答对了吗?下面我来给大家解释一下:

1.首先我们要清楚宏是怎样使用的,在C语言中宏的使用是替换,也就是说你定义的是什么,你就直接使用什么。比如上面#define定义的是X+Y,那么sum2在使用时为:4*2+3,因为你定义时没有用( )所以使用时会先算4*2,因此得到的结果是11,而不是20

因此为了能够得到sum2=20,我们可以写成下面的形式:👇

#define ADD(X, Y) ((X)+(Y))//因为使用的的X、Y不一定都是数据
#include <stdio.h>         //可能是表达式,所以带 (X)、(Y)
int main()
{
  int sum = ADD(2, 3);
  printf("sum = %d\n", sum);
 
  sum = 10*ADD(2, 3);
  printf("sum = %d\n", sum);
 
  return 0;
}

八、指针

指针作为C语言中的一个重难点,初识阶段的话大家可能不容易理解,我这里就带着大家简单学习一下C语言中的指针,尽量做到通俗易懂,当前大家只需要笼统的了解指针就行,后续我还会详细的介绍哦。

1. 内存

学习指针首先要了解内存:

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。这里就好比电脑是我们的学校,内存就是学校的一个宿舍楼,而一个内存单元就代表宿舍楼中的一个宿舍,而宿舍的门牌号就表示一个地址

如下图:

2.取地址

变量是创建在内存中的(在内存中分配空间的),每个内存单元都有地址,所以变量也是有地址的。大家还记得取地址运算符吗-&,下面我们就用它来取出变量地址:

代码展示:

#include <stdio.h>
int main()
{
int num = 10;
&num;//取出num的地址
  
printf("%p\n", &num);//打印地址,%p是以地址的形式打印
return 0;
}
//输出为:008FFC78-大家不要纠结,这就是地址的形式

上述代码的执行结果为:008FFC78-大家不要纠结,这就是地址的形式

注意:我们已知这里的num是int类型,所以占用的4个字节,每个字节都有地址,并且取地址时取出的是第一个字节的地址(较小的地址)

3. 指针

当我们取出地址,那地址又该如何存储呢?C语言定义指针变量用来存放地址

代码展示:

#include <stdio.h>
int main()
{
int num = 10;
int *p = &num;
  return 0;
}

显然这里使用的是整形指针,除此之外还有char*指针类型,float*指针类型......

4.指针的简单使用

下面我们以char类型的指针举例:

#include <stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'q';//*解引用操作符
printf("%c\n", ch);
  return 0;
}

*pc='q' 表示通过ch中的地址找到ch(这也就是单目操作符*的作用),并修改ch为字符q

5.指针变量的大小

首先指针变量的大小跟指针的类型是没有关系的,它取决于地址的大小

对于地址的大小,这里有个硬性规定:

  • 32位平台下地址是32个bit位(即4个字节)
  • 64位平台下地址是64个bit位(即8个字节)
#include <stdio.h>
//指针变量的大小取决于地址的大小
//32位平台下地址是32个bit位(即4个字节)
//64位平台下地址是64个bit位(即8个字节)
int main()
{
  printf("%d\n", sizeof(char *));
  printf("%d\n", sizeof(short *));
  printf("%d\n", sizeof(int *));
  printf("%d\n", sizeof(double *));
  return 0;
}

因此上述代码在32位平台下输出4,在64位平台下输出8

九、结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。

比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息,我们该怎么描述呢?这里就用到了结构体。下面我们就用结构体创建一个学生类型,并访问一个学生的信息

代码如下:

//创建一个学生类型:
struct Stu
{  
  //成员变量
  char name[20];//姓名
  int age;      //年龄
  char id[20];//学号
};
int main()
{   
  //结构体的创建和初始化
  struct Stu s = { "张三",20,"123456" };//创建了一个s结构体变量
  printf("输出方法1:%s %d %s\n",s.name,s.age,s.id);//访问成员变量
 
  struct Stu* ps = &s;
  printf("输出方法2:%s %d %s\n",(*ps).name,(*ps).age,(*ps).id);//这种方法比较繁琐
 
  printf("输出方法3:%s %d %s\n",ps->name ,ps->age ,ps->id );//这种方法直观
  return 0;
}
//三种方法均输出:张三 20 123456

上述程序中涉及到‘点’操作符和‘箭头’操作符,下面展开讲解:

1、点操作符使用方法:结构体变量.成员变量

作用:访问成员变量

2、箭头操作符使用方法:结构体指针->成员变量

作用:访问成员变量

初识C语言部分到这里就结束了,感谢各位老铁的观看,如果感觉不错的话请给博主一个三连哦🥰,撒花庆祝一下吧🎉🎉🎉

老铁们保持coding,我们下期再见!!!



相关文章
|
1月前
|
C语言
C语言练习5
C语言练习5。
17 2
|
1月前
|
存储 编译器 Linux
【C语言】初识C语言
【C语言】初识C语言
28 0
|
1月前
|
存储 程序员 C语言
C语言 (2)
C语言 (2)
16 0
|
9月前
|
C语言
C语言练习
C语言练习。
54 1
|
1月前
|
BI C语言
C语言:练习1
C语言:练习1
43 2
C4.
|
1月前
|
存储 算法 安全
C语言的算法结构
C语言的算法结构
C4.
35 0
|
10月前
|
C语言
C语言中的坑(1)
C语言中的坑(1)
35 0
|
7月前
|
存储 C语言 C++
初识C语言(3)
初识C语言(3)
93 0
|
7月前
|
自然语言处理 Java 编译器
零基础玩转C语言-初识C语言(上)
零基础玩转C语言-初识C语言(上)
102 0
|
7月前
|
存储 安全 编译器
初识c语言(下)
初识c语言(下)
25 0