作者主页:paper jie的博客_CSDN博客-C语言,算法详解领域博主
本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。
本文录入于《系统解析C语言》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将C语言基础知识一网打尽,希望可以帮到读者们哦。
其他专栏:《C语言》《算法详解》《C语言-语法篇》
内容分享:本期对C语言中的指针的进阶知识进行进行具体讲解,各位看官姥爷快搬好小板凳坐好叭。
-------- 不要998,不要98,只要一键三连,三连买不了吃亏,买不了上当
目录
写在前面
指针与一维数组
解析:
代码
指针与字符指针
char arr[] = { 'a','b','c','d','e','f' }
解析
代码
char arr[] = "abcdef"
分析
代码
char* p = "abcdef"
分析
代码
指针与二维数组
分析
代码
在开始前我们要注意两个知识点:
1. sizeof(数组名),这里的数组名表示的是整个数组,计算的是整个数组的大小
2. &数组名,这里的数组名表示的是整个数组,取出的是整个数组的大小
3. 除此之外,其他的数组名都是首元素的地址
sizeof(a) 计算的是整个数组的大小 。
sizeof(a+0): a不是sizeof(a),也不是&a 所以他是首元素地址 +0,它是1的地址 是一个整型指针 4个字节 。
sizeof(*a): *a就是1 1是一个整型 sizeof(*a) = 4。
sizeof(a+1): a+1 是首元素的地址加一 跳过一个整型,是2的地址 还是一个整型指针 4个字节。
sizeof(a[1]): a[1]=2 2是整型 4个字节。
sizeof(&a): &a取出的是整个数组 但它本质上还是一个整型指针 4个字节。
sizeof(*&a): &a取出的是整个数组 解引用得到的是整个数组的内容 里面有4个整型。
sizeof(&a+1): &a+1是跳过这个数组指向后面的内容 但还是一个指针 .。
sizeof(&a[0]): &a[0]是取出a[0]的地址 是一个整型指针。
sizeof(&a[0]+1): &a[0]+1 是a[1]的地址 是一个整型指针.
#include
int main()
{
int a[] = { 1,2,3,4 };
printf("%d\n", sizeof(a));
//16
//sizeof(a) 计算的是整个数组的大小
printf("%d\n", sizeof(a + 0));
//4
//a不是sizeof(a),也不是&a 所以他是首元素地址 +0
//它是1的地址 是一个整型指针 4个字节
printf("%d\n", sizeof(*a));
//4
//*a就是1 1是一个整型 sizeof(*a) = 4
printf("%d\n", sizeof(a + 1));
//4
//a+1 是首元素的地址加一 跳过一个整型
//是2的地址 还是一个整型指针 4个字节
printf("%d\n", sizeof(a[1]));
//4
//a[1]=2 2是整型 4个字节
printf("%d\n", sizeof(&a));
//4
//&a取出的是整个数组 但它本质上还是一个整型指针 4个字节
printf("%d\n", sizeof(*&a));
//16
//&a取出的是整个数组 解引用得到的是整个数组的内容 里面有4个整型
printf("%d\n", sizeof(&a + 1));
//4
//&a+1是跳过这个数组指向后面的内容 但还是一个指针
printf("%d\n", sizeof(&a[0]));
//4
//&a[0]是取出a[0]的地址 是一个整型指针
printf("%d\n", sizeof(&a[0] + 1));
//&a[0]+1 是a[1]的地址 是一个整型指针
return 0;
}
arr 是计算整个数组的大小,6个char类型 6
arr+0 首元素地址加0 指向的还是a 它是一个地址就是指针,是指针就是4个字节
*arr arr是首元素的地址,解引用就是a 计算的就是首元素a的大小 char类型 1
arr[1] 是第二个元素,计算的是第二个元素的大小 1
&arr 取出的是整个数组 但它本质是一个char指针 计算的就是一个cha类型的指针r
&arr+1 取出整个数组的地址再加1,跳过整个数组 这是一个指向数组后一个元素的指针
&arr[0]+1 取出第一个元素的地址加1 就是第二个元素的地址,本质上还是一个指针
strlen(arr) arr是首元素地址 计算的是arr数组元素的个数,从第一个元素开始计算在遇到\0不会停止,arr数组没有\0 它是一个随机值
strlen(arr+0) arr+0是首元素的地址 从第一个元素开始计算到\0停止 arr数组没有\0 随机值
strlen(*arr) 是第一个元素是一个字符 但是strlen函数的参数需要一个指针类型 所以err
strlen(arr[1]) arr[1]是一个字符 不合strlen需要的参数
strlen(&arr) 取出的是整个数组 本质上还是一个指针,等于首元素的地址,arr数组里没有\0 它是一个随机值
strlen(&arr+1) &arr+1是跳过整个数组,指向数组后面的内容 从这里开始计算,遇到\0停止 随机
strlen(&arr(&arr[0]+1) &arr[0]+1取出第二个元素的地址 从第二个元素开始计算,遇到\0停止 随机
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", sizeof(arr));
//6
//arr 是计算整个数组的大小,6个char类型 6
printf("%d\n", sizeof(arr + 0));
//arr+0 首元素地址加0 指向的还是a 它是一个地址就是指针,是指针就是4个字节
printf("%d\n", sizeof(*arr));
//1
//*arr arr是首元素的地址,解引用就是a 计算的就是首元素a的大小 char类型 1
printf("%d\n", sizeof(arr[1]));
//1
//arr[1] 是第二个元素,计算的是第二个元素的大小 1
printf("%d\n", sizeof(&arr));
//4
//&arr 取出的是整个数组 但它本质是一个char指针 计算的就是一个cha类型的指针r
printf("%d\n", sizeof(&arr + 1));
//4
//&arr+1 取出整个数组的地址再加1,跳过整个数组 这是一个指向数组后一个元素的指针
printf("%d\n", sizeof(&arr[0] + 1));
//4
//&arr[0]+1 取出第一个元素的地址加1 就是第二个元素的地址,本质上还是一个指针
printf("%d\n", strlen(arr));
//随机值
//strlen(arr) arr是首元素地址 计算的是arr数组元素的个数,从第一个元素开始计算在遇到\0不会停止,arr数组没有\0 它是一个随机值
printf("%d\n", strlen(arr + 0));
//随机值
//strlen(arr+0) arr+0是首元素的地址 从第一个元素开始计算到\0停止 arr数组没有\0 随机值
printf("%d\n", strlen(*arr));
//err
//strlen(*arr) 是第一个元素是一个字符 但是strlen函数的参数需要一个指针类型 所以err
printf("%d\n", strlen(arr[1]));
//err
//strlen(arr[1]) arr[1]是一个字符 不合strlen需要的参数
printf("%d\n", strlen(&arr));
//随机值
//strlen(&arr) 取出的是整个数组 本质上还是一个指针,等于首元素的地址,arr数组里没有\0 它是一个随机值
printf("%d\n", strlen(&arr + 1));
//随机值
//strlen(&arr+1) &arr+1是跳过整个数组,指向数组后面的内容 从这里开始计算,遇到\0停止 随机
printf("%d\n", strlen(&arr[0] + 1));
//strlen(&arr(&arr[0]+1) &arr[0]+1取出第二个元素的地址 从第二个元素开始计算,遇到\0停止 随机
"abcdef"里面包含的有:a b c d e f \0
arr sizeof(arr)是计算整个数组的大小 arr数组里面隐藏了\0 ,得算上\0 7
arr+0 是首元素的地址 计算的就是一个地址的大小 4
*arr 是首元素 计算的就是一个char类型 1
arr[1] 是第二个元素 计算的是一个char类型 1
&arr 取出的是整个数组 它是一个地址 计算的就是地址的大小 4
&arr+1 数组的地址+跳过一个数组 它还是一个地址 计算的就是地址 4
&arr[0]+1 是第二个元素的地址 计算的就是地址 4
arr 计算的是整个数组的个数 strlen遇到\0停止 \0不加入计算 6
arr+0 是首元素的地址 它作为给strlen的参数 从首元素开始计算到\0停止 6
*arr *arr是首元素,它不是地址 strlen的参数要指针 所以err
arr[1] 是第二个元素,它不是地址 strlen的参数要指针 所以err
&arr 取出的是整个元素的大小 但它本质上还是和首元素地址一样 所以从首元素开始计算到\0停止 6
&arr+1 就是跳过整个数组,指向后面的空间,也跳过了数组中的\0, 所以从后面的空间开始到\0 是随机的
&arr[0]+1 是第二个元素的地址 就是从第二个元素开始计算到\0停止 5
char arr[] = "abcdef";
//里面包含的有:a b c d e f \0
printf("%d\n", sizeof(arr));
//7
//arr sizeof(arr)是计算整个数组的大小 arr数组里面隐藏了\0 ,得算上\0 7
printf("%d\n", sizeof(arr + 0));
//4
//arr+0 是首元素的地址 计算的就是一个地址的大小 4
printf("%d\n", sizeof(*arr));
//1
//*arr 是首元素 计算的就是一个char类型 1
printf("%d\n", sizeof(arr[1]));
//1
//arr[1] 是第二个元素 计算的是一个char类型 1
printf("%d\n", sizeof(&arr));
//4
//&arr 取出的是整个数组 它是一个地址 计算的就是地址的大小 4
printf("%d\n", sizeof(&arr + 1));
//4
//&arr+1 数组的地址+跳过一个数组 它还是一个地址 计算的就是地址 4
printf("%d\n", sizeof(&arr[0] + 1));
//4
//&arr[0]+1 是第二个元素的地址 计算的就是地址 4
printf("%d\n", strlen(arr));
//6
//arr 计算的是整个数组的个数 strlen遇到\0停止 \0不加入计算 6
printf("%d\n", strlen(arr + 0));
//6
//arr+0 是首元素的地址 它作为给strlen的参数 从首元素开始计算到\0停止 6
printf("%d\n", strlen(*arr));
//err
//*arr *arr是首元素,它不是地址 strlen的参数要指针 所以err
printf("%d\n", strlen(arr[1]));
//err
//arr[1] 是第二个元素,它不是地址 strlen的参数要指针 所以err
printf("%d\n", strlen(&arr));
//6
//&arr 取出的是整个元素的大小 但它本质上还是和首元素地址一样 所以从首元素开始计算到\0停止 6
printf("%d\n", strlen(&arr + 1));
//随机值
//&arr+1 就是跳过整个数组,指向后面的空间,也跳过了数组中的\0, 所以从后面的空间开始到\0 是随机的
printf("%d\n", strlen(&arr[0] + 1));
//5
//&arr[0]+1 是第二个元素的地址 就是从第二个元素开始计算到\0停止 5
p p是字符串首元素的地址 计算的就是一个指针 4
p+1 第二个字符的地址 计算的就是一个指针 4
*p 第一个字符 计算的是一个char类型 1
p[0] ==*(p+0) 第一个字符 计算的是一个char类型 1
&p &p是第一个字符的地址的地址 一个二级指针 计算就是一个指针 4
&p+1 是二级指针加1 跳过一个char**类型 还是一个指针 计算就是一个指针 4
&p[0]+1 第二个字符的地址 是一个指针 计算的就是一个指针 4
p 首字符的地址 strlen通过第一个字符地址向后计算,到\0停止
p+1 第二个字符的地址 strlen通过第二个字符地址向后计算 到\0停止
*p 首字符 strlen参数只接收指针 err
p[0] 首字符 strlen参数只接收指针 err
&p 是首元素的地址的地址 strlen计算的是首元素的地址 相当于地址变成了它要计算的内容 里面不知道有没有\0 就是随机值
&p+1 二级指针加1 strlen计算的是首元素的地址加一 它的内容还是一个指针 随机值
&p[0]+1 第二个元素的地址 从第二个元素开始计算遇到\0停止 5
char* p = "abcdef";
printf("%d\n", sizeof(p));
//4
//p p是字符串首元素的地址 计算的就是一个指针 4
printf("%d\n", sizeof(p + 1));
//4
//p+1 第二个字符的地址 计算的就是一个指针 4
printf("%d\n", sizeof(*p));
//1
//*p 第一个字符 计算的是一个char类型 1
printf("%d\n", sizeof(p[0]));
//1
//p[0] ==*(p+0) 第一个字符 计算的是一个char类型 1
printf("%d\n", sizeof(&p));
//4
//&p &p是第一个字符的地址的地址 一个二级指针 计算就是一个指针 4
printf("%d\n", sizeof(&p + 1));
//4
//&p+1 是二级指针加1 跳过一个char**类型 还是一个指针 计算就是一个指针 4
printf("%d\n", sizeof(&p[0] + 1));
//4
//&p[0]+1 第二个字符的地址 是一个指针 计算的就是一个指针 4
printf("%d\n", strlen(p));
//6
//p 首字符的地址 strlen通过第一个字符地址向后计算,到\0停止
printf("%d\n", strlen(p + 1));
//p+1 第二个字符的地址 strlen通过第二个字符地址向后计算 到\0停止
printf("%d\n", strlen(*p));
//err
//*p 首字符 strlen参数只接收指针 err
printf("%d\n", strlen(p[0]));
//err
//p[0] 首字符 strlen参数只接收指针 err
printf("%d\n", strlen(&p));
//随机值
//&p 是首元素的地址的地址 strlen计算的是首元素的地址 相当于地址变成了它要计算的内容 里面不知道有没有\0 就是随机值
printf("%d\n", strlen(&p + 1));
//随机值
//&p+1 二级指针加1 strlen计算的是首元素的地址加一 它的内容还是一个指针 随机值
printf("%d\n", strlen(&p[0] + 1));
//5
//&p[0]+1 第二个元素的地址 从第二个元素开始计算遇到\0停止 5
a sizeof(a)是计算整个二维数组的大小 12*4
a[0][0] 第一行的第一个元素 计算一个整型大小 4
a[0] 代表了数组第一行 可以理解为第一行的数组名 sizeof(数组名)整个数组的大小 16
a[0]+1 表示第一行第二个元素的地址 一个指针 4
*(a[0]+1) 表示第一行的第二个元素 一个整型 4
a+1 a是第一行的地址+1 第二行的地址 一个指针 4
*(a+1) 表示第二行的元素 4个整型 16
&a[0]+1 &a[0]是取出第一行的地址在加一 就是第二行的地址 4
*(&a[0]+1)第二行的地址解引用 得到第二行的4个元素 16
*a a是二维数组首元素的地址 就是第一行的地址 解引用 4个整型 16
a[3] 这里我们不管a[3]越界了 我们只要知道它的类型是一个int [4] sizeof求的就是类型 16
int a[3][4] = { 0 };
printf("%d\n", sizeof(a));
//48
//a sizeof(a)是计算整个二维数组的大小 12*4
printf("%d\n", sizeof(a[0][0]));
//4
//a[0][0] 第一行的第一个元素 计算一个整型大小 4
printf("%d\n", sizeof(a[0]));
//16
//a[0] 代表了数组第一行 可以理解为第一行的数组名 sizeof(数组名)整个数组的大小 16
printf("%d\n", sizeof(a[0] + 1));
//4
//a[0]+1 表示第一行第二个元素的地址 一个指针 4
printf("%d\n", sizeof(*(a[0] + 1)));
//
//*(a[0]+1) 表示第一行的第二个元素 一个整型 4
printf("%d\n", sizeof(a + 1));
//4
//a+1 a是第一行的地址+1 第二行的地址 一个指针 4
printf("%d\n", sizeof(*(a + 1)));
//16
//*(a+1) 表示第二行的元素 4个整型 16
printf("%d\n", sizeof(&a[0] + 1));
//4
//&a[0]+1 &a[0]是取出第一行的地址在加一 就是第二行的地址 4
printf("%d\n", sizeof(*(&a[0] + 1)));
//16
//*(&a[0]+1)第二行的地址解引用 得到第二行的4个元素 16
printf("%d\n", sizeof(*a));
//16
//*a a是二维数组首元素的地址 就是第一行的地址 解引用 4个整型 16
printf("%d\n", sizeof(a[3]));
//16
//a[3] 这里我们不管a[3]越界了 我们只要知道它的类型是一个int [4] sizeof求的就是类型 16
通过这些奇形怪状的试题,我们一步一步的解析,到现在想必大家对与指针与数组已经门清了儿叭!