一、语句和语句分类
C语言的代码是由一条条的语句构成的,大致可以分为以下五类:
- 空语句
- 表达式语句
- 函数调用语句
- 复合语句
- 控制语句
空语句
空语句是一种在编程语言中使用的语句,它不执行任何操作,只是一个空占位符。在大多数编程语言中,分号(;)表示空语句。例如,在以下示例中,第2行是一个空语句:
int x;
;//空语句
int y;
空语句通常用于某些语言结构需要提供一个语句,但不需要执行任何操作的情况下,比如某些循环和条件语句中。
表达式语句
C语言中的表达式语句是一种语句,它包括一个表达式和一个分号,用于执行一些操作并返回一个值。表达式可以是一个常量、变量、函数调用或其他计算。表达式语句通常用于赋值、调用函数、递增或递减变量等操作。例如:
int a = 10;
a++;//表达式语句
printf("a的值为:%d\n", a);
这段代码中,a++
就是一个表达式语句,它将变量a
的值加1并返回,然后赋值给a
本身。printf
函数也是一个表达式语句,它将字符串和变量a
的值格式化后输出到控制台。表达式语句的执行结果可以忽略,因为它通常是为了产生副作用或改变程序状态而执行的。
函数调用语句
C语言的函数调用语句一般遵循以下格式:
函数名(参数列表);
其中,函数名是要调用的函数的名称,参数列表是传递给该函数的参数,可以是多个参数,用逗号隔开。例如:
printf("Hello, World!");
这个语句调用了C语言标准库中的printf函数,该函数输出字符串"Hello, World!"到屏幕上。
复合语句
C语言的复合语句是一组语句的组合,使用花括号"{ }"将一组语句括起来,作为一个整体语句来执行。常用于需要执行多个语句的地方,例如函数体、循环结构等。例如:
if (x > 0) {
printf("x is positive\n");
x = x * 2;
}
在上面的代码中,花括号括起来的两个语句组成了一个复合语句,当x大于0时,先输出一条信息,然后将x乘以2。复合语句可以嵌套使用,以便更复杂的逻辑控制。
控制语句
控制语句用于控制程序的执行流程,以实现程序的各种结构方式。C语言支持三种结构:顺序结构、选择结构、循环结构。它们由特定的语句定义符组成,C语言有九种控制语句,可以分为以下三类:
- 条件判断语句(分支语句):if语句、switch语句;
- 循环执行语句:do while语句、while语句、for语句;
- 转向语句:break语句、goto语句、continue语句、return语句
二、注释是什么?
C语言有两种注释方式:
- 单行注释:以“//”开头的单行注释。例如:
// 这是单行注释
- 多行注释:以“/”开头,“/”结尾的多行注释。例如:
/* * 这是多行注释 * 第二行 * 第三行 */
多行注释可以跨越多行,但不能嵌套使用。
注释可以在代码中添加说明、注解或者临时取消某些代码的执行。注释不会被编译器解析,对程序的执行没有任何影响。在编写代码时,注释的使用是一个良好的编程习惯。
三、数据类型介绍
C语言的数据类型可分为基本数据类型和复合数据类型两类。
基本数据类型包括:
1.整型(int):用于表示整数,包括有符号整数和无符号整数。
//短整型
short [int]
[signed] short [int]
unsigned short [int]
//整型
int
[signed] int
unsigned int
//⻓整型
long [int]
[signed] long [int]
unsigned long [int]
//更⻓的整型
//C99中引⼊
long long [int]
[signed] long long [int]
unsigned long long [int]
- 浮点型(float和double):用于表示实数,包括单精度浮点数和双精度浮点数。
float
double
long double
- 字符型(char):用于表示字符或小整数。
char
[signed] char
unsigned char
- 布尔型(bool):用于表示逻辑值,只有true和false两个取值。
C语言原本并没有为布尔值单独设置一个类型,而是使用整数0来表示假,非零值表示真。后来在C99中也引入了布尔类型,是专门表示真假的。代码演示如下:
_Bool flag =ture;
if (falg)
printf("i like c\n");
复合数据类型包括:
-
数组类型(array):包含相同数据类型的一组元素。
-
结构体类型(struct):包含不同数据类型的一组元素。
-
联合体类型(union):包含不同数据类型的一组元素,但只能存储其中的一个元素值。
-
枚举类型(enum):用于表示一组有限的取值集合。
四、signed和unsigned
在C语言中,signed和unsigned是两种用于表示整数类型的修饰符。
signed表示有符号整数类型,可以表示正数、负数和0。
unsigned则表示无符号整数类型,只能表示非负数和0。
在C语言中,整数类型默认为signed,如果希望使用unsigned类型,需要在变量前面加上unsigned关键字。例如:
unsigned int a = 10;
整数变量声明为 unsigned 的好处是,同样长度的内存能够表示的最大整数值,增大了⼀倍。
比如,16位的 signed short int 的取值范围是:-32768~32767,最大是32767;而
unsigned short int 的取值范围是:0~65535,最大值增大到了65,535。32位的 signed
int 的取值范围可以参看 limits.h 中给出的定义。
#define SHRT_MIN (-32768) //有符号16位整型的最⼩值
#define SHRT_MAX 32767 //有符号16位整型的最⼤值
#define USHRT_MAX 0xffff //⽆符号16位整型的最⼤值
#define INT_MIN (-2147483647 - 1) //有符号整型的最⼩值
#define INT_MAX 2147483647 //有符号整型的最⼤值
注意:使用无符号整数类型时要注意溢出问题,因为当超出范围时,其值将重新从0开始计数,可能会导致程序出现错误。
五、数据类型的取值范围
其实每⼀种数据l类型有自己的取值范围,也就是存储的数值的最大值和最小值的区间,有了丰富的类型,我们就可以在适当的场景下去选择适合的类型。如果要查看当前系统上不同数据类型的极限值:
limits.h
文件中说明了整型类型的取值范围。
float.h
这个头文件中说明浮点型类型的取值范围。
为了代码的可移植性,需要知道某种整数类型的极限值时,应该尽量使用这些常量。
• SCHAR_MIN
, SCHAR_MAX
:signed char 的最⼩值和最⼤值。
• SHRT_MIN
, SHRT_MAX
:short 的最⼩值和最⼤值。
• INT_MIN
, INT_MAX
:int 的最⼩值和最⼤值。
• LONG_MIN
, LONG_MAX
:long 的最⼩值和最⼤值。
• LLONG_MIN
, LLONG_MAX
:long long 的最⼩值和最⼤值。
• UCHAR_MAX
:unsigned char 的最⼤值。
• USHRT_MAX
:unsigned short 的最⼤值。
• UINT_MAX
:unsigned int 的最⼤值。
• ULONG_MAX
:unsigned long 的最⼤值。
• ULLONG_MAX
:unsigned long long 的最⼤值
六、变量
C语言的变量是用来存储数据的,它们是程序中的基本构建块之一。变量需要进行声明(定义),包括变量的名称和类型,以便计算机在执行程序时知道如何分配和使用内存空间。
变量在创建的时候就给一个初始值,就叫做初始化。
int age = 18;
char ch = 'w';
double weight = 48.0;
unsigned int height = 100;
全局变量
在大括号外部定义的变量就是全局变量
全局变量的使用范围更广,整个工程中想使用,都是有办法使用的。
局部变量
在大括号内部定义的变量就是局部变量
局部变量的使用范围是比较局限,只能在自己所在的局部范围内使用的。
#include <stdio.h>
int global = 2023;//全局变量
int main()
{
int local = 2018;//局部变量
printf("%d\n", local);
printf("%d\n", global);
return 0;
}
当局部变量和全局变量同名的时候,局部变量优先使用。
#include <stdio.h>
int n = 1000;
int main()
{
int n = 10;
printf("%d\n" n);//打印的结果是10
return 0;
}
⼀般我们在学习C/C++语⾔的时候,我们会关注
内存中的三个区域:栈区、堆区、静态区。
- 局部变量是放在内存的栈区
- 全局变量是放在内存的静态区
- 堆区是⽤来动态内存管理的
七、算术操作符:+、-、*、/、%
C语言的算术操作符包括:(双目操作符)
-
+
(加法):对两个数进行加法运算,如:a + b
。 -
-
(减法):对两个数进行减法运算,如:a - b
。
#include <stdio.h>
int main()
{
int x = 4 + 22;
int y = 61 - 23;
printf("%d\n", x);
printf("%d\n", y);
return 0;
}
*
(乘法):对两个数进行乘法运算,如:a * b
。
#include <stdio.h>
int main()
{
int num = 5;
printf("%d\n", num * num); // 输出 25
return 0;
}
/
(除法):对两个数进行除法运算,如:a / b
。除号的两端如果都是整数,执行的是整数除法,得到的结果也是整数。
#include <stdio.h>
int main()
{
float x = 6 / 4;
int y = 6 / 4;
printf("%f\n", x); // 输出 1.000000
printf("%d\n", y); // 输出 1
return 0;
}
如果希望得到的结果是浮点型,两个运算数必须至少有一个是浮点数。
#include <stdio.h>
int main()
{
float x = 6.0 / 4; // 或者写成 6 / 4.0
printf("%f\n", x); // 输出 1.500000
return 0;
}
%
(取模):对两个数进行取模运算,即取余数,如:a % b
。只能用于整数,不能用于浮点数。
#include <stdio.h>
int main()
{
int x = 6 % 4; // 2
return 0;
}
负数求模的规则是结果的正负号由第一个运算数的正负号来决定。
#include <stdio.h>
int main()
{
printf("%d\n", 11 % -5); // 1
printf("%d\n",-11 % -5); // -1
printf("%d\n",-11 % 5); // -1
return 0;
}
八、赋值操作符:= 和复合赋值
赋值操作符=
在变量创建的时候给⼀个初始值叫初始化,在变量创建好后,再给⼀个值,这叫赋值。
int a = 100;//初始化
a = 200;//赋值,这⾥使⽤的就是赋值操作符
赋值操作符也可以连续赋值,如:
int a = 3;
int b = 5;
int c = 0;
c = b = a+3;//连续赋值,从右向左依次赋值的
C语言虽然支持这种连续赋值,但是写出的代码不容易理解,建议还是拆开来写,这样方便观察代码的执行细节。
int a = 3;
int b = 5;
int c = 0;
b = a+3;
c = b;
复合赋值符
在写代码时,我们经常可能对⼀个数进行自增、自减的操作,如下代码:
int a = 10;
a = a+3;
a = a-2;
C语⾔给提供了更加方便的写法:
int a = 10;
a += 3;
a -= 2;
C语⾔中提供了复合赋值符,方便我们编写代码,这些赋值符有:
+= -=
*= /= %=
>>= <<=
&= |= ^=
九、单目操作符:++、–、+、-
前面介绍的操作符都是双目操作符,有2个操作数的。C语⾔中还有⼀些操作符只有⼀个操作数,被称为单目操作符。 ++
、--
、+
(正)、-
(负) 就是单目操作符。
++
是⼀种自增的操作符,又分为前置++
和后置++
,--
是⼀种自减的操作符,也分为前置--
和后置--
.
++
int a = 10;
int b = ++a;//++的操作数是a,是放在a的前⾯的,就是前置++
printf("a=%d b=%d\n",a , b);
//先+1,后使用
int a = 10;
int b = a++;//++的操作数是a,是放在a的后⾯的,就是后置++
printf("a=%d b=%d\n",a , b);
//先使用,后+1
--
int a = 10;
int b = --a;//--的操作数是a,是放在a的前⾯的,就是前置--
printf("a=%d b=%d\n",a , b);//输出的结果是:9 9
//先-1,后使用
int a = 10;
int b = a--;//--的操作数是a,是放在a的后⾯的,就是后置--
printf("a=%d b=%d\n",a , b);//输出的结果是:9 10
//先使用,后-1
这里的+
是正号,-
是负号,都是单目操作符。
运算符 +
对正负值没有影响,是⼀个完全可以省略的运算符,但是写了也不会报错。
int a = +10; 等价于 int a = 10;
运算符 -
用来改变一个值的正负号,负数的前面加上 -
就会得到正数,正数的前面加上 -
会得到负数。
int a = 10;
int b = -a;
int c = -10;
printf("b=%d c=%d\n", b, c);//这⾥的b和c都是-10
int a = -10;
int b = -a;
printf("b=%d\n", b); //这⾥的b是10
十、强制类型转换
在操作符中还有⼀种特殊的操作符是强制类型转换,语法形式很简单,形式如下:
(类型)
请看代码:
int a = 3.14;
//a的是int类型, 3.14是double类型,两边的类型不⼀致,编译器会报警告
为了消除这个警告,我们可以使用强制类型转换:
1 int a = (int)3.14;//意思是将3.14强制类型转换为int类型,这种强制类型转换只取整数部分
俗话说,强扭的瓜不甜,我们使用强制类型转换都是万不得已的时候使用,如果不需要强制类型转化就能实现代码,这样⾃然更好的。