[TOC]
C语言中一定要有main函数(主函数)
printf是专门用来打印数据的一个库函数
std - 标准
i - input
o - output
C语言规定
main函数是程序的入口
main函数有且仅有一个
#include <stdio.h>
int main()
{
printf("Hello World!\n");
return 0;
}C语言内置:
| 数据类型 | 中文名称 | 所占字节 |
|---|---|---|
| char | 字符型 | 1 |
| short | 短整型 | 2 |
| int | 整型 | 4 |
| long | 长整型 | 4 |
| long long | 更长的整形 | 8 |
| float | 单精度浮点型 | 4 |
| double | 双精度浮点型 | 8 |
创建:
-
struct结构体 -
枚举
C语言规定
sizeof(long) >= sizeof(int)
注:sizeof用于获取某个数据类型所占用空间的字节数
#include <stdio.h>
int main()
{
printf("char: %zu\n", sizeof(char));
printf("short: %zu\n", sizeof(short));
printf("int: %zu\n", sizeof(int));
printf("long: %zu\n", sizeof(long));
printf("long long:%zu\n", sizeof(long long));
printf("float: %zu\n", sizeof(float));
printf("double: %zu\n", sizeof(double));
return 0;
}
/*输出结果如下:
char: 1
short: 2
int: 4
long: 4
long long:8
float: 4
double: 8
*/类型是用来创建变量(本质是向内存申请空间)
char ch = 'w';
int high = 200;
double price = 12.3;
- 有意义
- 必须由字母、数字或下划线组成,不能有特殊字符
- 不能以数字开头
- 不能和C语言内置关键字同名
局部变量
{ }内部定义的变量
全面变量
{ }外部定义的变量
举例
#include <stdio.h> int b = 2;//全局变量 int main() { short a = 1;//局部变量 return 0; }
当局部变量和全局变量命名相同时,局部优先
scanf 是一个输入函数
printf 是一个输出函数
#define _CRT_SECURE_NO_WARNINGS //VS中使用scanf时需要加入 #include <stdio.h> int main() { int num1 = 0; int num2 = 0;//初始化 //输入两个整数 scanf("%d %d",&num1,&num2); //求和 int sum = num1 + num2; //输出 printf("%d\n",sum); return 0; }
scanf_s是VS编译器中的非标准C函数
局部变量的作用域
局部变量所在的局部范围
全局变量的作用域
整个工程
extern---->声明来自外部的变量eg :
extern int a;
局部变量的生命周期
进入作用域生命周期开始,出作用域生命周期结束
#include <stdio.h> int main() { {//----------------------------|----生命周期开始 int a = 10; printf("%d\n", a); } //----------------------------|----生命周期结束 printf("%d\n",a); return 0; }全局变量的生命周期
整个程序的生命周期
字面常量
例如:
10; //字面常量 3.14; //字面常量 'w'; //字符常量 'abc';//字符串常量const修饰的常变量
在C语言中,
const修饰的a,本质是变量,但不能被修改,具有常量的属性#include <stdio.h> int main() { const int a = 10;//----------------------此处的a不能被修改 a = 20;//------------err-此句无效,此处的变量a无法修改 printf("%d",a); return 0; }
const相当于锁定了整个变量,使其不能再变化define定义的标识符常量
#include <stdio.h> #define MAX 100 int main() { printf("%d\n", MAX); int a = MAX; printf("%d\n", a); return 0; }枚举常量
#include <stdio.h> //枚举常量 enum Color { RED,GREEN,BLUE }; int main() { //三原色 //RED,GREEN,BLUE enum Color c = RED; RED = 10;//-----------------------err-枚举常量不能修改 return 0; }
char字符类型用
''包裹的为字符用
" "包裹的为字符串eg :
定义数组
char arr1[]="abcdef";//占用7个字节⭐ 在字符串末尾会自动加上
\0作于结束标志(限char型数组)
printf("%d\n", arr1);结果为abcdef定义数组
char arr2[] = {'a','b','c','d','e','f'};//占用6个字节
printf("%d\n", arr2);结果为abcdef烫烫烫烫烫烫烫烫烫烫烫狓oa?只有当程序遇到
\0才会结束打印char arr2[] = {'a','b','c','d','e','f','\0'};在数组末尾加上一个
\0,打印的结果才为abcdef
strlen()该函数可返回字符串长度 (string length) , 包含在头文件 string.h中
#include <stdio.h>
#include <string.h>
int main()
{
char arr1[] = "abcdef";//7(以\0结尾)
char arr2[] = {'a','b','c','d','e','f'};//6
printf("%d\n", strlen(arr1));//打印arr1的长度
printf("%d\n", strlen(arr2));//打印arr2的长度
return 0;
}运行结果 : arr1:6 arr2:33--->由于arr2[ ]后没有停止标志位
\0,因此打印出数组的长度为随机值
若改为
char arr2[] = {'a','b','c','d','e','f','\0};后:arr2:6若改为
char arr2[10] = {'a','b','c','d','e','f'};数组中多出的位将会用 0 来填充,此时:arr2的长度为6
- C99标准之前,数组的大小都是用常量或者常量表达式来指定
int arr1[10]={0}; int arr2[3+7]={1,2,3,4};
- C99标准之后,支持变长数组,此时允许数组的大小是变量,这种指定方式的数组不能初始化
int a = 10; int arr1[a];VS不支持C99标准
\转义序列符
转义字符 释义 ? 在连续书写多个问号时使用,防止它们被解析成三字母词 \` 用于表示字符常量 \" 用于表示一个字符串内部的双引号 \\ 用于表示一个反斜杠,防止它们被解释成为一个转义序列符 \a 警告字符,蜂鸣 \b 退格符 \f 进纸符 \n 换行 \r 回车 \t 水平制表符 \v 垂直制表符 \ddd ddd表示1~3个八进制的数字。如:\130--->X \xdd dd表示2个十六进制数字。如:\x30--->0
- 转义字符只占一个字符
- 三字母词:
??)会在某些编译器中解析成]- \ddd - 八进制转十进制后的ASCII码值
- \xdd - 该十六进制的所代表的ASCII码值
[转到表尾](#### %x)
| 二进制 | 十进制 | 十六进制 | 字符/缩写 | 解释 |
|---|---|---|---|---|
| 0 | 0 | 00 | NUL (NULL) | 空字符 |
| 1 | 1 | 01 | SOH (Start Of Headling) | 标题开始 |
| 10 | 2 | 02 | STX (Start Of Text) | 正文开始 |
| 11 | 3 | 03 | ETX (End Of Text) | 正文结束 |
| 100 | 4 | 04 | EOT (End Of Transmission) | 传输结束 |
| 101 | 5 | 05 | ENQ (Enquiry) | 请求 |
| 110 | 6 | 06 | ACK (Acknowledge) | 回应/响应/收到通知 |
| 111 | 7 | 07 | BEL (Bell) | 响铃 |
| 1000 | 8 | 08 | BS (Backspace) | 退格 |
| 1001 | 9 | 09 | HT (Horizontal Tab) | 水平制表符 |
| 1010 | 10 | 0A | LF/NL(Line Feed/New Line) | 换行键 |
| 1011 | 11 | 0B | VT (Vertical Tab) | 垂直制表符 |
| 1100 | 12 | 0C | FF/NP (Form Feed/New Page) | 换页键 |
| 1101 | 13 | 0D | CR (Carriage Return) | 回车键 |
| 1110 | 14 | 0E | SO (Shift Out) | 不用切换 |
| 1111 | 15 | 0F | SI (Shift In) | 启用切换 |
| 10000 | 16 | 10 | DLE (Data Link Escape) | 数据链路转义 |
| 10001 | 17 | 11 | DC1/XON(Device Control 1/Transmission On) | 设备控制1/传输开始 |
| 10010 | 18 | 12 | DC2 (Device Control 2) | 设备控制2 |
| 10011 | 19 | 13 | DC3/XOFF(Device Control 3/Transmission Off) | 设备控制3/传输中断 |
| 10100 | 20 | 14 | DC4 (Device Control 4) | 设备控制4 |
| 10101 | 21 | 15 | NAK (Negative Acknowledge) | 无响应/非正常响应/拒绝接收 |
| 10110 | 22 | 16 | SYN (Synchronous Idle) | 同步空闲 |
| 10111 | 23 | 17 | ETB (End of Transmission Block) | 传输块结束/块传输终止 |
| 11000 | 24 | 18 | CAN (Cancel) | 取消 |
| 11001 | 25 | 19 | EM (End of Medium) | 已到介质末端/介质存储已满/介质中断 |
| 11010 | 26 | 1A | SUB (Substitute) | 替补/替换 |
| 11011 | 27 | 1B | ESC (Escape) | 逃离/取消 |
| 11100 | 28 | 1C | FS (File Separator) | 文件分割符 |
| 11101 | 29 | 1D | GS (Group Separator) | 组分隔符/分组符 |
| 11110 | 30 | 1E | RS (Record Separator) | 记录分离符 |
| 11111 | 31 | 1F | US (Unit Separator) | 单元分隔符 |
| 100000 | 32 | 20 | (Space) | 空格 |
| 100001 | 33 | 21 | ! | |
| 100010 | 34 | 22 | " | |
| 100011 | 35 | 23 | # | |
| 100100 | 36 | 24 | $ | |
| 100101 | 37 | 25 | % | |
| 100110 | 38 | 26 | & | |
| 100111 | 39 | 27 | ' | |
| 101000 | 40 | 28 | ( | |
| 101001 | 41 | 29 | ) | |
| 101010 | 42 | 2A | * | |
| 101011 | 43 | 2B | + | |
| 101100 | 44 | 2C | , | |
| 101101 | 45 | 2D | - | |
| 101110 | 46 | 2E | . | |
| 101111 | 47 | 2F | / | |
| 110000 | 48 | 30 | 0 | |
| 110001 | 49 | 31 | 1 | |
| 110010 | 50 | 32 | 2 | |
| 110011 | 51 | 33 | 3 | |
| 110100 | 52 | 34 | 4 | |
| 110101 | 53 | 35 | 5 | |
| 110110 | 54 | 36 | 6 | |
| 110111 | 55 | 37 | 7 | |
| 111000 | 56 | 38 | 8 | |
| 111001 | 57 | 39 | 9 | |
| 111010 | 58 | 3A | : | |
| 111011 | 59 | 3B | ; | |
| 111100 | 60 | 3C | < | |
| 111101 | 61 | 3D | = | |
| 111110 | 62 | 3E | > | |
| 111111 | 63 | 3F | ? | |
| 1000000 | 64 | 40 | @ | |
| 1000001 | 65 | 41 | A | |
| 1000010 | 66 | 42 | B | |
| 1000011 | 67 | 43 | C | |
| 1000100 | 68 | 44 | D | |
| 1000101 | 69 | 45 | E | |
| 1000110 | 70 | 46 | F | |
| 1000111 | 71 | 47 | G | |
| 1001000 | 72 | 48 | H | |
| 1001001 | 73 | 49 | I | |
| 1001010 | 74 | 4A | J | |
| 1001011 | 75 | 4B | K | |
| 1001100 | 76 | 4C | L | |
| 1001101 | 77 | 4D | M | |
| 1001110 | 78 | 4E | N | |
| 1001111 | 79 | 4F | O | |
| 1010000 | 80 | 50 | P | |
| 1010001 | 81 | 51 | Q | |
| 1010010 | 82 | 52 | R | |
| 1010011 | 83 | 53 | S | |
| 1010100 | 84 | 54 | T | |
| 1010101 | 85 | 55 | U | |
| 1010110 | 86 | 56 | V | |
| 1010111 | 87 | 57 | W | |
| 1011000 | 88 | 58 | X | |
| 1011001 | 89 | 59 | Y | |
| 1011010 | 90 | 5A | Z | |
| 1011011 | 91 | 5B | [ | |
| 1011100 | 92 | 5C | \ | |
| 1011101 | 93 | 5D | ] | |
| 1011110 | 94 | 5E | ^ | |
| 1011111 | 95 | 5F | _ | |
| 1100000 | 96 | 60 | ` | |
| 1100001 | 97 | 61 | a | |
| 1100010 | 98 | 62 | b | |
| 1100011 | 99 | 63 | c | |
| 1100100 | 100 | 64 | d | |
| 1100101 | 101 | 65 | e | |
| 1100110 | 102 | 66 | f | |
| 1100111 | 103 | 67 | g | |
| 1101000 | 104 | 68 | h | |
| 1101001 | 105 | 69 | i | |
| 1101010 | 106 | 6A | j | |
| 1101011 | 107 | 6B | k | |
| 1101100 | 108 | 6C | l | |
| 1101101 | 109 | 6D | m | |
| 1101110 | 110 | 6E | n | |
| 1101111 | 111 | 6F | o | |
| 1110000 | 112 | 70 | p | |
| 1110001 | 113 | 71 | q | |
| 1110010 | 114 | 72 | r | |
| 1110011 | 115 | 73 | s | |
| 1110100 | 116 | 74 | t | |
| 1110101 | 117 | 75 | u | |
| 1110110 | 118 | 76 | v | |
| 1110111 | 119 | 77 | w | |
| 1111000 | 120 | 78 | x | |
| 1111001 | 121 | 79 | y | |
| 1111010 | 122 | 7A | z | |
| 1111011 | 123 | 7B | { | |
| 1111100 | 124 | 7C | ||
| 1111101 | 125 | 7D | } | |
| 1111110 | 126 | 7E | ~ | |
| 1111111 | 127 | 7F | DEL (Delete) | 删除 |
[转到表头](### ASCII码表)
| %x | 含义 |
|---|---|
%d |
打印整形 |
%c |
打印字符 |
%s |
打印字符串 |
%f |
打印float类型的数据 |
%lf |
打印double类型的数据 |
%p |
打印地址 |
C语言的注释风格
/**//* 这是注释 */不支持嵌套注释
C++的注释风格
////这是注释
-
语句结构
if(逻辑表达式) { 语句体1; } else { 语句体2; }
**解释:**如果逻辑表达式成立,就执行语句体1;否则,执行语句体2(else可以省略)
-
应用举例
if else语句#include <stdio.h> int main(void) { int choose = 0; printf("是否将开关打开(0/1):"); scanf("%d", &choose); if (choose == 1) { printf("打开\n"); } else if(choose == 0) { printf("关闭\n"); } else { printf("错误输入\n"); } return 0; }if(表达式) { 语句列表; }
- 如果表达式的结果为真,则语句执行
- 0表示假,非0表示为真
if else(表达式) { 语句列表; }
if else语句,是紧接在if语句后的带有选择条件的else语句- 如果表达式的结果为真,则语句执行
else { 语句列表; }
- 一般位于
if else语句的最后,作用于其它未被选择的条件,类似于集合与其补集的关系else遵循就近原则,即else与离其最近的if匹配
例1:if语句实现判断奇偶数
int main() { while(1) { int num = 0; printf("输入一个数:"); scanf("%d", &num); if (num % 2 == 1) printf("%d为奇数\n", num); else printf("%d为偶数\n", num); } return 0; }
输出结果
输入一个数:1 1为奇数 输入一个数:12 12为偶数 输入一个数:123 123为奇数
例2:if语句输出1-100之间的奇数
//定义一个可返回奇数的函数 int Retu_J(int Num) { if (1 == Num % 2) { return Num; } else return 0; } int main() { int i = 0; int num = 0; while (i <= 100) { num = Retu_J(i); if (num) { printf("%d ", num); } i++; } return 0; }
输出结果
1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 此处运用了外部函数的调用来实现函数功能,当然除此之外还有更加简便的写法,此处不过多赘述。
switch语句也是一种分支语句,但通常用于多分支的情况。
-
语句结构
switch(整形变量) { case 常量1 : 语句体1 ; break; case 常量2 : 语句体2 ; break; ...... default : 语句体x ; break; }
**含义:**将变量与case后的各个常量对比,若有相等,则执行相应的语句;若全不等,则执行
default后面的语句。 -
switch应用举例int main() { int day; while (1) { scanf("%d", &day); switch (day) { case 1:printf("星期一\n"); break; case 2:printf("星期二\n"); break; case 3:printf("星期三\n"); break; case 4:printf("星期四\n"); break; case 5:printf("星期五\n"); break; case 6:printf("星期六\n"); break; case 7:printf("星期七\n"); break; default : printf("没有这一天\n"); break; } } return 0; }
- 输出结果:
5 星期五 6 星期六 9 没有这一天
-
switch应用举例:case穿透使用switch实现的代码功能:
当输入1~5时,输出工作日;
当输入6~7时,输出周末;
int main() { int day = 1; while(1) { scanf("%d", &day); switch (day) { case 1: case 2: case 3: case 4: case 5: printf("工作日\n"); break; case 6: case 7: printf("周末\n"); break; default: printf("输入错误\n"); break; } } return 0; }
- 输出结果:
1 工作日 6 周末 9 输入错误
case穿透可以实现多个case匹配同一个执行语句
-
语句结构
while(逻辑表达式) { 循环体; }
**解释:**如果逻辑表达式成立,则执行循环体,执行后再次判断,直至不成立时才停止执行。
-
while应用举例*代码实现功能:*打印数字1~10;
int main() { int a = 1; while (a <= 10) { printf("%d ", a); a++; } return 0; }
输出结果:
1 2 3 4 5 6 7 8 9 10
-
break中止while循环break可以永久的中止整个循环int main() { int a = 1; while (a <= 10) { if (5 == a) break;//此代码执行时,会直接跳出while循环 printf("%d ", a); a++; } return 0; }
- 输出结果:
1 2 3 4
-
continue跳过本次while循环continue被执行时,会跳过continue后面的语句(结束本次循环),直接去判断部分,进行下一次循环的判断int main() { int a = 0; while (a <= 9) { a++; if (5 == a) continue; printf("%d ", a); } return 0; }
因此在a=5时,continue被执行,程序将直接结束本次循环,开始下一次循环,故而等于5时的a没有被打印
- 输出结果:
1 2 3 4 6 7 8 9 10//输出结果中的5被直接跳过
while循环#include <stdio.h> int main() { int count = 0; printf("开始:\n"); while (count <= 1000) { printf("计数:%d\n",count); count++; } if (count > 1000) { printf("END\n"); } else printf("Lost\n"); return 0; }
for循环
do ... while循环
C语言是结构化的程序设计语言
- 顺序结构
- 选择结构
- 循环结构
求任意两个数的和 ( 函数的调用 )
#include <stdio.h> /************************************************ **函数名:Add **参数: 整形变量a,b **返回值:求和a+b=s **作用: 将a+b的值返回 */ int Add(int a, int b) { return (a + b); } int main() { int X = 1; int Y = 1; scanf("%d %d", &X, &Y); int sum = Add(X, Y); printf("和为:%d", sum); return 0; }
举例 : 定义一个数组
int arr[10] = {10,11,12,13,14,15,16,17,18,19}; // 数组的下标 0 1 2 3 4 5 6 7 8 9
数组里可以放置一系列相同类型的元素
C语言规定:数组的每个元素都有下标,且数组的下标都是从0开始
可以通过下标来访问数组中的元素
---->arr[7] = 17通过
while循环来打印数组中的元素int main() { int arr[10] = { 10,11,12,13,14,15,16,17,18,19 }; int i = 0; while (i < 10) { printf("%d ", arr[i]); i++; } return 0; }
/除
- 除号两端都是整数时执行的是整数除法
int a = 7 / 2; | \|/ printf("%d\n", a);//结果:a = 3
- 除号两端有一个浮点数,就会执行浮点数的除法
float a = 7 / 2.0;//两端需要有一个位小数 | \|/ printf("%.2f\n", a);//结果:a = 3.50 【%f-->表示输出浮点数;.x就保留x位小数,默认保留7位小数】
%取模取模操作符两端必须为整数
int b = 7 % 2; | \|/ printf("%d\n", b);//结果:a = 1
<<左移操作符.
>>右移操作符.
&按位与.
|按位或.
^按位异或.
| 运算符 | 描述 | 实例 |
|---|---|---|
= |
简单的赋值运算符,把右边操作数的值赋给左边操作数 | 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 |
| ` | =` | 按位或且赋值运算符 |
对于赋值操作符
=int a = 0;//初始化 a = 10; //赋值
| 运算符 | 描述 | 实例 |
|---|---|---|
! |
逻辑反操作(0假1真) | a = 10 ; !a = -10 |
- |
负值 | a = -10 |
+ |
正值 | a = +10(+可省略) |
& |
取地址 | &a; 将给出变量的实际地址 |
⭐sizeof() |
返回变量的长度 | sizeof(int) 将返回 4,其中 a 是整数 |
~ |
对一个数的二进制位按位取反 | ~0 = 1 |
-- |
自减 | *前置--:*先--,后使用 |
++ |
自增 | *后置++:*先使用,后-- |
* |
间接访问操作符(解引用) | *p(指针变量解引用) |
(类型) |
强制类型转换 | c = a+(int)b |
-
sizeof是操作符int a = 10; printf("%d\n", sizeof(a)); //4 printf("%d\n", sizeof(int));//4 printf("%d\n", sizeof a); //4--->a的括号可省,间接说明sizeof是操作符
int arr[ 10 ] = { 0 }; printf("%d\n", sizeof(arr));//40--->计算的是整个数组的大小,单位是字节 printf("%d\n", sizeof(arr[0]));//4->计算的是数组中元素的大小,单位是字节 printf("%d\n", sizeof(arr)/sizeof(arr[0]));//10
🌔注意区分int型数组与char型数组
-
++自增操作符int main() { int a = 10; int b = a++;//先使用,再++ printf("%d\n", a);//11 printf("%d\n", b);//10 return 0; }
int main() { int a = 10; int b = ++a;//先++,再使用 printf("%d\n", a);//11 printf("%d\n", b);//11 return 0; }
-
(类型)强制类型转换int a = 3.14; //3.14字面浮点数,编译器默认理解为double类型
int a = (int)3.14; //将3.14强制转换为int类型,自动舍去小数点后的数值
| 操作符 | 描述 |
|---|---|
> |
大于 |
>= |
大于或等于 |
< |
小于 |
<= |
小于或等于 |
!= |
不等于 |
== |
等于(区别于赋值=) |
-
&&逻辑与(并且)-
全真才为真(有假则假)
eg:成绩分类
int main() { int scores; while(1) { printf("输入成绩:"); scanf("%d", &scores); //只有scores满足逻辑与符号(&&)前后的所有条件,程序才会向下执行 if (scores >= 60 && scores <= 90) { printf("合格\n"); } else if (scores < 60)printf("不及格\n"); else if (scores > 90 && scores <=100)printf("优秀\n"); else printf("输入错误\n"); } return 0; }
程序运行结果:
输入成绩:56 不及格 输入成绩:78 合格 输入成绩:95 优秀 输入成绩:123 输入错误
-
-
||逻辑或(或者)-
全假才为假(有真则真)
eg:区分1~9内的质数
int main() { int num; while (1) { printf("输入1-9:"); scanf("%d", &num); //num只需满足逻辑或符号(||)前后的任一条件,程序就会向下执行 if (num == 2 || num == 3 || num == 5 || num == 7) { printf("%d 是质数\n", num); } else { printf("%d 不是质数\n", num); } } return 0; }
程序运行结果:
输入1-9:1 1 不是质数 输入1-9:2 2 是质数
-
三目操作符:有三个操作数(可以嵌套)
Exp1 ? Exp2 : Exp3
Exp1 |
Exp2 |
Exp3 |
|---|---|---|
| 真 | √ | × |
| 假 | × | √ |
int a = 10;
int b = 20;
int c = a > b ? a : b;//输出b=20a > b ? a : b该句句意为:判断a>b是否成立,如果成立,则输出a,反之输出b
即用逗号
,隔开的一串表达式自左向右依次计算,整个表达式的结果是最后一个表达式的结果
int a = 10; int b = 20; int c = 30; //........15.......50.......65.... int d = (a = a+5, b = b+c, a + b); printf("%d\n", d);//此时d的值为65
-
[]下标引用操作符-
访问数组元素时,需要用到下标引用操作符
int arr[3] = {12,23,34}; a = arr[1]; //a的值为23
arr[1]中,[ ]就是下标引用操作符,arr和1就是[ ]的操作数
注意: 数组中的元素下标是从0开始
-
给数组中的元素赋值时,也是如此
int arr[3] = {12,23,34}; arr[1] = 66; //此时数组元素中的23被重新赋值为66
-
-
()函数调用操作符int Sum(int x,int y) { return x+y; } int main() { int s = Sum(2,3);//此处的()就是函数调用操作符,Sum、2、3都是()的操作数 return 0; }
-
.操作符结构体对象
.成员名 -
->操作符结构体的指针变量
->成员名
关键字---C语言本身内置,用户无法创建
auto
所有的局部变量前都会加上auto
int main() { int a = 10;//***************************** return 0; }等效于
int main() { auto int a = 10;//************************ return 0; }也因此,局部变量在开始时会创建,结束时会自动销毁
循环语句
forwhiledo whilebreak
- 用于跳出循环
- 常与for、while、do while、switch搭配使用
continue分支语句
if else
switch
case
default
go to内置类型
char
int
short
long
float
double
signed- 有符号
unsigned- 无符号... ...
自定义类型
enum- 枚举struct- 结构体union- 联合体(共用体)
const
- 常属性
- 用于修饰变量,不能被修改
register- 寄存器
extern
- 用于声明外部符号
static
在C语言中,static可以用来修饰变量或函数
修饰局部变量(改变存储位置)
int add() { int a = 1; printf("%d ", a); a++; } int main() { int i = 0; while (i < 10) { add(); i++; } return 0; }以上代码的输出结果为:
1 1 1 1 1 1 1 1 1 1
- 这是由于局部变量只会在其进入作用域时创建,出作用域时销毁。在主函数每次循环时,函数
add()始终处于刚刚创建的状态,因此每次打印出的a的值都为1使用static来修饰a,使其成为静态变量
int add() { static int a = 1;//静态变量在出作用域时不销毁,每次循环延续使用上次a的值 printf("%d ", a); a++; } int main() { int i = 0; while (i < 10) { add(); i++; } return 0; }此时,代码的运行结果为:
1 2 3 4 5 6 7 8 9 10
通过static修饰的局部变量,出了作用域,不会被销毁。
本质上,static修饰局部变量的时候,改变了变量的存储位置(由栈区变为静态区)。同时延长了变量的生命周期,使其变得和程序的生命周期一样长。
修饰全局变量(改变全局变量的链接属性)
- 全局变量具有外部链接属性,static修饰全局变量时,该全局变量的外部链接属性就变成了内部链接属性。其它源文件就不能再通过extern来使用这个全局变量
text.c
#define _CRT_SECURE_NO_WARNINGS //全局变量--->全局变量具有外部链接属性 //int number = 1234; static int number = 1234; //此时的全局变量number只具有内部连接属性main.c
extern int number; int main() { printf("%d\n", number); return 0; }
- 此时就无法使用extern int number;来声明外部变量number
修饰函数(改变函数的链接属性)
类似于修饰全局变量,函数同样具有外部链接属性,static修饰函数时,该函数的外部链接属性就变成了内部链接属性。其它源文件就不能再通过extern来使用这个函数
text.c
//此时在main.c中可以通过extern外部调用Add函数 int Add(int x, int y)//具有外部链接属性 { return x + y; } //***************************************** //用static修饰的函数Add,无法在main.c中使用 static int Add(int x, int y)//仅具有内部连接属性 { return x + y; }main.c
extern int Add(int x, int y); int main() { int a = 10; int b = 20; int c = Add(a, b); printf("%d\n", c); return 0; }
return
- 函数返回值
sizeof
计算大小(字符或字符串长度)
int main() { int a = 10; char b = 20; double c = 30; printf("%d\n", sizeof a);//8 printf("%d\n", sizeof b);//1 printf("%d\n", sizeof c);//4 return 0; }
sizeof是根据所定义变量的类型,从而计算出变量的大小,例如:int型变量a的大小为4;char型变量b的大小为1;double型变量c的大小为8
typedef
类型定于(类型重命名)
可以用于简化一些复杂的类型
typedef unsigned int uint; //将unsigned int重定义为uint typedef unsigned char uchar; //将unsigned char重定义为uchar简化结构体的名称:
typedef struct Node { int data; struct Node* next; }Node; int main() { struct Node b; Node a; return 0; }
void
- 无
- 常用于函数的返回类型,函数的参数
volatile
#define
定义常量和宏
定义常量
#define Sum 100 //此时的Sum等效于常量100定义宏
#define ADD(x,y) ((x)+(y)) //ADD--------->宏名 //(x,y)------->宏的参数(参数为无类型) //((x)+(y))--->宏体 int main() { int a = 10; int b = 20; int c = ADD(a, b);//进行宏替换后的结果为((a)+(b)) printf("%d\n", c); return 0; }ADD--------->宏名 (x,y)------->宏的参数(参数为无类型) ((x)+(y))--->宏体注:
define不是关键字,而是预处理指令
- 指针变量用于存放地址
在计算机中,内存会划分为一个个的内存单元(一个内存单元的大小为:1byte)
每个内存单元都有一个编号
在32位的电脑中,有32根地址线
00000000 00000000 00000000 00000000 -->0 00000000 00000000 00000000 00000001 -->1 00000000 00000000 00000000 00000010 -->2 00000000 00000000 00000000 00000011 -->3 ... ... 11111111 11111111 11111111 11111111 -->4,294,967,295$ 2^{32}=4,294,967,295(Byte) $ 个地址序列 $$ \begin{aligned} 2^{32} &=4,294,967,295(Byte)\ &=4,194,304(Kb)\ &=4096(Mb)\ &=4(Gb) \end{aligned} $$
int main() { int a = 11;//向内存申请4个字节,存储11 printf("%p\n", &a);//%p取地址操作符 return 0; }
相较于64位的系统,在VS中监视变量a的存储过程
\C语言程序设计\源码\画图\0000000b.png)
a存放的地址:
在内存中a的数据为
0x00000005B9CFFBA4 0b 00 00 00 .... ^^ ^^ ^^ ^^ || || || || A4 A5 A6 A7若要存储a的地址:
int* p = &a; printf("%p\n", &a);//%p用于打印变量地址此时的p就是指针变量
int* p = &a; int--->说明p指向的对象是int类型的 * --->说明p是指针变量
内存单元
编号--->地址--->地址也被称为指针
因此存放指针(地址)的变量就是指针变量
int main() { int a = 11; int* p = &a; *p = 20;//解引用操作符,意思就是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象 printf("%d\n", a);//20 return 0; }
- ⭐*p = 20;
- *p为解引用操作符,意思就是通过p中存放的地址,找到p所指向的对象,*p就是p指向的对象(此处的p指向的对象是a)
//x64的环境下 int main() { printf("%zd\n", sizeof(char*)); //8 printf("%zd\n", sizeof(short*)); //8 printf("%zd\n", sizeof(int*)); //8 printf("%zd\n", sizeof(double*)); //8 return 0; }
- 指针变量是用来存放地址的
- 不管是什么类型的指针,都是在创建指针变量
- 指针变量的大小取决于系统存放一个地址需要多大的空间
- *32位(x86)*的系统上的地址:32bit - 4byte,所以此处指针变量的大小是4个字节
- *64位(x64)*的系统上的地址:64bit - 8byte,所以此处指针变量的大小是8个字节
指针与底层硬件(内存)联系紧密,使用指针可以操作数据的地址,实现数据的间接访问
-
指针即指针变量,用于存放其它数据单元(变量、数组、结构体、函数等)的首地址
-
若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元
-
若指针存放的值是0,则该指针为空指针
-
-
定义一个指针变量
数据类型 所占字节 指向该数据类型的指针 所占字节 (unsigned) char1字节 (unsigned) char *x字节(unsigned) short2字节 (unsigned) short *x字节(unsigned) int4字节 (unsigned) int *x字节(unsigned) long4字节 (unsigned) long *x字节float4字节 float *x字节double8字节 double *x字节-
16位系统
x= 2 -
32位系统
x= 4 -
64位系统
x= 8指针占用的位宽 = 系统的位宽
-
int a; |
定义一个int类型的数据 |
int *p; |
定义一个指向int类型数据的指针p |
-
对指针p有如下操作方式
操作方式 举例 解释 取地址 p = &a;将数据a的首地址赋给p 取内容 *p;取出指针指向的数据单元 加++ p++;使指针向下移动1个数据宽度 加 p = p+5;使指针向下移动5个数据宽度 减-- p--;使指针向上移动1个数据宽度 减 p = p-5;使指针向上移动5个数据宽度 *数据宽度:*int = 4 ; char = 1 ... ...
- 变量1
&变量2 ---> 按位与 -
&变量1 ---> 取地址
- 变量1
*变量2 ---> 相乘 -
*变量1 ---> 取内容(解引用) - int等数据类型
*---> 标识
- 变量1
-
数组是一些相同数据类型的变量组成的集合
-
数组名为指向该数据类型的指针
数组的定义等效于申请内存--->定义指针--->初始化
char a[] = {0x33,0x34,0x35};
-
申请内存
-
定义char *a = 0x4000
0x4000是数组*a[ ]*中元素的首地址
-
初始化数组数据
-
-
利用下标引用数组数据⇔指针取内容
数组数据 ⇔ 指针取内容 a[0]⇔ *aa[1]⇔ *(a+1)a[2]⇔ *(a+2) -
同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告
-
传递参数
- 使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用。
- 使用指针传递输出函数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计。
#include <stdio.h>
void Fun(int Temp)
{
printf("%x\n", Temp);
}
void main()
{
int a = 0x66;
Fun(a);
return 0;
}
- 优点 :主函数与子函数之间的数据隔离开,保证了数据的安全
- 缺点:数据重复,占用了更多的空间,降低了程序的运行效率
#include <stdio.h>
//找到数组中的最大值
//***************形参********
int FindMax(int* array, int length)
{
int Max = array[0];
int i;
for (i = 1; i < length; i++)
{
if (array[i] > Max)
{
Max = array[i];
}
}
return Max;
}
void main()
{
int a[] = { 5,6,9,7,8,1 };
int Max = 0;
//**********实参****
Max = FindMax(a, 6);
printf("Max=%d\n", Max);//9
return 0;
}#include <stdio.h>
//输出最大值及其出现的次数
void FindMaxAndCount(int* max, int* count, const int* array, int length)
//const----->只读
{
int i;
*max = array[0];
*count = 1;
for (i = 1; i < length; i++)
{
if (array[i] > *max)
{
*max = array[i];
*count = 1;
}
else if (array[i] == *max)
{
*count = *count + 1;
}
}
}
void main()
{
int a[] = { 8,8,6,8,1,3,8 };
int Max, Count;
FindMaxAndCount(&Max, &Count, a, 7);
printf("Max=%d\n", Max);
printf("Count=%d\n", Count);
return 0;
}-
-
数组复制:strcpy( _ , _ )
char str1[20]; char str2[] = "Hello"; strcpy(str1,str2);//将数组str2的值赋给数组str1
-
将模块内的共有部分返回,让主函数持有模块的“句柄”,便于程序对指定对象的操作
#include <stdio.h>
int A[] = { 21,76,49 };
int* GetA( )//返回值为int型指针
{
return A;
}
void main()
{
int* a;
a = GetA();
printf("A[0]=%d\n", a[0]);
printf("A[1]=%d\n", a[1]);
printf("A[2]=%d\n", *(a + 2));//有两种写法
}输出结果:
A[0]=21
A[1]=76
A[2]=49struct是结构体的关键字- 结构体是把复杂对象的单一类型整合在一起,例如:
- 长方体--->长,宽,高
- 学生------>姓名,学号,班级
//此时设定的结构体Studio相当于“图纸”,不占用内存空间
struct Student
{
char name[20];
int age;
char sex[10];
char Tel[20];
};
int main()
{
//用类型来创建变量,此时才给stu1分配了空间
struct Student stu1 = {"小明",20,"男","123456789"};
printf("姓名:%s\n年龄:%d\n性别:%s\n电话:%s\n", stu1.name, stu1.age, stu1.sex, stu1.Tel);
//结构体对象 . 成员名
return 0;
}输出的结果为:
姓名:小明 年龄:20 性别:男 电话:123456789
struct Student { char name[20]; int age; char sex[10]; char Tel[20]; };此时设定的结构体Student相当于*“图纸”*,不占用内存空间
而
struct Student stu1 = {"小明",20,"男","123456789"};是利用
struct Student类型来创建结构体变量stu1,相当于利用“图纸”来建“房子”,因此在创建变量stu1的同时分配了一定的系统空间。
结构体指针变量 -> 成员名
结构体对象 . 成员名
struct Student { char name[20]; int age; char tel[15]; }; void print(struct Student* p) { //结构体对象 . 成员名 printf("%s %d %s\n", (*p).name, (*p).age, (*p).tel); //结构体指针变量 -> 成员名 printf("%s %d %s\n", p->name, p->age, p->tel); } int main() { struct Student stu2 = { "李四",23,"123123123" }; print(&stu2); return 0; } //输出结果 李四 23 123123123 李四 23 123123123








