3.! 逻辑非
if(!(a>b))
{
}
2.3.6 位运算符
16进制 除16得余
10进制 除10得余
-数的原码等于正数的原码加个符号位1
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6IXIadxW-1649660664430)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220330215822663.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KAh6ckPT-1649660664430)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220330222009122.png)]
同一为一 ,有0为0.
按位与
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kZ4jHvEJ-1649660664431)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331101220336.png)]
两个都是0则结果为0.有一位为1 则结果为1.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cTBz1sIk-1649660664431)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331103149272.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fOiJzeEw-1649660664432)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331111304992.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V9JEDUXj-1649660664433)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331111334239.png)]
对于无符号数来说,补的就是0
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OYluGwdY-1649660664434)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331111533674.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1pPVF56W-1649660664434)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331112145450.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZgfRRKNa-1649660664435)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220330220106137.png)]
2.3.7 条件运算符号
三目运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-L4qTsmf6-1649660664436)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331113128233.png)]
2.3.8 逗号运算符
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QM7CeaXp-1649660664436)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331113444463.png)]
2.3.9 自增自减运算符
i++ i–
运算符在变量的后面,在当前表达式中先用i的值,下条语句的时候i 的值改变
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JInPg1r2-1649660664437)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331130542718.png)]
++i --i
在当前表达式中先用i自增后的值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-67IeoJOz-1649660664437)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331130440749.png)]
2.3.10 运算符优先级及结合性
运算符优先级
在表达式中按照优先级先后进行运算,优先级高的优于优先级低的先运算。
优先级一样的按结合性来运算
int a;
a =2+5+3*4-6
运算符结合性
左结合性:从左往右计算
int a;
a=2+3.+9+10;
右结合性:从左往右运算
int a,b,c,d;
a=b=c=d=100;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GOQt5bl7-1649660664438)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331131245656.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DPM0ZHbD-1649660664438)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331131430949.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1kaRIZLw-1649660664439)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331131513416.png)]
2.4 控制语句相关关键字讲解
2.4.1 控制语句相关的关键字
1、if语句
形式 :
if( 条件表达式)
{ //复合语句 ,若干条语句的集合
语句一:
语句二;
}
如果条件成立执行大括号里面的所有语句,不成立的话大括号里的语句不执行
2、
if(条件表达式)
{
}else{
}
if else 语句的作用是,如果if条件成立,执行if后面{}内的语句,否则执行 else 后的语句.
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZcCmH3zM-1649660664439)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331132649328.png)]
2.switch 语句
switch (表达式) //表达式只能是字符型或者整型的(short int int long int)
{
case 常量表达式1:
语句1;
break;
case 常量表达式2:
语句2;
break;
default: 语句3; break;
}
注意:break 的使用
2.4.2 循环控制语句
1、for()循环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-iLpR9fKV-1649660664440)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331151831680.png)]
// for (int i = 0; i < 5; i++)
// {
// if (i == 3)
// {
// printf("这个世界很奇妙\n");
// continue;
// };
// printf("i =%d\n", i);
// };
// return 0;
int sum = 0;
for (int i = 0; i <= 100; i++)
{
sum += i;
};
printf("1-100的和sum = %d", sum);
return 0;
循环嵌套
int i, j;
int sum = 0;
for (i = 1; i <= 9; i++)
{
for (j = 1; j <= i; j++)
{
printf("%d*%d=%d ", j, i, j * i);
};
printf("\n");
};
2、while 循环
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HjO4MICU-1649660664440)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331161036106.png)]
int i = 1;
int sum = 0;
while (i <= 100)
{
sum += i;
i++;
}
printf("sum=%d\n", sum);
return 0;
do{} while(); //至少执行一次
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UGlqdyxq-1649660664441)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331161408879.png)]
int i = 1;
int sum = 0;
do
{
sum += i;
i++;
} while (i <= 100);
printf("sum=%d\n", sum);
return 0;
对于循环来说
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DN4iJgQJ-1649660664441)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331161826494.png)]
3、goto
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BEBYaXx1-1649660664442)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331162134158.png)]
程序经量少使用goto
4.水仙花数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EiT83G1e-1649660664442)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331162241934.png)]
#include
int main()
{
int a, b, c;
int i;
for (i = 0; i <= 999; i++)
{
a = i / 100;
b = i % 100 / 10;
c = i % 10;
if (i == a * a * a + b * b * b + c * c * c)
{
printf("水仙花数为=%d", i);
};
};
return 0;
}
#include
int main()
{
int year, month, day;
int sum;
printf("please input year month day:\n");
scanf_s(" %d %d %d", &year, &month, &day);
switch (month)
{
case 1:
sum = day;
break;
case 2:
sum = 31 + day;
break;
case 3:
sum = 31 + 28 + day;
break;
case 4:
sum = 31 + 28 + 31 + day;
break;
case 5:
sum = 31 + 28 + 31 + 30 + day;
break;
case 6:
sum = 31 + 28 + 31 + 30 + 31 + day;
break;
case 7:
sum = 31 + 28 + 31 + 30 + 31 + 30 + day;
break;
case 8:
sum = 31 + 28 + 31 + 30 + 31 + 30 + 31 + day;
break;
case 9:
sum = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + day;
break;
case 10:
sum = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + day;
break;
case 11:
sum = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + day;
break;
case 12:
sum = 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + day;
break;
default:
sum = 0;
printf("你输入月份有误");
break;
}
if (month > 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
sum += 1;
}
printf("%d %d %d 是一年中的第%d 天\n", year, month, day, sum);
return 0;
}
3.数组
3.1数组的概念
数组是若干个相同类型的变量在内存中有序存储的集合。
int a[10]; //定义了一个整型的数组 a, a是数组的名字,数组中有10个元素,每个元素的类型都是 int 类型,而且在内存中连续存储。
这十个元素分别是a[0] a[1] … a[9]
a[0]~a[9]在内存中连续的顺序存储
3.2数组的分类
3.1.1按照元素的类型分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m3aZo3sV-1649660664443)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331172910862.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BfdrmL5Q-1649660664444)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331173159764.png)]
3.2.2 按维数分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ccDgTN3Y-1649660664444)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331173359170.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TeXmYZtY-1649660664445)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331173419099.png)]3.3数组的定义
定义一个数组,在内存里分配空间
3.3.1 一维数组的定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TIOVYigU-1649660664445)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331174540507.png)]
3.3.2 二维数组的定义
格式:
数据类型 数组名 [行的个数] [列的个数];
int a [4] [5];
定义了20个int 类型的变量 分别是
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aiCUi4W7-1649660664446)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220331180506119.png)]
因为一个整数占4个字节 可以按照这样计算
二维数组可以不指定行数,但是必须指定列数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7lpGEwRB-1649660664447)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401093931210.png)]
3.4数组的初始化
定义数组的时候,顺便给数组的元素赋初值,及开辟的内存空间同时并且给元素赋值。
3.4.1一维数组的初始化
a 、 全部初始化
int a[5] = {2,4,7,8,5};
b 、 部分初始化
int a[5] = {2,4,3};初始化赋值不够后面补0
a[0] = 2 a[1] = 4 a[2] =3 a[4] =0 a[5] =0
注意:只能省略后面的元素,可以不初始化,不能中间的不初始化。
3.4.2 二维数组的定义并初始化
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nYybKbXP-1649660664447)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401094452739.png)]
#include
int main()
{
int a[2][2] = {{1, 2}, {4, 5}};
int b[3][3] = {
{1, 2},
{9, 8}};
int i, j;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 2; j++)
{
printf("a[%d][%d]=%d ", i, j, a[i][j]);
};
};
for (i = 0; i < 3; i++)
{
for (j = 0; j < 3; j++)
{
printf("a[%d][%d]=%d ", i, j, b[i][j]);
};
printf("\n");
};
return 0;
}
#include
int main()
{
int a[2][3] = {2, 2, 4, 4, 5, 6};
int i, j;
for (i = 0; i < 2; i++)
{
for (j = 0; j < 3; j++)
{
printf("a[%d][%d]=%d", i, j, a[i][j]);
};
printf("\n");
};
}
3.5数组元素的引用方法
3.5.1 一维数组元素的引用方法
数组名[下标]; //下标代表数组元素在数组中的位置
int a[5];
3.5.2 二维数组元素的引用方法
数组名[行下标] [列下标]
int a [4] [5]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-y8vKuj7W-1649660664448)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401100950995.png)]
3.5.3 字符数组
char c1[] = {‘c’,‘a’,‘g’,‘r’};
char c2[] = “c prog”;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-et9IrVqY-1649660664448)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401102245644.png)]
[数组是若干个相同类型变量的集合][]
两道练手题
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HV98oiTq-1649660664448)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401112245495.png)]
#include
int main()
{
int i;
int sum = 0;
int year, month, day;
int buf[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
printf("please input year month day\n");
scanf_s("%d %d %d", &year, &month, &day);
if (day >= 30 || day < 1)
{
printf("你输入的信息有误");
}
else
{
for (i = 0; i < month - 1; i++)
{
sum += buf[i];
}
sum += day;
if (month > 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
{
sum += 1;
}
printf("sum=%d\n", sum);
}
return 0;
}
打字游戏
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4nmB995c-1649660664449)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401131148819.png)]
#include
#include
#include
void help(void)
{
printf("\n******************************************");
printf("\n* 输入过程中无法退出! *");
printf("\n* 请按住所给字母敲击键盘! *");
printf("\n* 请按任意键开始测试,按下首字母时候开始计时!");
printf("\n* 输入错误则以_表示 ");
printf("\n******************************************\n\n");
}
int main()
{
char ch;
char str[51] = "";
int i;
int count;
time_t start_time, end_time;
while (1)
{
system("cls");
help();
ch = _getch();
srand(time(NULL));
for (i = 0; i < 50; i++)
{
str[i] = rand() % 26 + 'a';
}
str[50] = "\0";
printf("%s\n", str);
count = 0;
for (i = 0; i < 50; i++)
{
ch = _getch();
if (i == 0)
{
start_time = time(NULL);
}
if (ch == str[i])
{
count++;
printf("%c", ch);
}
else
{
printf("_");
}
}
end_time = time(NULL);
printf("\n正确率: %d%%\n", count * 100 / 50);
printf("用时%d秒", (long int)end_time - start_time);
while (1)
{
ch = _getch();
if (ch == ' ')
{
break;
}
if (ch == 27)
{
return 0;
}
}
}
return 0;
}
4.函数
4.1函数的概念
函数是c语言的功能单位,实现一个功能可以封装一个函数来实现。
定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值。
4.2函数的分类
1、从定义的角度分类(即函数是谁实现的)
- 库函数(c库实现的)
- 自定义函数(程序员自己实现的函数)
- 系统调用
2、从参数角度分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7QzEGTfq-1649660664449)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401141601267.png)]
3 、从返回值的角度分类
1.带返回值的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GGJc1oAs-1649660664450)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401142237504.png)]
2.没有返回值的函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-PmDH8tQN-1649660664450)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220401144514427.png)]
4.3函数的定义
什么叫做函数的定义呢?即函数的实现
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-61NS3hK7-1649660664450)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402095635167.png)]
不能再函数体内定义另一个函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eOw6p5hx-1649660664451)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402095940734.png)]
4.4函数的声明
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4kz3tgEL-1649660664451)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402101003626.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B52kLNzI-1649660664452)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402101442600.png)]
声明就是在一个函数中调用另一个函数
1.直接声明法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nVxLDqOF-1649660664452)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402101510543.png)]
#include //这种类型是C库文件的声明
#include “4_3.h” //是对程序员创建的程序的声明
2.间接声明法
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-t6jGkYGQ-1649660664452)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402101907638.png)]
3.分文件声明法
将函数都写在一个.c中,使用头文件.h来进行声明,然后再其他文件中就可以直接使用了。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T7ZFG7pX-1649660664453)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402103034664.png)]
4.5 函数的调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N4Fpe71r-1649660664453)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402103315924.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JVIwclJ4-1649660664454)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402103508303.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RtmHhF67-1649660664454)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220402103410739.png)]
4.6函数的总结
在定义函数的时候 ,关于函数的参数和返回值是什么情况,完全取决于函数的功能。
使用函数的好处?
1、定义一次,可以多次调用,减少代码的冗余度。
2、使咱们的代码,模块化更好,方便程序调试,而且阅读方便。
递归函数
#include
int fun(int x){
int p;
if(x==0||x==1)p=3;
else p=x-fun(x-2);
return p;
}
int main(int argc, char const *argv[])
{
printf("%d\n",fun(12));
return 0;
}
4.7 变量的存储类别
4.7.1 内存的分区:
1、内存:物理内存、虚拟内存
物理内存:实实在在存在的存储设备
虚拟内存:操作系统虚拟出来的内存
操作系统会在物理内存和虚拟内存之间做映射。
在32位平台下,每个进程的寻址范围是4G,0x00 00 00 00 -0xff ff ff ff
在写应用程序,咱们看到的都是虚拟地址。
2、在运行程序的时候,操作系统会将 虚拟内存进行分区。
-
堆
在动态申请内存的时候,在堆中开辟内存。
-
栈
主要存放局部变量。
-
静态全局区
-
未初始化的静态全局区
静态变量(定义变量的时候,前面加static修饰),或全局变量,没有初始化的,存在此区
-
初始化的静态全局区
全局变量、静态变量、赋过初值的,存放此区
-
代码区
存放咱们的代码。
-
文字常量区
存放常量的。
4.7.2 普通的全局变量
概念:
在函数外部定义的变量
int num =100; //num 就是一个全局变量
int main(){
return 0;
}
作用范围:
全局变量的作用范围,是程序所有地方。
只不过用之前需要声明。声明方法 extern int num;
注意声明的时候,不要赋值。
生命周期:
程序运行的整个过程,一直存在,直到程序结束。
注意:定义普通的全局变量的时候,如果不赋初值,它的默认值为0
4.7.3 静态的全局变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6E6fWh55-1649660664454)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403164550691.png)]
#include
void fun(void) {
static int num = 3;
int num1 = 4;
num++;
num1++;
printf("num = %d\n", num);
printf("num1 = %d\n", num1);
}
int main() {
fun();
fun();
fun();
return 0;
}
4.7.4 普通的局部变量
概念:
在函数内部定义的,或者复合语句中定义的变量
int main(){
int num;
{
int a;
}
}
作用范围:
在函数中定义的变量,在函数中有效。
再复合语句中定义的,再复合语句中有效。
生命周期:
在函数调用之前,局部变量不占用内存空间,调用函数的时候,才为局部变量开辟空间,函数结束了,局部变量就释放了。
在复合语句中的定义亦如此。
#include
void fun(void) {
int num = 3;
num++;
printf("num = %d", num);
}
void fun2( int x) {
x++;
printf("x=%d\n", x);
}
int main() {
fun();
fun();
fun();
fun2(3);
return 0;
}
4.7.5 静态的局部变量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QLoPeBjS-1649660664455)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403170643017.png)]
#include
void fun() {
static int num = 3;
num++;
printf("num = %d \n", num);
}
int main() {
fun();
fun();
fun();
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0tQ9ezq0-1649660664455)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403170831889.png)]
void fun2(void) {
static int b;
printf("静态局部变量 = %d \n", b);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MHJOj8pA-1649660664455)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403171448675.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Rjajb1F-1649660664456)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403171819955.png)]
4.7.6 外部函数
咱们定义的普通函数,都是外部函数。
咱函数可以在程序的任何一个文件中调用
4.7.7 内部函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-H1Hrs820-1649660664456)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220403172617175.png)]5.预处理 、 动态库 、 静态库
5.1 c语言编译过程
1:预编译
将.c 中的文件展开、宏展开
生成的文件是.i 文件
2:编译
将预处理之后的.i 文件生成 .s 汇编文件
3、汇编
将.s 汇编文件生成.o 目标文件
4、链接
将.o 文件链接成目标文件
Linux 下 GCC编译器编译过程
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NG5z1Wpp-1649660664457)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404014338085.png)]
5.2 include
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWF5FFYc-1649660664457)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404015646638.png)]
会将头文件在预处理阶段转换成这种语句。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7KYMhqXI-1649660664458)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404020237728.png)]
5.3 define
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-axn0CcHx-1649660664458)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404020409717.png)]
#undef PI // 从此行开始,宏失效
#define PI 3.1415926
int main()
{
double f;
printf("PI= %lf\n", PI);
f = PI;
#undef PI // 从此行开始,宏失效
printf("f= %lf\n", f);
#define PI 3.1415926 //重新定义一个宏
return 0;
}
//也可以将define 放入头文件中 调用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vKhjOhaf-1649660664458)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404021307907.png)]
#define S(a, b) a *b
int main()
{
int num;
num = S(7, 8);
printf("num = %d", num);
num = S(3 + 5, 7);
printf("num = %d", num);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eFsxXNy1-1649660664459)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404024334622.png)]
5.4 选择性编译
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9lXxj28A-1649660664459)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404031333665.png)]
#define AAA
int main()
{
#ifdef AAA
printf("hello world\n");
#else
printf("hello China!!\n");
#endif
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vSs4lCoJ-1649660664460)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404155737854.png)]
#include "选择性编译.h"
#include "选择性编译.h"
int main() {
return 0;
}
.h
#ifndef __选择性编译_H__
#define __选择性编译_H__
extern int fun(int x, int y);
#endif
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LHBpbzon-1649660664460)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404155915743.png)]
记住一下选择性编译都是在预处理环境下进行的
5.5 静态库
一:动态编译
动态编译使用的是动态库文件进行编译
gcc hello.c -o hello
默认咱们使用的是动态编译方法
二:静态编译
静态编译使用的静态库文件进行编译
gcc -static hello.c -o hello
三:静态编译和动态编译的区别
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-clMYSNMd-1649660664460)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404171319813.png)]
int max(int x,int y) {
return (x > y) ? x : y;
}
int min(int x, int y) {
return (x > y) ? x : y;
}
#ifndef __mylib_h__
#define __mylib_h__
extern int max(int x, int y);
extern int min(int x, int y);
#endif
#include
#include"mylib.h"
int main(int args,char *argv[]) {
int a = 10, b = 20, max_num, min_num;
max_num = max(a, b);
min_num = min(a, b);
printf("max_num = %d\n", max_num);
printf("min_num = %d\n", min_num);
return 0;
}
把mylib.c制作成静态库文件。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FWHgbF8f-1649660664461)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404174023073.png)]
以前
gcc mytest.c mylib.c mylib.h mylib.o mytest
方法一要求库文件和头文件都在指定路劲下,才会生效。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5x5aZMum-1649660664461)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404180827029.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kYrKVKht-1649660664461)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404181232497.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TcWtQTRD-1649660664462)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404181803267.png)]
5.6 动态库
第一步
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-C2zZGELz-1649660664462)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404182700912.png)]
有了动态库开始编译
该步骤需要先指定库文件和头文件的指定路径方便程序查找运行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MPp7tJlE-1649660664462)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404183846414.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-b9WjWfLZ-1649660664463)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404183830013.png)]
6.指针
6.1.1 关于内存那点事
存储器:存储数据器
外存
外村又叫做外部存储器,长期存放数据,掉电不丢失数据。
常见的外存设备:硬盘、flash、rom、u盘、光盘、磁带
内存
内存又叫内部存储器,展示存放数据,掉电数据丢失
常见的内存设备:ram 、 DDR
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4QD3GWBi-1649660664463)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404195840339.png)]
32位下 是 4个g
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UEZnPcye-1649660664464)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404200155971.png)]
每一个存储地址是一个字节都代表一个字符
例如’a’ 存放的是ascll码的二进制
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O2Hl6yHl-1649660664464)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404200329903.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ClsHs56B-1649660664465)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404200348046.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fo0KXuJk-1649660664465)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404200946920.png)]
内存以字节为单位来存储数据的,咱们可以将程序中的虚拟寻址空间,看成一个很大的一维的字符数组。。。(4g)
6.1.2 指针的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yS1DsqRP-1649660664466)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404211649924.png)]
写了个100 ,就是100的二进制 写了个a ,字符的ascll码的二进制。
指针变量:是个变量,是一个指针变量,即用这个变量来存放一个地址编号
在32位平台下,地址总线是32位的,所以地址是32位编号,所以指针变量是32位的即4个字节。
注意: 1:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-aLxW1jlH-1649660664467)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404223340875.png)]
当然,在64位系统,占用8个字节。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-oTbdKcgv-1649660664468)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404223538380.png)]
#include
int main(void)
{
int *a = NULL;
float *b = NULL;
double *c = NULL;
char *d = NULL;
printf("%d %d %d %d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));
return 0;
}
6.1.3 指针的定义方式
1.简单的指针变量
数据类型 * 指针变量名
int * p ; // 定义了一个指针变量 p
在定义指针变量的时候 * 是用来修饰变量的 ,说明变量 p 是一个指针变量
变量名称是p
2.关于指针的运算符
& 取地址 、 *取值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wwxYAiMB-1649660664468)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404230413669.png)]
p保存了 a的地址 ,也可以说是p指向了 a
p和a 的关系分析:a的值是0x1234adcd ,假如a 的地址是:0xbf e8 98 68
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-m50li5s0-1649660664470)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404231024967.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T0JE4qG2-1649660664470)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404231218022.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5muXD9ia-1649660664471)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404231257965.png)]
#include
int main()
{
int a = 100, b = 200;
int *p_1, *p_2 = &b;
p_1 = &a;
printf("a=%d\n", a);
printf("*p_1=%d\n", *p_1);
printf("b=%d\n", b);
printf("*p_2=%d\n", *p_2);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wr3huheK-1649660664471)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404232305806.png)]
3.指针大小
#include
int main(void)
{
int *a = NULL;
float *b = NULL;
double *c = NULL;
char *d = NULL;
printf("%d %d %d %d\n", sizeof(a), sizeof(b), sizeof(c), sizeof(d));
return 0;
}
6.1.4 指针的分类
按照指针指向的数据的类型来分
1:字符指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nHBzW7oR-1649660664472)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404233319200.png)]
2:短整形指针
short int *p; //定义了一个短整型的指针变量p,只能存放短整型变量的地址。
short int a;
p= &a; //&取变量a的地址
3:整形指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CYUzFZsL-1649660664472)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404233510743.png)]
4:长整型指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rREI3Tph-1649660664473)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404233652852.png)]
5:float 型指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-j2icRoIO-1649660664474)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404233737331.png)]
6:double型指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c7EI2kGg-1649660664474)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220404233808919.png)]
总结:无论什么类型的指针变量,在32位系统下,都是4个字节。(同理,在64位系统下,都是8位字节)指针只能存放对应类型的变量的地址编号(通用指针任意地址编号)。
6.1.5 指针和变量的关系
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hOom6Sif-1649660664474)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405000548584.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dN4yPPlQ-1649660664475)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405000830103.png)]
#include
int main()
{
int *p1, *p2, temp, a, b;
p1 = &a;
p2 = &b;
printf("请输入a和b的值 = \n");
scanf_s("%d %d", p1, p2);
temp = *p1;
*p1 = *p2;
*p2 = temp;
printf("a =%d,b=%d = \n", a, b);
printf("*p1=%d *p2=%d \n", *p1, *p2);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KTj2KDtD-1649660664475)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405004257546.png)]
#include
int main()
{
int a = 0x12345678, b = 0xabcdef66;
char *p1, *p2;
int *p;
p1 = (char *)&a;
p2 = (char *)&b;
printf("%0x %0x\n", *p1, *p2);
p = &a;
printf("*p =%0x\n", *p);
p1++;
p2++;
printf("%0x %0x\n", *p1, 0xff & (*p2));
return 0;
}
78 66
*p =12345678
56 ef
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-e6zzmTuh-1649660664476)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405005805252.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hweBVyAL-1649660664476)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405010600617.png)]
6.1.6 指针和数组的关系
1[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-zWRYhAwZ-1649660664476)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405025602658.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-krGhH6DH-1649660664477)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405030409831.png)]
虽然指针里面的a[0]占用4个字节空间,在他赋值给p的时候,会将它最小的地址赋值。即0x 00 00 20 00
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NJ3jt96H-1649660664478)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405030038007.png)]
2.数组的引用方式
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-HvJSBJjd-1649660664478)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220405033133256.png)]
注意:p 和 a 的不同,p是指针变量,而a是一个常量。所以可以用等号给p赋值,但不能给a 赋值。
p=&a[3]; //正确
a=&a[3]; //错误
方法3:通过指针变量运算加取值的方法来引用数组的元素
int *p;
p = a;
*(p+2)=100;//也是可以的 ,相当于a[2] = 100
解释:p是第0个元素的地址,p+2 是a[2] 这个元素的地址。
对第二个元素的地址取值,即a[2]
方法4:通过数组名+取值的方法引用数组的元素
int a[10];
*(a+2)=100;//也可以是a[2] = 100;
注意:a+2 是 a[2] 的地址。这些地方并没有给 a 赋值
例题:
#include
int main()
{
int a[5] = {0, 1, 2, 3, 4};
int *p;
p = a;
printf("a[2] = %d\n", a[2]);
printf("p[2] = %d \n", p[2]);
printf("*(p+2)=%d\n", *(p + 2));
printf("*(a+2)=%d\n", *(a + 2));
printf("a=%d\n", a);
printf("a+1=%d\n", a + 1);
printf("&a=%d\n", &a);
printf("&a+1=%d\n", &a + 1);
printf("sizeof(a)%d\n", sizeof(a));
printf("sizeof(a)%d\n", sizeof(a + 1));
printf("p = %d\n", p);
printf("p+2 = %d\n", p + 1);
return 0;
}
3、指针的运算
1:指针可以加一个整数,往下指几个它指向的变量,结果还是个地址
前提:指针指向数组的时候 ,加一个整数才有意义。
例:
int a[10];
int *p;
p=a ;
p+2;
**假如p保存的地址编号是 2000的话 ,p+2 代表的地址编号就是2008 **
例:
char buf[10];
char *q;
q = buf;
q+2;
假如:q中存放的地址编号是2000的话,q+2代表的地址编号是 2002
2:两个相同类型的指针可以比较大小
前提:只有两个相同类型的指针指向 同一个数组的元素的时候,比较大小才有意义。
指向前面元素的指针 小于 指向后面 元素的指针
#include
int main()
{
int a[10];
int *p, *q, n;
p = &a[1];
q = &a[6];
if (p < q)
{
printf("p);
}
else if (p > q)
{
printf("p>q\n");
}
else
{
printf("p=q\n");
}
return 0;
}
3.相同类型的指针可以做减法
指针数组相减,减少的是两个数组之间相隔几个元素,如整数a[0]和a[3] a3-a1 =3 相隔三个元素 12个字节 一个元素4个字节
前提:必须是两个相同类型的指针指向同一个数组的元素的时候,做减法才有意义
做减法的结果是,两个指针指向的中间有多少个元素
int a[5];
int *p, *q;
p = &a[0];
q = &a[3];
printf("q-p=%d\n", q - p);
printf("q=%d\n", q);
printf("p=%d\n", p);
printf("q=%d\n", *q);
printf("p=%d\n", *p);
4:两个相同类型的指针可以相互赋值
注意:只有相同类型的指针才可以相互赋值(*void 类型的除外)
int *p;
int *q;
int a;
p=&a;
p=q;
注意:c语言规定数组的名字,就是数组的首地址,就是数组第0个元素的地址
int *p;
int a[10];
p=a; p=&a[0]
6.1.7 指针数组
1、指针和数组的关系
1:指针可以保存数组元素的地址
2:可以定义一个数组,数组中由若干个相同类型指针变量,这个数组被称为指针数组 int *p[5];//p[0] p[1] 都可以存放整形
指针数组的概念:
指针数组本身就是一个数组,是一个指针数组,是若干个相同类型的指针变量构成的集合
2、指针数组的定义方法
类型说明符 * 数组名 [元素个数];
int * p[5];// 定义了一个整型的指针数组p,有5个元素 p[0]~p[5]
每个元素都是int * 类型的变量
int * p[5];
int a;
p[0]=&a;
int b[10];
p[1]=&b[5];
#include
int main()
{
int *p[5];
int a = 100;
int b[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
printf("sizeof(p) = %d\n", sizeof(p));
p[0] = &a;
printf("p[0]=%p\n", p[0]);
printf("&a =%p\n", &a);
printf("*p[0]=%d\n", *p[0]);
p[1] = &b[2];
printf("*p[1]=%d\n", *p[1]);
return 0;
}
例 13
#include
int main()
{
char *name[5] = {"hello",
"china",
"beijing",
"henan",
"anhui"};
int i;
for (i = 0; i < 5; i++)
{
printf("*name[i] = %s\n",name[i]);
printf("*name[i] = %d\n", sizeof(*name[i]));
printf("*name[i] = %c\n", *name[i]);
}
return 0;
}
文字常量区存放的都是字符的ascll码的二进制,没有存放在字符数组name中,数组里面存放的都是字符串对应的首地址编号[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-lksIpjQf-1649660664479)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406093205483.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2zXifd4Q-1649660664479)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406093433672.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OHo2yC0R-1649660664480)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406093627223.png)]
3、指针数组的分类
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-4Z7UkmSK-1649660664480)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406093724932.png)]6.1.8 指针的指针
指针的指针,即指针的地址,
咱们定义一个指针变量本身指针变量占4个字节(32位系统下,64位占8个字节),指针变量也有地址编号
例如:
int a = 0x12345678;
假如:a的地址是0x00002000
int *p;
p =&a;
则p中存放的是a的地址编号即0x00002000
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qugKO56p-1649660664480)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406094445442.png)]
int *p;
int **q;
q =&p;
则q里面存放的就是0x00003000
int ***m;
m = &q;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-40ylSbfK-1649660664481)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406094819145.png)]
p q m 都是指针变量,都占用4个字节,都存放地址编号,只不过类型不一样而已。
#include
int main()
{
int a = 0x12345678;
int *p;
int **q;
int ***m;
p = &a;
printf("&a = %p\n", &a);
printf("p=%p\n", p);
q = &p;
printf("&p = %p\n", &p);
printf("q=%p\n", q);
m = &q;
printf("&q = %p\n", &q);
printf(" m=%p\n", m);
printf("*P = %x\n", *p); //一级指针 12345678
printf("**q=%x\n", **q); //二级指针 12345678
printf("***m=%x\n", ***m); //三级指针 12345678
return 0;
}
//想获取一个指针的地址,就需要二级指针,或者三级四级...
6.1.9 字符串和指针
1.字符串的概念:
字符串就是以’\0’结尾的若干个的字符的集合:比如"helloworld"。
字符串的地址,是第一个字符的地址。如:字符串:“helloworld” 的地址,其实就是字符串中字符’h’ 的地址。
我们可以定义一个字符指针变量保存字符串的地址,比如:char *s =“helloworld”;
2.字符串的存储形式:数组、文字常量区、堆
1、字符串存放在数组中
其实就是在内存中(栈、静态全局区)中开辟了一段空间来存放字符串。
char string[100] = “I LOVE C!”;
定义了一个字符数组 string,用来存放多个字符,并且用"I LOVE C!" 给string数组初始化
字符串"I LOVE C!" 存放在string中。
注:普通全局数组,内存分配在静态全局区
普通局部数组,内存分配在栈区。
静态数组(静态全局数组、静态局部数组),内存分配在静态全局区
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rc0z9NxA-1649660664481)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406101218607.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-gkQNnAlQ-1649660664482)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406101417564.png)]
3.字符串的可修改性
字符串的内容是否可以被修改,取决于字符串存放在哪里。
1.存放在数组中的字符串的内容是可以修改的
char str[100] =“I LOVE C!”;
str[0] = ‘y’; // 正确可以修改的
注:数组没用const 修饰
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vDiAfe85-1649660664482)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406101954855.png)]
#include
int main()
{
char *str = "I LOVE C!";
printf("str=%s\n", str);
*str = 'y';
printf("str=%s\n", str);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-s8DSU9uy-1649660664482)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406103217764.png)]
#include
#include
int main()
{
char *str;
str = (char *)malloc(20);
strcpy(str, "I LOVE C!");
printf("str = %s\n", str);
*str = 'y';
printf("str = %s\n", str);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7jNSifC7-1649660664482)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406104507888.png)]
4.初始化
1.字符数组初始化:
char buf aver[20] = “hello world”;
2.指针指向文字常量区,初始化:
char * buf_point = “hello world”;
3.指针指向堆区,堆区存放字符串。
不能初始化,只能先给指针赋值,让指针指向堆区,在使用strcpy、scanf等方法把字符串拷贝到堆区。
char *buf_heap;
buf_heap =(char * )malloc(15);
strcpy(buf_heap,"hello world!);
scanf(“%s,buf_heap”);
5.使用时赋值
1.字符数组:使用scanf 或者 strcpy
char buf[20] = “hello world”
buf = “hello kitty”; 错误,因为字符数组的名字是个常量,不能用等号给常量赋值
strcpt(buf,“hello world”); 正确,数组中的内容是可以修改的
scanf(“%s”,buf); // 这个直接输入也可以修改哦
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CcfOcs51-1649660664483)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406111723731.png)]
总结来说:指针指向文字常量区的内容不可以修改,但是能够修改指向
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPcNChQM-1649660664483)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406114101291.png)]字符串和指针总结:
1、指针可以指向文字常量区
(1)指针指向的文字常量区的内容不可以修改
(2)指针的指向可以改变,既可以给指针变量重新赋值,指针变量指向别的地方。
2、指针可以指向堆区
(1)指针指向的堆区的内容可以修改
(2)指针的指向可以改变,即可以给指针变量重新赋值,指针变量指向别的地方。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3j7lbsst-1649660664483)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406132249753.png)]
6.1.10 数组指针
1、二维数组
二维数组,有行,有列。二维数组可以看成有多个一维数组构成的,是一个一维数组的集合可以认为二维数组的每一个元素是个一维数组。
例:
int a[3] [5]
定义了一个3行5列的一个二维数组。
可以认为二维数组 a 由 3个一维数组构成,每个元素是一个一维数组。
回顾:
数组的名字是数组的首地址,是第0个元素的地址,是个常量,数组名字加1 指向下一个元素
二维数组a中 ,a+1指向下一个元素,即下一个一维数组,即下一行。
#include
int main()
{
int a[3][5];
printf("a=%d\n", a);
printf("a+1=%d\n", a + 1);
}
2、数组指针的概念
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pHJX32IH-1649660664484)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406154213618.png)]
3、数组指针的定义及使用
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9bxDb49a-1649660664484)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220406171438471.png)]
和指针数组的区别在于一个是数组一个是指针,前者用于指向一个二维或多维数组,后者用来存放若干个相同类型的指针变量的存储集合
#include
int main(){
int a[3][5];
int b[6][5];
int (*p)[5] ;
p = a ;
printf("a=%d\n",a);
printf("a+1=%d\n",a+1);
printf("p=%d\n",p);
printf("p+1=%d\n",p+1);
printf("a[0][0]=%d\n",&a[0][0]);
printf("a[0][0]+1=%d\n",&a[0][0]+1);
return 0;
}
指针数组的用法:
#include
void fun(int (*p)[5],int x,int y);
int main(){
int a[3][5] = {
{1,2,3,4,5},
{6,7,8,9,10},
{11,12,13,14,15}
};
printf("a[1][2]=%d\n",a[1][2]);
fun(a,3,5);
printf("a[1][2]=%d\n",a[1][2]);
return 0;
}
void fun(int (*p)[5],int x,int y)
{
p[1][2] = 100;
}
4、各种数组指针的定义
(1)、一维数组指针,加1后指向下个一维数组
int(*p)[5];// 注意加括号 不然就是int *p[5] 前者数组指针,后者指针数组。前者代表二维数组的元素只占用4个字节,后者存放了5个整型指针变量,占用20字节。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1WrjgKFv-1649660664484)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408090644478.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-EA8sUXj8-1649660664484)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408090706596.png)]
(p+1)[i]相当于p[i+1] 往后指一行
#include
void fun(int(*p)[4][5])
{
}
int main(){
int a[3][4][5];
printf("a=%p\n",a);
printf("a+1=%p\n",a+1);
printf("&a=%p\n",&a);
printf("&a+1=%p\n",&a+1);
int (*p)[4][5];
p =a;
printf("p=%p\n",p);
printf("p+1=%p\n",p+1);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N0xp7jlD-1649660664485)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408092842379.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-UT60v2sD-1649660664485)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408090804532.png)]
8、数组名字取地址:变成 数组指针
一维数组名字取地址,变成一维数组指针,即加1跳一个一维数组
int a[10];
a+1 跳一个整型元素,是a[1]的地址
a和 a+1 相差一个元素,4个字节。
&a 就变成了一个一维数组指针,是 int(*p)[10]类型的。
(&a)+1 和&a相差一个数组即10个元素即40个字节
#include
int main()
{
int a[10];
printf("a=%p\n", a);
printf("a+1=%p\n", a + 1); // a和a+1相差4个字节
printf("&a =%p\n", &a); //数组指针 ,取地址的a+1
printf("&a+1=%p", &a + 1); //数组取地址加1 等同于int(*p)[10]; 等于跳过了10个元素,单个元素4个字节 也就是40字节 。两者相差40
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uSJ5iinn-1649660664486)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407113128193.png)]
在运行程序时,大家会发现a和&a所代表的地址编号是一样的,即他们指向同一个存储单元,但是a和&a的指针类型不同
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-eKwO1xKE-1649660664486)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407115017603.png)]
#include
int main()
{
int a[4][5];
printf("a = %d\n", a);
printf("a+1= %d\n", a + 1);
printf("&a=%d\n", &a);
printf("&a+1 = %d\n", &a + 1);
int b[3][4][5];
printf("a = %d\n", b);
printf("a+1= %d\n", b + 1);
return 0;
}
总结:c语言规定,数组名字取地址,变成了指针数组。加一跳一个数组
9、数组名字和指针变量得区别
int a[5];
int *p;
p=a;
相同点:
a是数组的名字,是a[0]的地址,p=a即保存了a[0]的地址,即a和p都指向a[0],所以在引用数组元素的时候,a和p等价
引用数组元素回顾:
a[2]、*(a+2)、p[2]、 *(p+2)都是对数组a中a[2]元素的引用。
#include
int main()
{
int a[5] = {0, 1, 2, 3, 4};
int *p;
p = a;
printf("a=%p\n", a);
printf("a+1=%p\n", a + 1);
printf("a=%d\n", &a);
printf("a+1=%d\n", &a + 1);
printf("p=%p\n", p);
printf("a[2] = %d\n", a[2]);
printf("*(a+2)= %d\n", *(a + 2));
printf("p[2]=%d\n", p[2]);
printf("*(p+2)= %d", *(p + 2));
return 0;
}
#include
int main()
{
int a[5] = {0, 1, 2, 3, 4};
int *p;
p = a;
p = &a[3];
printf("*p=%d\n", *p);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wkb17opj-1649660664486)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407141535634.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-a845xe8E-1649660664487)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407142940311.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cENmLf1p-1649660664487)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407142830288.png)]
#include
int main()
{
int a[5] = {0, 1, 2, 3, 4};
int *p;
p = a;
printf("a=%d\n", a);
printf("&a= %d\n", &a);
printf("a+1=%d\n", a + 1);
printf("&a+1=%d\n", &a + 1);
printf("&p =%d\n", &p);
printf("&p+1 = %d\n", &p + 1);
}
10、数组指针取*
数组指针>取 * ,并不是取值的意思,而是指针的类型发生变化:
一维数组指针取*,结果为它指向的一维元素第0个元素的地址,它们还是指向同一个地方。
二维数组指针取 * ,结果为一维数组指针,它们还是指向同一个地方。
三维数组指针取 * ,结果为二维数组指针,它们还是指向同一个地方。
多维数组以此类推
这里不用迷,就是说给数组指针取*不管是几维数组传给了这个指针对这个指针变量取** 的值都是第0个元素的地址,二维数组是【0】【0】个元素的地址+一也就是【0】【1】的地址,三维以此类推,二不加**就是数组第【0个元素的地址】,在二维数组也就是【0】【0】的地址,+1也就是【1】【0】的地址,两者是不相同的
#include
int main()
{
int a[3][5];
int(*p)[5];
p = a;
printf("a =%d\n", a);
printf("a+1 =%d\n", a + 1);
printf("*a =%d\n", *a);
printf("*a+1 =%d\n", *a + 1);
printf(" \n");
printf("p=%d\n", p);
printf("p+1=%d\n", p + 1);
printf("*p = %d\n", *p);
printf("*p+1=%d\n", *p + 1);
printf(" \n");
printf("&a[0][0]%d\n", &a[0][0]);
printf("&p=%d\n", &p);
printf("&p+1=%d\n", &p + 1);
printf("&a=%d\n", &a);
printf("&a+1=%d\n", &a + 1);
return 0;
}
a =6421984
a+1 =6422004
*a =6421984
*a+1 =6421988
p=6421984
p+1=6422004
*p = 6421984
*p+1=6421988
&a[0][0]6421984
&p=6421976
&p+1=6421984
&p=6421984
&p+1=6422044
6.1.11 指针和函数的关系
1.指针作为函数的参数
咱们可以给一个函数传一个 整型、字符型、浮点型的数据,也可以给函数传一个地址。
例子
不传函数地址
#include
void swap(int x, int y)
{
int temp;
temp = x;
x = y;
y = temp;
}
int main()
{
int a = 10;
int b = 20;
swap(a, b);
printf("a=%d b=%d\n", a, b);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mZRuiC8T-1649660664487)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407172736783.png)]
传函数地址
#include
void swap(int *p, int *p2, int x, int y)
{
int temp;
temp = *p;
*p = *p2;
*p2 = temp;
}
int main()
{
int a = 10;
int b = 20;
int *p;
p = &a;
int *p2;
p2 = &b;
swap(p, p2, a, b);
printf("a=%d b=%d\n", a, b);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-dsBUAWLP-1649660664488)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220407173133723.png)]
#include
void swap(int *p, int *p2)
{
int *p0;
p0 = p;
p = p2;
p2 = p0;
}
int main()
{
int a = 10;
int b = 20;
swap(&a, &b);
printf("a=%d b=%d\n", a, b);
}
结果不变
总结:要想改变主调函数中变量得值,必须传变量得地址,而且还得通过*+地址去赋值
#include
void fun(char *q){
q = "hello kitty";
}
int main(){
char *p ="hello world!";
fun(p);
printf("p=%s\n",p);
return 0;
}
#include
void fun(char **q){
*q = "hello kitty";
}
int main(){
char *p = "helloworld! ";
fun(&p);
printf("p = %s\n",p);
return 0;
}
总结一句话:要想改变主调函数中变量得值,必须传变量得地址,而且还得通过*+地址去赋值,无论这个变量是什么类型的。
传数组
给函数传数组:
给函数传数组的时候,没法一下将数组的内容作为整体直传进去。
只能传数组名进去,数组名就是数组的首地址,即只能把数组的地址传进去。
也就是说,只能传一个4个字节大小的地址编号进去
例:传一维数组的地址
#include
void fun(int p[]){
printf("p[2]=%d\n",p[2]);
*(p+3) =100;
}
int main(){
int a[10] = {1,2,3,4,5,6,7,8,9,0};
fun(a);
printf("a[3]=%d\n",a[3]);
return 0;
}
例:传二维数组的地址
#include
void fun(int p[][4],int x,int y){
printf("p[1][2]=%d\n",p[1][2]);
p[0][1] = 100;
for(int i =0;i<x;i++){
for(int j = 0;j<y;j++){
printf("i=%d j=%d p[i][j]=%d\n",i,j,p[i][j]);
}
}
}
int main(){
int a[3][4]={
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
fun(a,3,4);
printf(" a[0][1] =%d\n", a[0][1]);
return 0;
}
传指针数组
#include
void fun(char **p,int x){
for(int i=0;i<x;i++){
printf("p[i]=%s\n",*(p+i));
}
}
int main(){
char * p[3] ={"hello","world","kitty"};
fun(p,3);
return 0;
}
2.指针作为函数的返回值
一个函数可以返回整型数据、字符数据、浮点型的数据,也可以返回一个指针
#include
char *fun(void)
{
char *str = "hello world!!";
return str;
}
int main()
{
char *p;
p = fun();
printf("p=%s\n", p);
return 0;
}
#include
#include
#include
char *fun(void)
{
char *str;
str = (char *)malloc(100);
strcpy_s(str, 100, "helloworld");
return str;
}
int main()
{
char *p;
p = fun();
printf("p=%s\n", p);
free(p);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-g1xntWTx-1649660664488)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408095825301.png)]
3.指针保存函数得地址(函数指针)
1、函数指针得概念
咱们定义的函数,在运行程序的时候,会将函数的指令加载到内存得代码段。所以函数也有起始地址。
c语言规定:函数的名字就是函数的首地址,即函数的入口地址
咱们就可以定义一个指针变量,来存放函数的地址。
这个指针变量就是函数指针变量
2、函数指针的用处
函数指针用来保存函数的入口地址
在项目开发中,我们经常需要编写或者调用带函数指针参数的函数。
比如LInux系统中创建多线程得函数,他有个参数就是函数指针,接收线程函数得入口地址,即线程创建线程成功后,新的任务执行线程函数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-xElebZYM-1649660664488)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408101958309.png)]
3、函数指针变量得定义
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pfGDMuaL-1649660664489)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408102813317.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mXdPOGzD-1649660664489)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408103031290.png)]
4、调用函数的方法
1.通过函数的名字去调函数(最常用的)
int max(int x , int y)
{
}
int main()
{
int num;
num =max(3,5);
}
2、可以通过函数指针变量去调用
#include
int max(int x, int y)
{
int temp;
if (x > y)
{
temp = x;
}
else
{
temp = y;
}
return temp;
}
int min(int x, int y)
{
int temp1;
if (x > y)
{
temp1 = y;
}
else
{
temp1 = x;
}
return temp1;
}
int main()
{
int (*p)(int, int);
int num;
num = max(10, 20);
printf("num =%d\n", num);
p = min;
num = (*p)(10, 20);
printf("num = %d\n", num);
return 0;
}
5、函数指针数组
概念:由若干个相同类型的函数指针变量构成的集合,在内存中连续的顺序存储.
函数指针数组是个数组,他的每个元素都是一个函数指针变量。
函数指针数组的定义:
*类型名(数组名[元素个数])(形参列表)
*int(p[5])(int,int);
定义了一个函数指针数组,有5个元素p[0]~p[4],每个元素都是函数指针变量,每个函数指针变量指向的函数,必须有整型的
返回值,两个整型参数。
#include
int min(int x, int y)
{
int temp1;
if (x > y)
{
temp1 = y;
}
else
{
temp1 = x;
}
return temp1;
}
int max(int x, int y)
{
int temp1;
if (x > y)
{
temp1 = y;
}
else
{
temp1 = x;
}
return temp1;
}
int add(int x,int y) {
return x + y;
}
int del(int x, int y) {
return x-y;
}
int mux(int x, int y) {
return x * y;
}
int main(int x, int y) {
int (*p[5])(int, int) = { max,min,mux,del,add };
int num;
num = (*p[2])(10, 20);
printf("num = %d", num);
}
6、函数指针的应用举例
函数指针变量作为函数的参数
#include
int add(int x, int y) {
return x + y;
}
int del(int x, int y) {
return x - y;
}
int mux(int x, int y) {
return x * y;
}
int dive(int x, int y) {
return x / y;
}
int process(int(*p)(int, int), int x, int y) {
int ret;
ret = (*p)(x, y);
return ret;
}
int main(int x, int y) {
int num;
num = process(add, 10, 20);
printf("num = %d\n", num);
num = process(mux, 10, 20);
printf("num = %d\n", num);
return 0;
}
总结来说一句话:函数指针变量,就是一个指针变量,他就是8个字节(32位系统下为4字节)
6.1.12 经常容易混淆的指针概念
第一组:
1、int *a[10];// 这是一个指针数组,共存放10个元素,一个元素8字节,a占了80个字节。
这是一个指针数组,数组a中有10个整型的指针变量
a[0]~a[9] ,每个元素都是int *类型的指针变量
2、int (*a)[10];//数组指针本质还是指针,它指向数组里面的元素,也就是4个字节
数组指针变量,他是一个指针变量。它占4个字节,存地址编号。
它指向一个数组,它加一的话,指向下一个数组。
3、int **p
这是个指针的指针,保存指针变量的地址。
它经常用来保存指针的地址:
常见用法1:
int **p
int *q;
p = &q;
常见用法二:
int **p;
int *q[10];
分析:q是指针数组的名字,是指针数组的首地址,是q[0]的地址。
*q[0]是一个int 类型的指针。 所以q[0]指针变量的地址,是int * * 类型的。
p = &q[0] ; 等价于p =q;
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ai2OXkhH-1649660664489)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408151535767.png)]
6.1.13 特殊指针
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-N1pkVFDp-1649660664490)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408152810278.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NLkaW0Du-1649660664490)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408152947882.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-V75V7tfy-1649660664491)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408154220760.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rg9fIKQt-1649660664491)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220408154446270.png)]
6.1.14 main函数传参
#include
int main(int argc, char const *argv[])
{
int i;
printf("argc= %d\n", argc);
for (i = 0; i < argc; i++)
{
printf("argc[%d]=%s\n", i, argv[i]);
}
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jWR6ua98-1649660664492)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409120329217.png)]
第七章 动态内存申请
7.1动态分配内存的概述
在数组一章中,介绍过数组的长度是预先设定好的,在整个程序中固定不变,但是实际的编程中,往往会发生这种情况
即所需的**内存空间取决于实际输入的数据**,而无法预先确定。为了解决上述问题,C语言提供了一些内存管理函数,这些内存
管理函数可以按需要动态的分配内存空间,也可把不再使用的空间回收再次利用。
7.2静态分配、动态分配
静态分配
- 在程序的编译或运行的过程中,按事先规定大小分配内存空间的分配方式。int a[10]
- 必须事先知道所需空间的大小
- 分配在栈区或全局变量区,一般以数组的形式
- 按计划分配。
动态分配
- 在程序运行过程中,根据需要大小自由分配所需空间。
- 按需分配
- 分配在堆区,一般使用特定的函数进行分配
7.3动态分配函数
头部库文件 stdlib.h
1、malloc 函数
函数原型:void * malloc(unsigned int size);
功能说明:
在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域,用来存放类型说明符指定的类型。函数
原型返回的void*指针,使用时必须做相应的强制类型转换,分配的内存空间内容不确定,一般使用memset初始化。
**返回值:**分配空间的起始地址(分配成功)
null (分配失败)
注意:
1、再调用malloc之后,一定要判断一下,是否申请内容成功
2、如果多次malloc申请的内存,第一次和第二次申请的内存不一定是连续的
char *p;
p = (char *)malloc(20);//*malloc默认是void 类型,转换成你想要的字符型需要强转。
#include
#include
int main()
{
int *p;
int i, n;
printf("请输入你要申请int数组的元素个数:\n");
scanf_s("%d", &n, 4);
p = (int *)malloc(n * 4);
if (p == NULL)
{
printf("malloc is null\n");
return 0;
}
for (i = 0; i < n; i++)
{
p[i] = i;
printf("p[%d]=%d\n", i, p[i]);
}
free(p);
return 0;
}
2、free函数(释放内存空间)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FV5DQw5e-1649660664492)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409130855489.png)]
3、calloc函数
头文件:#include
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-XwMbhDPr-1649660664493)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409131147121.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QLA6UGqz-1649660664493)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409131405670.png)]
4、realloc函数(重新申请内存)
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jb5Vw8m0-1649660664493)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409131646615.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TEEDvBHa-1649660664493)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409131658733.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OGmjiyux-1649660664494)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409133819419.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-QCCJzAII-1649660664494)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409133825113.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9sVyGk0C-1649660664494)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409133956445.png)]
7.4 内存泄漏
内存泄漏的概念:
申请的内存,首地址丢了,找不了,再也没法使用了,也没法释放了,这块内存就泄露了。
内存泄漏 例1:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-P0HUyuyy-1649660664495)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409162418755.png)]
内存泄漏 例2:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-mhQr1ZtW-1649660664495)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409162824613.png)]
内存泄漏1 解决方案:
其实就是在方法的后面清理一下 加上 free§;函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rTALpP6u-1649660664495)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409162923834.png)]
内存泄漏2 解决方案:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BRLpRL5K-1649660664496)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409163047423.png)]
总结:申请的内存,一定不要把首地址给丢了,在不用的时候一定要释放内存。
第八章 字符串处理函数
#pragma 指令的作用是:用于指定计算机或者操作系统特定的编译器功能。
#pragma warning(disable:4996) 在c文件开始处写上这句话,即告诉编译器忽略4996警告,strcpy、scanf等一些不安全的
标准C库函数在vs 中可以用了。
8.1 测字符串长度函数
头文件:#include
函数定义:size_t strlen(const char *a)
函数功能:
测字符指针 s 指向的字符串中字符的个数,不包括 ‘/0’
返回值:字符串中字符个数。
#include
#include
#pragma warning(disable:4996)
int main() {
char str1[20] = "hello";
char* str2 = "hello";
printf("sizeof(str1)=%d\n", sizeof(str1));
printf("sizeof(str2)=%d\n", sizeof(str2));
printf("strlen(str1)=%d\n", strlen(str1));
printf("strlen(str2)=%d\n", strlen(str2));
return 0;
}
sizeof(str1)=20
sizeof(str2)=8
strlen(str1)=5
strlen(str2)=5
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LztD2tiA-1649660664496)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409175429156.png)]
8.2 字符串拷贝函数
头文件:#include
函数的声明:**char *strcpy(char dest,const char src);
函数的说明:
拷贝src指向的字符串到dest 指针指向的内存中,'\0’也会拷贝
函数的返回值:
目的内存的地址
#include
#include
#pragma warning(disable : 4996)
int main()
{
char str[100] = "aaaaaaaaaaaaaaaaaaaaaaaaaa";
strcpy(str, "hello");
printf("str=%s\n", str);
printf("str+6=%s\n", str + 6);
return 0;
}
str=hello
str+6=aaaaaaaaaaaaaaaaaaaa
注意:在使用此函数的时候,必须保证dest指向的内存空间足够大,否则会出现内存污染。
**char strncpy(char * dest,const char src,size_t n);
函数的说明:
将src指向的字符串前n个字节,拷贝到dest指向的内存中
返回值:目的内存的首地址
注意:
1、strcpy 不拷贝 ‘\0’
2、 **如果n大于src指向的字符串中的字符个数,则在 dest 后面填充n-strlen(src)**个’\0’
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100] = "aaaaaaaaaaaaaaaaaaaaaa";
strncpy(buf, "helloworld", 5);
printf("buf=%s\n", buf);
return 0;
}
buf=helloaaaaaaaaaaaaaaaaa
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100] = "aaaaaaaaaaaaaaaaaaaaaaaaaa";
int len;
len = strlen(buf);
strncpy(buf, "helloworld", 15);
printf("buf=%s\n", buf);
for (int i = 0; i < len; i++)
{
printf("buf[%d]=%c\n", i, buf[i]);
}
return 0;
}
buf=helloworld
buf[0]=h
buf[1]=e
buf[2]=l
buf[3]=l
buf[4]=o
buf[5]=w
buf[6]=o
buf[7]=r
buf[8]=l
buf[9]=d
buf[10]=
buf[11]=
buf[12]=
buf[13]=
buf[14]=
buf[15]=a
buf[16]=a
buf[17]=a
buf[18]=a
buf[19]=a
buf[20]=a
buf[21]=a
buf[22]=a
buf[23]=a
buf[24]=a
buf[25]=a
8.3 字符串追加函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9wzQTDsw-1649660664497)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409194234637.png)]
注意:
追加的时候会追加’\0’
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100] = "aaa\0aaaaaaaaaa";
strcat(buf, "helloworld");
printf("buf=%s\n", buf);
return 0;
}
buf=aaahelloworld
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WiIG3mey-1649660664497)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220409200952976.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char str[100] = "aa\0aaaaaaaaaaaaaaaaa";
char *src = "hello";
strncat(str, src, 3);
printf("str = %s\n", str);
return 0;
}
str = aahello
结果是 aahello
验证了追加字符串的时候追加 ‘\0’
8.4 字符串比较函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-yhER3HG4-1649660664498)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410124711183.png)]
注意:比较的是ascll码
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str1 = "hello world!";
char *str2 = "hello kitty!";
int ret;
ret = strcmp(str1, str2);
if (ret > 0)
printf("str1>str2");
else if (ret < 0)
printf("str1);
else
printf("str1=str2");
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RkKbePJI-1649660664498)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410125423719.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str1 = "hello world!";
char *str2 = "hello kitty!";
int ret;
ret = strncmp(str1, str2, 5);
if (ret > 0)
printf("str1>str2");
else if (ret < 0)
printf("str1);
else
printf("str1=str2");
}
8.5 字符查找函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-6iXMrbhZ-1649660664498)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410125738444.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str1 = "hello world!saadtyujnn";
char *p;
p = strchr(str1, 'l');
if (p == NULL)
{
printf("没有你要找的i那个字");
return 0;
}
printf("p-str=%d\n", p - str1);
printf("*p=%c\n", *p);
}
p-str=2
*p=l
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-r06P30iM-1649660664498)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410155232175.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str1 = "hello world!saadtyujnn";
char *p;
p = strrchr(str1, 'n');
if (p == NULL)
{
printf("没有你要找的i那个字");
return 0;
}
printf("p-str=%d\n", p - str1);
printf("*p=%s\n", str1);
}
p-str=21
*p=hello world!saadtyujnn
8.6 字符串匹配函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-DEMuWWtn-1649660664499)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410155910634.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char str1[100] = "defjk$#$sadsadas$#$fjka";
char str2[100] = "$#$";
char *p;
p = strstr(str1, str2);
if (p == NULL)
{
printf("没有你要查找的字符串\n");
return 0;
}
printf("p-str1=%d\n", p - str1);
return 0;
}
8.7 空间设定函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-8Zjkt2i8-1649660664499)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410194032528.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char str[100] = "helloworld";
printf("str=%s\n", str);
memset(str, 'a', 5);
printf("str=%s\n", str);
return 0;
}
str=helloworld
str=aaaaaworld
8.8 字符串转换数值
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y2LI4cIz-1649660664499)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410202940678.png)]
long atol(const char *nptr);将字符串转换为一个长整型的数
double atof(const char *nptr); 将字符串转换为一个浮点型的数
8.9 字符串切割函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NbmSksXn-1649660664500)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410203521142.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char str[100] = "xiaoming:21,,,.男.女,北京:haidian";
char *p[7];
int i = 0, j;
printf("str=%s\n", str);
p[i] = strtok(str, ":,.");
printf("p[%d]=%s\n", i, p[i]);
printf("str=%s\n", str);
while (p[i] != NULL)
{
i++;
p[i] = strtok(NULL, ":,.");
}
for (j = 0; j < i; j++)
{
printf("p[%d]=%s\n", j, p[j]);
}
printf("p[1]+3= %s\n", p[1] + 3);
return 0;
}
str=xiaoming:21,,,.男.女,北京:haidian
p[0]=xiaoming
str=xiaoming
p[0]=xiaoming
p[1]=21
p[2]=男
p[3]=女
p[4]=北京
p[5]=haidian
p[1]+3= ,,.男
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ywrxvJK9-1649660664500)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410205140728.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-tMPgpiht-1649660664500)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410205653235.png)]
#include
#include
#pragma warning(disable : 4996)
int msg_deal(char *msg_src, char *msg_done[], char *str)
{
int i = 0;
msg_done[i] = strtok(msg_src, ",");
while (msg_done[i] != NULL)
{
i++;
msg_done[i] = strtok(NULL, str);
}
return i;
}
int main()
{
char s[100] = "+CMGR:REC UNREAD,+8617633722460,98/10/01,18:22:11+00,ABCdefGHI";
char *p[6];
int num, i;
num = msg_deal(s, p, ",");
printf("num=%d\n", num);
for (i = 0; i < num; i++)
{
printf("p[%d]=%s\n", i, p[i]);
}
printf("手机号=%s\n", p[1] + 3);
printf("日期=%s\n", p[2]);
*(p[3] + 8) = '\0';
printf("时间=%s\n", p[3]);
printf("内容=%s\n", p[4]);
return 0;
}
num=5
p[0]=+CMGR:REC UNREAD
p[1]=+8617633722460
p[2]=98/10/01
p[3]=18:22:11+00
p[4]=ABCdefGHI
手机号=17633722460
日期=98/10/01
时间=18:22:11
内容=ABCdefGHI
8.10 格式化字符串操作函数
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-csaMnNz8-1649660664500)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220410220600692.png)]
sprintf
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100];
sprintf(buf, "%d:%d:%d:%d", 2000, 10, 1, 101);
printf("buf=%s\n", buf);
return 0;
}
buf=2000:10:1:101
sscanf
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100];
sprintf(buf, "%d:%d:%d:%d", 2000, 10, 1, 101);
printf("buf=%s\n", buf);
int a, b, c, d;
char buf1[100];
sscanf(buf, "%d:%d:%d:%d", &a, &b, &c, &d);
printf("a=%d\n", a);
printf("b=%d\n", b);
printf("c=%d\n", c);
printf("d=%d\n", d);
return 0;
}
sscanf高级用法1
1、跳过数据:%s 或 %*d
例如:sscanf(“1234 5678”,“%*d %s”,buf);
sscanf默认碰到空格终止
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
int num;
sscanf("1234 56 78", "%*d %*d %s", buf);
printf("buf=%s\n", buf);
sscanf("123 45678", "%*s %d", &num);
printf("buf=%d\n", num);
sscanf("1234 5678", "%*d %d", &num);
printf("buf=%d\n", num);
return 0;
}
buf=78
buf=45678
buf=5678
sscanf高级用法2
2、读指定宽度的数据:%[width]s
例:sscanf(“12345678”,“%4s”,buf);
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
int num;
sscanf("12345678", "%s", buf);
printf("buf=%s\n", buf);
sscanf("12345678", "%5s", buf);
printf("buf=%s\n", buf);
sscanf("12345678", "%3d", &num);
printf("num=%d\n", num);
return 0;
}
buf=12345678
buf=12345
num=123
sscanf高级用法3
3、支持集合操作:只支持获取字符串
%[a-z] 表示匹配a到z中任意字符(尽可能的多匹配)
#include
#pragma warning(disable : 4996)
int main()
{
char buf[10];
sscanf("abdw345mnytUTadf", "%[a-z]", buf);
printf("buf=%s\n", buf);
sscanf("abdz w345mnytUTadf", "%[a-z]", buf);
printf("buf=%s\n", buf);
sscanf("abdewzw345mnytUTadf", "%[a-f]", buf);
printf("buf=%s\n", buf);
}
buf=abdw
buf=abdz
buf=abde
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wE8mWZeQ-1649660664501)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411100141236.png)]
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
sscanf("ad05Fkl78adf9Faljs", "%[ad05Fk]", buf);
printf("buf=%s\n", buf);
return 0;
}
buf=ad05Fk
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
sscanf("ad05Fkl78adf9Faljs", "%[^k ]", buf);
printf("buf=%s\n", buf);
sscanf("ad0 5Fkl78adf9Faljs", "%[^k]", buf);
printf("buf=%s\n", buf);
return 0;
}
buf=ad05F
buf=ad0 5F
sscanf高级用法4
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
sscanf("asdf#sdjh@djkd", "%*[^#]%*c%*[^@]%*c%s", buf);
printf("buf=%s\n", buf);
return 0;
}
buf=djkd
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nm4DC4LE-1649660664501)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411114132521.png)]
1.实现strlen函数功能
#include
#pragma warning(disable : 4996)
unsigned int my_strlen(const char *s)
{
char *p = s;
while (*p != '\0')
{
p++;
}
return p - s;
}
int main()
{
int num;
num = my_strlen("helloworld");
printf("num = %d\n", num);
}
2、实现strcpy函数功能
#include
#pragma warning(disable : 4996)
char *my_strcpy(char *dest, const char *src)
{
char *p1 = dest;
const char *p2 = src;
while (*p2 != '\0')
{
*p1 = *p2;
p1++;
p2++;
}
*p1 = '\0';
return dest;
}
int main()
{
char buf[100];
my_strcpy(buf, "hello world");
printf("buf=%s\n", buf);
return 0;
}
#include
#pragma warning(disable : 4996)
int my_atoi(const char *str)
{
const char *s = str;
int temp = 0;
while (*s != '\0')
{
temp = temp * 10 + (*s - '0');
s++;
}
return temp;
}
int main()
{
int num;
char buf[100] = "123456789";
printf("buf=%s\n", buf);
num = my_atoi(buf);
printf("num =%d\n", num);
return 0;
}
buf=123456789
num =123456789
4、使用sscanf读取"[ti:简单爱]" ":“号与”]"之间的内容
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100] = "[ti:简单爱]";
char buf1[100];
sscanf(buf, "%*[^:]%*c%[^]]", buf1);
printf("buf1=%s\n", buf1);
}
buf1=简单爱
5、使用 sscanf读取"[02:06:85]" 02(代表分钟) 06(代表秒) 到整型变量min 、 sec 中
#include
#pragma warning(disable : 4996)
int main()
{
int min, sec;
sscanf("[02:06.85]", "[%2d:%2d", &min, &sec);
printf("&min=%02d\n", min);
printf("&min=%02d\n", sec);
}
&min=02
&min=06
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1e4qXAoa-1649660664501)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411142500984.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str = "helloworldhelloworldhelloworldhelloworld";
int num = 0;
char *p;
char *q = str;
while ((p = strchr(q, 'w')) != NULL)
{
num++;
printf("第%d个w的位置:%d\n", num, p - str);
q = p + 1;
}
printf("总共找到%d个w\n", num);
return num;
}
第1个w的位置:5
第2个w的位置:15
第3个w的位置:25
第4个w的位置:35
总共找到4个w
8.11 const:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7Pv78gfZ-1649660664502)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411105613475.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-BVFirm1O-1649660664502)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411105920944.png)]
char buf[20] = "helloworld";
const char *str = buf;
strcpy(str, "hello kitty!");
printf("buf=%s\n", buf);
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20] = "helloworld";
char *const str = buf;
printf("str=%s\n", str);
*str = 'w';
printf("str=%s\n", str);
return 0;
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-RIpZsWbP-1649660664502)(C:\Users\宁智波带土\AppData\Roaming\Typora\typora-user-images\image-20220411111236229.png)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20] = "helloworld";
char *const str = buf;
printf("str=%s\n", str);
return 0;
}
第九章 结构体
; //一旦不在adf这个范围就停止输入
printf(“buf=%s\n”, buf);
return 0;
}
buf=ad05Fk
```c
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
//匹配%[^k]遇到这个字符则停止输入
sscanf("ad05Fkl78adf9Faljs", "%[^k ]", buf); //一旦遇到k字符就停止获取
printf("buf=%s\n", buf);
sscanf("ad0 5Fkl78adf9Faljs", "%[^k]", buf); //空格也能打印出来,遇到k则停止
printf("buf=%s\n", buf);
return 0;
}
buf=ad05F
buf=ad0 5F
sscanf高级用法4
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20];
sscanf("asdf#sdjh@djkd", "%*[^#]%*c%*[^@]%*c%s", buf);
printf("buf=%s\n", buf);
return 0;
}
buf=djkd
[外链图片转存中…(img-nm4DC4LE-1649660664501)]
1.实现strlen函数功能
#include
#pragma warning(disable : 4996)
unsigned int my_strlen(const char *s)
{
char *p = s;
while (*p != '\0')
{
p++;
}
return p - s;
}
int main()
{
int num;
num = my_strlen("helloworld");
printf("num = %d\n", num);
}
2、实现strcpy函数功能
#include
#pragma warning(disable : 4996)
char *my_strcpy(char *dest, const char *src)
{
char *p1 = dest;
const char *p2 = src;
while (*p2 != '\0')
{
*p1 = *p2;
p1++;
p2++;
}
*p1 = '\0';
return dest;
}
int main()
{
char buf[100];
my_strcpy(buf, "hello world");
printf("buf=%s\n", buf);
return 0;
}
#include
#pragma warning(disable : 4996)
int my_atoi(const char *str)
{
const char *s = str;
int temp = 0;
while (*s != '\0')
{
temp = temp * 10 + (*s - '0');
s++;
}
return temp;
}
int main()
{
int num;
char buf[100] = "123456789";
printf("buf=%s\n", buf);
num = my_atoi(buf);
printf("num =%d\n", num);
return 0;
}
buf=123456789
num =123456789
4、使用sscanf读取"[ti:简单爱]" ":“号与”]"之间的内容
#include
#pragma warning(disable : 4996)
int main()
{
char buf[100] = "[ti:简单爱]";
char buf1[100];
sscanf(buf, "%*[^:]%*c%[^]]", buf1);
printf("buf1=%s\n", buf1);
}
buf1=简单爱
5、使用 sscanf读取"[02:06:85]" 02(代表分钟) 06(代表秒) 到整型变量min 、 sec 中
#include
#pragma warning(disable : 4996)
int main()
{
int min, sec;
sscanf("[02:06.85]", "[%2d:%2d", &min, &sec);
printf("&min=%02d\n", min);
printf("&min=%02d\n", sec);
}
&min=02
&min=06
[外链图片转存中…(img-1e4qXAoa-1649660664501)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char *str = "helloworldhelloworldhelloworldhelloworld";
int num = 0;
char *p;
char *q = str;
while ((p = strchr(q, 'w')) != NULL)
{
num++;
printf("第%d个w的位置:%d\n", num, p - str);
q = p + 1;
}
printf("总共找到%d个w\n", num);
return num;
}
第1个w的位置:5
第2个w的位置:15
第3个w的位置:25
第4个w的位置:35
总共找到4个w
8.11 const:
[外链图片转存中…(img-7Pv78gfZ-1649660664502)]
[外链图片转存中…(img-BVFirm1O-1649660664502)]
char buf[20] = "helloworld";
const char *str = buf;
strcpy(str, "hello kitty!");
printf("buf=%s\n", buf);
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20] = "helloworld";
char *const str = buf;
printf("str=%s\n", str);
*str = 'w';
printf("str=%s\n", str);
return 0;
}
[外链图片转存中…(img-RIpZsWbP-1649660664502)]
#include
#include
#pragma warning(disable : 4996)
int main()
{
char buf[20] = "helloworld";
char *const str = buf;
printf("str=%s\n", str);
return 0;
}
第九章 结构体