目录
char arr[] = { 'a','b','c','d','e','f' }
写在前面
在开始前我们要注意两个知识点:
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 <stdio.h> 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; }
指针与字符指针
char arr[] = { 'a','b','c','d','e','f' }
解析
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停止 随机
char arr[] = "abcdef"
分析
"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
char* p = "abcdef"
分析
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
通过这些奇形怪状的试题,我们一步一步的解析,到现在想必大家对与指针与数组已经门清了儿叭!