指针和数组笔试题解析
#include<stdio.h> int main() { //一维数组 int a[] = { 1,2,3,4 }; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(a + 0)); printf("%d\n", sizeof(*a)); printf("%d\n", sizeof(a + 1)); printf("%d\n", sizeof(a[1])); printf("%d\n", sizeof(&a)); printf("%d\n", sizeof(*&a)); printf("%d\n", sizeof(&a + 1)); printf("%d\n", sizeof(&a[0])); printf("%d\n", sizeof(&a[0] + 1)); return 0; }
大家可以试着先分析一下结果是多少,分析错了不要紧,我逐个逐个给大家解释
首先这是一个数组,里面放的都是整型数据
数组元素的总大小是16个字节
sizeof(数组名)--数组名表示整个数组
&数组名---数组名表示整个数组
对于第一个sizeof(数组名),计算的是数组的总大小--单位是字节---16
对于第二个sizeof(a+0)结果是4,数组名在这里表示数组首元素的地址,a+0还是首元素的地址,地址的大小就是4/8个字节
对于第三个sizeof(*a)---数组名表示首元素的地址,*a就是首元素,sizeof(*a)就是4
对于第四个sizeof(a+1)--数组名在这里表示首元素的地址,a+1是第二个元素的地址,地址的大小就是4/8个字节
对于第五个sizeof(a【1】)--第二个元素的大小--4
对于第六个sizeof(&a)--&a取出的是数组的地址,但是数组的地址那也是地址,地址的大小就是4/8个字节
对于第七个sizeof(*&a)--16---&a数组的地址,数组的地址解引用访问的数组,sizeof计算的就是数组的大小--单位是字节
对于第八个sizeof(&a+1)--&a是数组的地址,&a+1虽然地址跳过整个数组,但还是地址,所以是4/8个字节
对于第九个sizeof(&a【0】)--&a【0】是第一个元素的地址
对于最后一个sizeof(&a【0】+1)--&a【0】+1是第二个元素的地址
我们把代码结果运行给大家看一下
X86平台演示的结果
X64平台演示的结果
下面我们来看字符数组
#include<stdio.h> int main() { //字符数组 char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(arr + 0)); printf("%d\n", sizeof(*arr)); printf("%d\n", sizeof(arr[1])); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(&arr + 1)); printf("%d\n", sizeof(&arr[0] + 1)); return 0; }
我们还是一个一个来分析
对于第一个sizeof(arr)--计算的是数组的大小,6*1=6个字节
对于第二个sizeof(arr+0)--arr是首元素的地址,arr+0还是首元素的地址,地址的大小是4/8个字节
对于第三个sizeof(*arr)--arr是首元素的地址,*arr就是首元素,首元素是字符大小是一个字节
对于第四个sizeof(arr【1】)--1
对于第五个sizeof(&arr)--&arr虽然是数组的地址,但还是地址,地址大小为4/8个字节
对于第六个sizeof(&arr+1)--&arr+1是跳过整个数组后的地址,地址的大小是4/8个字节
对于最后一个sizeof(&arr【0】+1)--第二个元素的地址---4/8个字节
希望大家能够理解,我们把两个代码运行起来给大家看一下
X86平台演示的结果
X64平台演示的结果
我们再来看一组代码
#include<stdio.h> int main() { char arr[] = { 'a','b','c','d','e','f' }; printf("%d\n", strlen(arr)); printf("%d\n", strlen(arr + 0)); printf("%d\n", strlen(*arr)); printf("%d\n", strlen(&arr)); printf("%d\n", strlen(arr[1])); printf("%d\n", strlen(&arr + 1)); printf("%d\n", strlen(&arr[0] + 1)); return 0; }
我们还是给大家讲解一下
对于第一个strlen(求字符串长度)---找不到\0的位置,\0的位置不确定,所以结果打印随机值
对于第二个strlen---1--数组名---首元素的地址,和第一种情况相同---随机值
对于第三个strlen---这里传了个'a'--97过去,他就把97当作一个地址,大家有听说过吗?所以这叫非法访问,是有问题的
对于第四个strlen---同第三个,非法访问,是有问题的
对于第五个strlen----取地址arr---虽然是取出来的是数组的地址,但是数组的地址也是从'a'开始的,所以结果也是随机值
对于第六个strlen---也是随机值,但是随机值跟前面的随机值差6
对于第六个strlen---也是随机值,但是比前面的随机值差1
我们还是把代码运行起来给大家看一下
X86平台演示的结果
X64平台演示的结果
我们接着来看代码
#include<stdio.h> int main() { char arr[] = "abcdef"; printf("%d\n", sizeof(arr)); printf("%d\n", sizeof(arr + 0)); printf("%d\n", sizeof(*arr)); printf("%d\n", sizeof(arr[1])); printf("%d\n", sizeof(&arr)); printf("%d\n", sizeof(&arr + 1)); printf("%d\n", sizeof(&arr[0] + 1)); return 0; }
我们还是来给大家讲解一下
第一个:计算的是数组的大小,单位是字节---7
第二个:计算的是地址的大小,arr+0是首元素的地址
第三个:*arr是首元素,计算的是首元素的大小--1
第四个:arr【1】是第二个元素,计算的是第二个元素的大小
第五个:&arr虽然是数组的地址,但也是地址,所以是4/8个字节
第六个:&arr+1是跳过整个数组后的地址,但也是地址---4/8个字节
第七个:&arr【0】+1是第二个元素的地址--4/8个字节
我们来把代码演示结果给大家展示一下
X86平台演示的结果
X64平台演示的结果
我们来看下面的代码
#include<stdio.h> int main() { char arr[] = "abcdef"; printf("%d\n", strlen(arr)); printf("%d\n", strlen(arr + 0)); printf("%d\n", strlen(*arr)); printf("%d\n", strlen(arr[1])); printf("%d\n", strlen(&arr)); printf("%d\n", strlen(&arr + 1)); printf("%d\n", strlen(&arr[0] + 1)); return 0; }
还是给大家一个一个讲解一下
第一个:6,字符串的长度
第二个:6,和第一个相同
第三个:非法访问内存,访问97的这个地址,所以是有问题的
第四个:和第三个是一个道理,访问的是'b'--98的地址,属于非法访问,是有问题的
第五个:&arr---数组的地址--strlen的返回类型为const char*,我们正常使用应该使用数组指针---char(*p)【7】==&arr
第六个:&arr+1把\0也跳过去了,你也不知道后面的字符串有多长,所以结果是随机值
第七个:跳过了a这个字符从b开始往后数,所以长度为5
我们运行代码看一下结果
X86平台演示的结果
X64平台演示的结果
如果大家能够理解,我们继续来看下面的代码
#include<stdio.h> int main() { char* p = "abcdef"; printf("%d\n", sizeof(p)); printf("%d\n", sizeof(p + 1)); printf("%d\n", sizeof(*p)); printf("%d\n", sizeof(p[0])); printf("%d\n", sizeof(&p)); printf("%d\n", sizeof(&p + 1)); printf("%d\n", sizeof(&p[0] + 1)); return 0; }
我们还是来解释一下
第一个:计算指针变量p的大小---4/8个字节
第二个:p+1得到的是字符b的地址,地址的大小为4/8个字节
第三个:*p就是字符串的第一个字符,也就是字符a,a为字符--1个字节
第四个:---可以等价等int arr[10]----arr[0]==*(arr+0) p[0]==*(p+0)=='a',所以还是字符a--大小为1个字节
第五个:计算的地址,地址是4/8个字节
第六个:也是地址,大小为4/8个字节
第七个:b的地址---大小为4/8个字节
我们运行起来看一下效果
X86平台演示的结果
X64平台演示的结果
我们再来看下一个代码
#include<stdio.h> int main() { char* p = "abcdef"; printf("%d\n", strlen(p)); printf("%d\n", strlen(p + 1)); printf("%d\n", strlen(*p)); printf("%d\n", strlen(p[0])); printf("%d\n", strlen(&p)); printf("%d\n", strlen(&p + 1)); printf("%d\n", strlen(&p[0] + 1)); return 0; }
第一个:6-从a开始的字符串的长度到\0结束
第二个:5-从b开始的字符串的长度到\0结束
第三个:error--将a的值传过去了
第四个:error--同第三个代码
第五个:地址如果内存分配不同,结果也会不同(涉及大小端知识)--随机值
第六个:也是随机值---取地址加1对于后面的内存,地址的大小我们也不知道,所以是随机值
第七个:5--从第二个元素开始到\0结束
给大家运行代码看一下结果
X86平台演示的结果
X64平台演示的结果
我们来看最后一个代码
#include<stdio.h> int main() { //二维数组 int a[3][4] = { 0 }; printf("%d\n", sizeof(a)); printf("%d\n", sizeof(a[0][0])); printf("%d\n", sizeof(a[0])); printf("%d\n", sizeof(a[0] + 1)); printf("%d\n", sizeof(*(a[0] + 1))); printf("%d\n", sizeof(a + 1)); printf("%d\n", sizeof(*(a + 1))); printf("%d\n", sizeof(&a[0] + 1)); printf("%d\n", sizeof(*(&a[0] + 1))); printf("%d\n", sizeof(*a)); printf("%d\n", sizeof(a[3])); return 0; }
我们还是来给大家分析一下
第一个:48
第二个:4
第三个:16--a【0】相当于第一行作为一维数组的数组名,这里计算的是一行的大小
第四个:4---a【0】是第一行的数组名,数组名此时是首元素的地址,a【0】其实是第一行第一个元素的地址,a【0】+1就是第一行第二个元素的地址,地址大小为4/8个字节
第五个:4--*(a【0】+1)是第一行第二个元素,大小是4个字节
第六个:4--a是二维数组的数组名,所以a是首元素的地址,二维数组的首元素是他的第一行,a就是第一行(首元素)的地址,a+1就是第二行的地址
第七个:16---计算的是第二行的大小,单位是字节
第八个:第二行的地址--4
第九个:计算的是第二行的大小,单位是字节
第十个:a是首元素的地址--第一行的地址,*a就是第一行,计算的是第一行的大小
第十一个:16
给大家把代码运行起来看结果
X86平台演示的结果
X64平台上演示的结果
指针详解的全部知识就给大家讲完了,希望大家能够有所收获
全章终!!!