网站建设中心联系方式,自己做的一个网站怎么赚钱,广告联盟平台入口,天柱县住房和城乡建设部网站引言#xff1a;
对指针知识进行简单的回顾#xff0c;然后再完成笔试题。 ✨ 猪巴戒#xff1a;个人主页✨ 所属专栏#xff1a;《C语言进阶》 #x1f388;跟着猪巴戒#xff0c;一起学习C语言#x1f388; 目录
引言#xff1a;
知识简单回顾
指针是什么
指针变…引言
对指针知识进行简单的回顾然后再完成笔试题。 ✨ 猪巴戒个人主页✨ 所属专栏《C语言进阶》 跟着猪巴戒一起学习C语言 目录
引言
知识简单回顾
指针是什么
指针变量的大小
指针类型的意义
指针的运算
指针数组
数组名是什么
数组指针
函数指针
函数指针数组
回调函数
笔试题
一维数组
题目
解析
总结
字符数组
题目1
解析
题目2
解析 总结
题目3
解析
总结
题目4
解析
总结
题目5
答案
题目6
答案 知识简单回顾
指针是什么
内存 -内存的单元1byte-编号-地址 我们有一块很大的内存空间内存空间被分为一个一个的单元一个内存单元的大小是1byte(字节)每个字节都有它的编号这个编号就是地址地址又叫做指针。 指针就是一个地址。
我们口头语说的指针一般指指针变量
指针变量就是一个变量就是一块内存空间指针变量用来存放地址。 a就是内存的编号也是地址. 这个指针变量叫做pa,int*是类型整形指针通过这个类型创造的变量叫做pa。 *pa就是对pa进行解引用通过pa存放的地址找到它所指向的对象a,pa存的是a的地址所以pa指向a,*pa其实就是a。 *pa 20就相当于 a 20将 a 的值改变了。 int main()
{int a 0;int* pa a;*pa 20;return 0;
} 指针变量的大小 ——4/8个字节取决于编译器是x86环境还是x64环境 指针类型的意义
两件事情
1.指针类型进行1/-1的操作时它会跳过几个字节。
2.进行解引用操作的时候决定了解引用操作时候的权限访问多少个字节 指针的运算
1。-整数
2.指针-指针
3.指针的关系运算 指针数组
本质上就是数组数组中存放的是指针地址。
arr 存放了三个元素每个元素都是int*类型也就是指针那么arr就是指针数组。
int main()
{int *pa;int *pb;int *pc;int* arr { pa,pb,pc };return 0;
} 数组名是什么
1.数组名在大部分情况下表示数组首元素的地址
但是有两个例外
asizeof数组名表示的是整个数组的大小
b数组名取出的是整个数组的地址 数组指针
数组名这里的parr ,存放的是数组的地址parr为数组指针。
数组指针int (*parr)[10]parr与*结合代表parr为指针[10]表示parr指向数组数组中元素的类型是int。
指针数组int* parr[10],没有括号parr与[10]结合表示parr为数组数组中元素的类型是int*(整形指针)
数组指针类型的表示int (*)[10];
int arr[10] {1,2,3};
int (*parr)[10] arr;函数指针
函数指针就是函数的地址函数也有地址我们可以通过函数的地址去使用函数。
函数的地址存放在函数指针变量中
函数指针类型表示
int (*)(int,int)
int (*pf)(int ,int)pf与*结合表示pf是指针指针指向的是(int , int)参数是两个整形的函数函数的返回类型是int。
int Add(int x,int y)
{return x y;
}int main()
{int (*pf)(int ,int) Add;int sum (*pf)(2,3);//Add 和 函数名一样Add也可以直接表示为地址,因此也可以写成这种形式//int (*pf)(int ,int) Add;//Add传给了pfpf 等同于 Add ,那么我们也可以这样写。 //int sum pf(2.3)return 0;
} 函数指针数组
存放函数指针的数组。
我们将函数指针数组命名为arrarr数组的每个元素的类型是int (*)(int,int) 函数指针数组的类型表示 int *[4])(int,int) 怎么理解这函数指针数组的形式 arr与[4]结合说明arr是数组这个数字的每个元素是int(*)(int,int),而这正好是函数指针类型。 int *arr[4])(int,int) {Add,Sub,Div,Mul}; 回调函数
通过函数指针调用的函数就是回调函数。
这里的函数指针是pfpf指向的函数是Add通过pf调用Add我们称Add为回调函数。
int Add(int x,int y)
{return x y;
}int main()
{int (*pf)(int ,int) Add;int sum pf(2.3);return 0;
} 笔试题
一维数组
题目
以下打印的结果分别是什么 int a[] {1,2,3,4};
1|printf(%d\n,sizeof(a));
2|printf(%d\n,sizeof(a0));
3|printf(%d\n,sizeof(*a));
4|printf(%d\n,sizeof(a1));
5|printf(%d\n,sizeof(a[1]));
6|printf(%d\n,sizeof(a));
7|printf(%d\n,sizeof(*a));
8|printf(%d\n,sizeof(a1));
9|printf(%d\n,sizeof(a[0]));
10|printf(%d\n,sizeof(a[0]1)); 数组名的理解指针的运算和指针类型的意义 解析
1.printf ( %d\n , sizeof ( a ) ); 16 sizeof(数组名数组名表示整个数组计算的是整个数组的大小单位是字节 2.printf ( %d\n , sizeof( a0 ) ); 4 / 8 a不是单独放在sizeof内部也没有取地址所以a就是首元素的地址a0还是首元素的地址。是地址大小就是4 / 8个字节。地址的大小和环境有关32位的系统环境就是4个字节64位系统环境就是8个字节。 3.printf ( %d\n , sizeof( *a ) ); 4 *a中的a是数组数组首元素的地址*a就是对首元素的地址解引用找到的就是首元素 首元素是整形所占内存大小是4个字节 4.printf ( %d\n , sizeof( a1 ) ); 4 / 8 a不是单独放在sizeof的内部a表示的是首元素的地址a1就是数组第二个元素的地址 地址的大小是4个字节或者8个字节。 5.printf ( %d\n , sizeof( a[1] ) ); 4 a[1]表示的是数组的第二个元素作为整形元素的大小为4个字节 6.printf ( %d\n , sizeof( a ) ); 4 / 8 a,数组名这里的a表示的是整个数组的地址一共4个元素地址的大小是4个字节。虽然说是整个数组的地址但是还是通过首元素的地址来表达。 注意首元素的地址和数组的地址虽然表现是同一个地址但是它们的运算的结果是不一样的。
比如a1和a1,一个表示的是跳过了一个4个整形元素的数组的地址一个表示的是数组第二个元素的地址 7.printf ( %d\n , sizeof( *a ) ); 16 a取的是整个数组的地址对a进行解引用得到的是整个数组一共4个元素一个整形元素的大小为4个字节一共是16个字节 8.printf ( %d\n , sizeof( a1 ) ); 4 / 8 数组名取的是整个数组的地址a再加上1就是跳过一个数组的位置然后再取了一个相同大小数组的地址。a1还是地址地址的大小就是4 / 8个字节。 9.printf ( %d\n , sizeof( a[0] ) ); 4 / 8 a[0]取的是数组第一个元素的地址大小是4个字节或者8个字节。 10.printf ( %d\n , sizeof( a[0]1 ) ); 4 / 8 a[0],取的是数组第一个元素的地址a[0]1就是数组第二个元素的地址。大小是4个字节或者8个字节。 总结
1.数组名大多数表示首元素的地址有两个例外1.sizeof数组名2.数组名。数组名表示的是整个数组 。
2.不同类型地址跳过的字节不一样a1a表示的是整个数组1就会跳过一个数组的大小。a[0]1,a[0]是数组第一个元素的地址所以1跳过的是一个元素的大小。
3.地址意义可能不同但是地址的大小都是4 / 8个字节。 字符数组
题目1
以下打印的结果是什么
char arr[] {a,b,c,d,e,f};
1|printf(%d\n,sizeof(arr));
2|printf(%d\n,sizeof(arr0));
3|printf(%d\n,sizeof(*arr));
4|printf(%d\n,sizeof(arr[1]));
5|printf(%d\n,sizeof(arr));
6|printf(%d\n,sizeof(arr1));
7|printf(%d\n,sizeof(arr[0]1));解析
1| printf ( %d\n , sizeof ( arr ) ) 6 sizeof(数组名)取的是整个数组的大小字符数组arr一共6个元素所以大小为6个字节。 2|printf ( %d\n , sizeof( arr0 ) ) 4 / 8 arr并没有单独放在sizeof内部所以arr表示首元素的地址arr0也表示首元素的地址。是地址那么大小就为4个字节或者8个字节。 3|printf ( %d\n ,sizeof ( *arr ) ) 1 arr是首元素的地址就是 ‘a’ 的地址然后解引用就是‘a’char类型大小是1个字节。 *arr 等价于arr [ 0 ] *(arr0) 等价于 arr [ 0 ] 4|printf ( %d\n , sizeof( arr[1] ) ) 1 arr[1]是数组第二个元素‘b大小是1个字节。 5|printf ( %d\n , sizeof( arr ) ) 4 / 8 arr取的是数组的地址是地址就是4 / 8 个字节。 6|printf ( %d\n , sizeof( arr1 ) ) 4 / 8 arr取的是arr数组的地址arr1跳过一个6个字符元素的数组下图是arr1的地址位置是地址大小就是4个字节或者8个字节。 7|printf ( %d\n , sizeof( arr[0]1 ) ) 4 / 8 arr[0]取的是数组第一个元素的地址arr[0]1就是第二个元素的地址是地址就是4个字节或者8个字节。 题目2
以下的打印结果分别是什么
char arr[] {a,b,c,d,e,f};
1|printf(%d\n,strlen(arr));
2|printf(%d\n,strlen(arr0));
3|printf(%d\n,strlen(*arr));
4|printf(%d\n,strlen(arr[1]));
5|printf(%d\n,strlen(arr));
6|printf(%d\n,strlen(arr1));
7|printf(%d\n,strlen(arr[0]1));
解析
strlen
用来求字符串长度的库函数参数是地址从参数传来的地址开始直到有 \0 停止。 1|printf ( %d\n , strlen ( arr ) ) 随机值 arr为数组首元素的地址字符数组没有 \0 ,strlen会运行完数组还会继续运行直到遇到 \0,但是数组外的元素不由数组控制也就是说 \0 什么时候出现是不可知的所以会打印随机值。 下图遇到 \0 前一共19个元素所以打印结果为19。 \0 的ASCII的数字就是0. 2|printf ( %d\n , strlen ( arr0 ) ) 随机值 arr0也是首元素的地址其实和前面问题的随机值是一样的。这里也将会在第20个元素遇到 ‘\0’所以这里的随机值与 1| 一样。 3|printf ( %d\n , strlen ( *arr ) ) 访问冲突 strlen的参数是地址而*arr传过去的是 ’a‘ ’a的ASCII值为97不是一个地址就会发生访问冲突也就是野指针问题。 4|printf ( %d\n , strlen ( arr[1] ) ) 访问冲突 和前面一个问题产生的结果一样既然strlen函数的参数是地址将值传过去就会产生野指针的问题。 5|printf ( %d\n , strlen ( arr ) ) 随机值 arr传过去的是整个数组的地址strlen用const char* str来接收那么strlen又是怎么运行的呢这里的地址和1|、2|类型不同但是地址的位置是相同的strlen也应该是从首元素开始一个一个筛查直到遇到 ‘\0’ 求字符串才算结束。所以这里和1|、2|的结果应该是一样的。 6|printf ( %d\n , strlen ( arr1 ) ) 随机值 - 6 arr1arr取的是整个数组的地址arr1会跳过一个6个char类型元素的数组下图标记arr1的地址位置strlen函数也就是从这里开始运行直到遇到 ‘\0’ ,那么这里的结果就会比1|、2|、5|的结果少6个元素。结果随机值 - 6 7|printf ( %d\n , strlen ( arr[0]1 ) ) 随机值 - 1 arr[0]取的是数组第一个元素的地址arr[0]1就是数组第二个元素的地址从第二个元素开始strlen遇到 \0 停止就会比1|、2|、5|的结果少1个元素。结果随机值 - 1. 总结
1.strlenconst char* str传递的参数是地址如果传递数值的话就会产生访问冲突的问题。
2.strlen不管地址的类型只管地址的位置从地址的位置开始逐个去数字符直到遇到 \0 ,strlen就停止运行求出字符串的长度。 题目3
以下打印的结果是什么
char arr[] abcdef;
1|printf(%d\n,sizeof(arr));
2|printf(%d\n,sizeof(arr0));
3|printf(%d\n,sizeof(*arr));
4|printf(%d\n,sizeof(arr[1]));
5|printf(%d\n,sizeof(arr));
6|printf(%d\n,sizeof(arr1));
7|printf(%d\n,sizeof(arr[0]1));
解析
char arr[] abcdef,这个数组的元素为[ a b c d e f \0 ],一共7个元素字符串默认以 \0 结尾。
1|printf ( %d\n , sizeof ( arr ) ) 7 sizeof(数组名)这里的数组名表示的是整个数组因为字符串默认为 ‘\0’ 结尾所以这个数组有7个元素结果为7个字节。 2|printf ( %d\n , sizeof ( arr0 ) ) 4 / 8 arr表示的是首元素的地址arr0表示首元素的地址是地址地址的大小为4个字节或者8个字节。 3|printf ( %d\n , sizeof ( *arr ) ) 1 arr表示首元素的地址*arr取的是‘a’,大小为1个字节。 4|printf ( %d\n , sizeof ( arr[1] ) ) 1 arr[1]为数组的第二个元素‘b’大小为1个字节。 5|printf ( %d\n , sizeof ( arr ) ) 4 / 8 arr取的是整个数组的地址地址的大小为4个字节或者8个字节。 6|printf ( %d\n , sizeof ( arr1 ) ) 4 / 8 arr取的是整个数组的地址arr1跳过1个7个元素的数组跳过一个数组但是地址的类型是不变的是还是一个数组的地址不过既然是地址地址的大小为4个字节或者8个字节。 7|printf ( %d\n , sizeof ( arr[0]1 ) ) 4 / 8 arr[0]取的是数组第一个元素的地址arr1就是数组第二个元素的地址地址的大小为4个字节或者8个字节。 总结
1.不管地址的类型是什么只要是地址地址的大小就是4个字节或者8个字节。
2.字符串相当于普通的字符数组但是字符串通常默认 \0 为结尾。
3.sizeof 只关注占用内存空间的大小不在乎内存中放的是什么。 题目4
以下打印的结果是什么
char arr[] abcdef;
1|printf(%d\n,strlen(arr));
2|printf(%d\n,strlen(arr0));
3|printf(%d\n,strlen(*arr));
4|printf(%d\n,strlen(arr[1]));
5|printf(%d\n,strlen(arr));
6|printf(%d\n,strlen(arr1));
7|printf(%d\n,strlen(arr[0]1));
解析 char arr[] abcdef,这个数组的元素为[ a b c d e f \0 ],一共7个元素字符串默认以 \0 结尾。 strlen是求字符串长度的关注的是字符串中的 \0 计算的是 \0 之前出现的字符的个数。 1|printf ( %d\n , strlen ( arr ) ) 6 arr是首元素的地址遇到 \0 停止。结果6 2|printf ( %d\n , strlen ( arr0 ) ) 6 3|printf ( %d\n , strlen ( *arr ) ) 访问冲突 传递的不是地址。 4|printf ( %d\n , strlen ( arr[1] ) ) 访问冲突 传递的不是地址。 5|printf ( %d\n , strlen ( arr ) ) 6 取的是整个数组的地址但是地址位置是首元素的地址。 6|printf ( %d\n , strlen ( arr1 ) ) 随机值 跳过了一个数组\0也包括在这个数组里面strlen就会往下去寻找 \0 ,结果会是随机值。 7|printf ( %d\n , strlen ( arr[0]1 ) ) 5 从第二个元素开始后面遇到 \0,一共是5个元素。 总结
1. strlen是求字符串长度的关注的是字符串中的 \0 计算的是 \0 之前出现的字符的个数。
2.sizeof 只关注占用内存空间的大小不在乎内存中放的是什么。 题目5
char* p abcdef;
1|printf(%d\n,sizeof(p));
2|printf(%d\n,sizeof(p1));
3|printf(%d\n,sizeof(*p));
4|printf(%d\n,sizeof(p[0]));
5|printf(%d\n,sizeof(p));
6|printf(%d\n,sizeof(p1));
7|printf(%d\n,sizeof(p[0]1));
答案 这里的“abcdef”并不是数组而是常量字符串常量字符串在内存中有独立的地址。p接收的是首元素’a‘的地址。 1|printf ( %d\n , sizeof ( p ) ) 4 / 8
p是 指针变量存放的是’a‘的地址。地址的大小为4个字节或者8个字节。 2|printf ( %d\n , sizeof ( p1 ) ) 4 / 8 p1是地址。 3|printf ( %d\n , sizeof ( *p ) ) 1 *p是 ’a‘大小是1个字节 4|printf ( %d\n , sizeof ( p[0] ) ) 1 p[0]是’a‘大小是1个字节。 5|printf ( %d\n , sizeof ( p ) ) 随机值 p是地址p是指针变量p存放的是常量字符串首元素’a‘的地址但是p的地址与常量字符串没有关系p的地址属于二级指针一级指针的地址。所以是随机值。 6|printf ( %d\n , sizeof ( p1 ) ) 4 / 8 p1是地址。所以大小为4个字节或者8个字节。 7|printf ( %d\n , sizeof ( p[0]1 ) ) 4 / 8 p[0]1是地址。p[0]就是‘a’的地址1就是‘b’的地址。 题目6
char* p abcdef;
1|printf(%d\n,strlen(p));
2|printf(%d\n,strlen(p1));
3|printf(%d\n,strlen(*p));
4|printf(%d\n,strlen(p[0]));
5|printf(%d\n,strlen(p));
6|printf(%d\n,strlen(p1));
7|printf(%d\n,strlen(p[0]1));
答案
1|printf ( %d\n , strlen( p ) ) 6 p是首元素‘a’的地址往后6个元素到 \0 停止。 2|printf ( %d\n , strlen( p1 ) ) 5 p1是第二个元素的地址往后5个元素到 \0 停止。 3|printf ( %d\n , strlen ( *p ) ) 访问冲突 strlen的参数为地址。 4|printf ( %d\n , strlen ( p[0] ) ) 访问冲突 strlen的参数为地址。 5|printf ( %d\n , strlen ( p ) ) 随机值 p是一级指针p就是二级指针。p的地址和常量字符串“abcdef”没有关系。 6|printf ( %d\n , strlen( p1 ) ) 随机值 - 1 p取的是p的地址p指向p的下一位。 7|printf ( %d\n , strlen ( p[0]1 ) ) 5 p[0]就是’a‘,p[0]取出了’a‘的地址p[0]1就是’b‘的地址。 strlen从’b‘开始往后数一直数到 \0为止一共是5个元素。