关注小程序 找一找教程网-随时随地学编程

C/C++教程

C语言 指针的一些题目(1)

首先要注意的是:

1,&数组名,这里的数组名也表示整个数组,取出的是数组的地址,不是数组首元素的地址.关于它们两个的区别,本文不在累述,有疑问的请自己查阅资料.

2,语法规定:sizeof(数组名),这里只有单独的数组名的时候,sizeof(数组名)计算的是整个数组的大小.

3,除了以上的情况之外,所有的数组名都是数组首元素的地址.

4,sizeof只关注占用空间的大小,单位是字节,sizeof不关注类型.sizeof是操作符

5,strlen关注的字符串中\0的为止,计算的是\0之前出现了多少个字符,strlen指针对字符串而言的.strlen是库函数.

6,本文为了加强记忆和区别,只要涉及到比如数组首元素的地址,数组的地址之类的关键语句,就会加粗,同时,写出每一个的分析过程.

1,下面各语句打印的结果是什么?

//一维数组
int a[] = {1,2,3,4};

printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a+0));//2
printf("%d\n",sizeof(*a));//3
printf("%d\n",sizeof(a+1));//4
printf("%d\n",sizeof(a[1]));//5
printf("%d\n",sizeof(&a));//6
printf("%d\n",sizeof(*&a));//7
printf("%d\n",sizeof(&a+1));//8
printf("%d\n",sizeof(&a[0]));//9
printf("%d\n",sizeof(&a[0]+1));//10

解析:

01        16. 数组名a单独放在sizeof内部,计算的是整个数组的大小,大小为4*4个字节;(以下单位均为字节,省略)

02        4/8.(32位上面是4,64位上面是8,以下4/8同理)数组名a不是单独放在里面的,表示数组首元素的地址,地址的大小是4/8;

03        4.a没有单独放在里面,是数组首元素的地址,在*一下就拿出了这个元素1,是int类型的,大小为4;

04        4/8.a没有单独放在里面,是数组首元素的地址,在+1,就是数组中第二个元素的地址2的地址,地址的大小是4/8;

05        4.a没有单独放在里面,是数组首元素的地址,在[1]就是数组第二个元素,类型为int型,大小为4;

06        4/8.&数组名,表示数组的地址,数组的地址也是地址,地址的大小是4/8;

07        16.拿到(&)a的地址,在*,相当于二者抵消,还是单独的一个a.数组名a单独放在sizeof内部,计算的是整个数组的大小,大小为4*4;

08        4/8.&数组名,表示数组的地址.&a拿到数组a的地址,在+1,就跳过了整个数组a,指向下一个地址,地址的大小是4/8;

09        4/8.注意优先级!优先级[]>&(取地址符).a[0],数组第一个元素,在&就是它的地址.地址的大小是4/8;

10        04/8.注意优先级!优先级[]>&(取地址符).a[0],数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是int型,加1就跳过4个字节,到了第二个元素).地址的大小是4/8;

2,下面各语句打印的结果是什么?

//字符数组
char arr[] = {'a','b','c','d','e','f'};

printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7
printf("%d\n", strlen(arr));//8
printf("%d\n", strlen(arr+0));//9
printf("%d\n", strlen(*arr));//10//运行时需要注释掉
printf("%d\n", strlen(arr[1]));//11//运行时需要注释掉
printf("%d\n", strlen(&arr));//12
printf("%d\n", strlen(&arr+1));//13
printf("%d\n", strlen(&arr[0]+1));//14

解析:

01        6. 数组名arr单独放在sizeof内部,计算的是整个数组的大小,大小为1*6个字节,在这里不要认为是字符串,它只是一个字符数组!

02        4/8.数组名arr不是单独放在里面的,表示数组首元素的地址,在+0,没影响.地址的大小是4/8;

03        1.数组名arr不是单独放在里面的,表示数组首元素的地址,在*,就拿到这个元素.char类型的大小为1;

04        1.数组名arr不是单独放在里面的,表示数组首元素的地址,是第二个元素.char类型的大小为1;

05        4/8.&数组名,表示数组的地址,数组的地址也是地址,地址的大小是4/8;

06        4/8.&数组名,表示数组的地址.&arr拿到数组arr的地址,在+1,就跳过了整个数组arr,指向下一个地址,地址的大小是4/8;

 07        04/8.注意优先级!优先级[]>&(取地址符).arr[0]是数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素).地址的大小是4/8;

08         随机值.数组名arr不是单独放在里面的,表示数组首元素的地址,strlen函数开始由这个地址继续走,由于字符数组中没有'\0',结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

09         随机值.数组名arr不是单独放在里面的,表示数组首元素的地址,在+0,还是这个元素的地址.strlen函数开始由这个地址继续走,由于字符数组中没有'\0',结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

10         错误.数组名arr不是单独放在里面的,表示数组首元素的地址,在*,就拿到这个元素'a'.字符在内存中存放的时ASCII码,'a'就是97.strlen函数将97当作地址继续走,结果就是访问内存冲突;

11         错误.数组名arr不是单独放在里面的,表示数组首元素的地址,arr[1],就拿到这个元素'b'.字符在内存中存放的时ASCII码,'b'就是98.strlen函数将98当作地址继续走,结果就是访问内存冲突;

12        随机值.&数组名,表示数组的地址,虽然类型和strlen的参数类型有所差异,但是传参过去后,还是从第一个字符的地址开始计算,由于字符数组中没有'\0',结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

13        随机值.&数组名,表示数组的地址,虽然类型和strlen的参数类型有所差异,但是传参过去后,+1,跳过这个字符数组开始计算,由于后面不知道'\0'的位置,结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

14        随机值.注意优先级!优先级[]>&(取地址符).arr[0],数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素),虽然类型和strlen的参数类型有所差异,但是传参过去后,还是从第二个字符的地址开始计算,由于字符数组中没有'\0',结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

char arr[] = "abcdef";

printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7
printf("%d\n", strlen(arr));//8
printf("%d\n", strlen(arr+0));//9
printf("%d\n", strlen(*arr));//10//运行时需要注释掉
printf("%d\n", strlen(arr[1]));//11//运行时需要注释掉
printf("%d\n", strlen(&arr));//12
printf("%d\n", strlen(&arr+1));//13
printf("%d\n", strlen(&arr[0]+1));//14

解析:

这里的arr数组表示字符串了.

01        7. 数组名arr单独放在sizeof内部,计算的是整个字符串+'\0'的大小,大小为1*7个字节.

02        4/8.数组名arr不是单独放在里面的,表示数组首元素的地址,在+0,没影响.地址的大小是4/8;

03        1.数组名arr不是单独放在里面的,表示数组首元素的地址,在*,就拿到这个元素.char类型的大小为1;

04        1.数组名arr不是单独放在里面的,表示数组首元素的地址,是第二个元素.char类型的大小为1;

05        4/8.&数组名,表示数组的地址,数组的地址也是地址,地址的大小是4/8;

06        4/8.&数组名,表示数组的地址.&arr拿到数组arr的地址,在+1,就跳过了整个数组arr,指向下一个地址,地址的大小是4/8;

 07        4/8.注意优先级!优先级[]>&(取地址符).arr[0]是数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素).地址的大小是4/8;

08         6.数组名arr不是单独放在里面的,表示数组首元素的地址,strlen函数开始由这个地址继续走,由于字符串末尾加'\0',所以能够计算出大小.strlen遇到'\0'才会停下来;

09         6.数组名arr不是单独放在里面的,表示数组首元素的地址,arr在+0,还是这个地址.strlen函数开始由这个地址继续走,由于字符串末尾加'\0',所以能够计算出大小.strlen遇到'\0'才会停下来;

10         错误.数组名arr不是单独放在里面的,表示数组首元素的地址,在*,就拿到这个元素'a'.字符在内存中存放的时ASCII码,'a'就是97.strlen函数将97当作地址继续走,结果就是访问内存冲突;

11         错误.数组名arr不是单独放在里面的,表示数组首元素的地址,arr[1],就拿到这个元素'b'.字符在内存中存放的时ASCII码,'b'就是98.strlen函数将98当作地址继续走,结果就是访问内存冲突;

12        6.&数组名,表示数组的地址,虽然类型和strlen的参数类型有所差异,但是传参过去后,还是从第一个字符的地址开始计算,strlen函数开始由这个地址继续走,由于字符串末尾加'\0',所以能够计算出大小.strlen遇到'\0'才会停下来;

13        随机值.&数组名,表示数组的地址,虽然类型和strlen的参数类型有所差异,但是传参过去后,+1,跳过这个字符串开始计算,由于后面不知道'\0'的位置,结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

14        随机值.注意优先级!优先级[]>&(取地址符).arr[0],数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素),虽然类型和strlen的参数类型有所差异,但是传参过去后,还是从第二个字符的地址开始计算,由于字符数组中没有'\0',结果就是不知道什么时候停下来.所以,在不同的计算机上计算的结果是不一样的.strlen遇到'\0'才会停下来;

char *p = "abcdef";

printf("%d\n", sizeof(p));//1
printf("%d\n", sizeof(p+1));//2
printf("%d\n", sizeof(*p));//3
printf("%d\n", sizeof(p[0]));//4
printf("%d\n", sizeof(&p));//5
printf("%d\n", sizeof(&p+1));//6
printf("%d\n", sizeof(&p[0]+1));//7
printf("%d\n", strlen(p));//8
printf("%d\n", strlen(p+1));//9
printf("%d\n", strlen(*p));//10//运行时需要注释掉
printf("%d\n", strlen(p[0]));//11运行时需要注释掉
printf("%d\n", strlen(&p));//12
printf("%d\n", strlen(&p+1));//13
printf("%d\n", strlen(&p[0]+1));//14

解析:

01        4/8.p是一个指针变量,是存放地址的.sizeof(p)计算的就是指针变量的大小.指针的大小是4/8;

02        4/8.p是一个指针变量,是存放地址的.在+1,还是地址.地址的大小是4/8;

03        1.p是一个指针变量,在*,就拿到这个元素.char类型的大小为1;

04        1.p是一个指针变量,和[0]结合,相当于*(p + 0),还是*p.char类型的大小为1;

05        4/8.p是一个指针变量,在&,就拿到这个指针变量的地址.地址的大小是4/8;

06        4/8.p是一个指针变量,在&,就拿到这个指针变量的地址.在+1,还是指向一个地址,地址的大小是4/8;

 07        4/8.注意优先级!优先级[]>&(取地址符).p[0]是数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素).地址的大小是4/8;

08         6.p中存放的是'a'的地址,strlen函数开始由这个地址继续走,由于字符串末尾加'\0',所以能够计算出大小.strlen遇到'\0'才会停下来;

09         5.p中存放的是'a'的地址,在+1,就是'b'的地址,strlen函数开始由这个地址继续走,由于字符串末尾加'\0',所以能够计算出大小.strlen遇到'\0'才会停下来;

10         错误.p是一个指针变量,在*,就拿到这个元素'a'.字符在内存中存放的时ASCII码,'a'就是97.strlen函数将97当作地址继续走,结果就是访问内存冲突;

11         错误.p是一个指针变量,,在*就拿到这个元素'a',在+1,就拿到'b'.字符在内存中存放的时ASCII码,'b'就是98.strlen函数将98当作地址继续走,结果就是访问内存冲突;

12        随机值.p是一个指针变量,在&,就拿到p的地址,不是"abcdef"的地址,strlen函数开始由这个地址继续走.strlen遇到'\0'才会停下来;

13        随机值.p是一个指针变量,在&,就拿到p的地址,在+1,又是一个地址,不是"abcdef"的地址,strlen函数开始由这个地址继续走.strlen遇到'\0'才会停下来;

14        随机值.注意优先级!优先级[]>&(取地址符).p[0],数组第一个元素,在&就是它的地址,在加1还是地址,是数组第二个元素的地址(数据类型决定了指针加1能走多长,是char型,加1就跳过1个字节,到了第二个元素),传参过去后,从第二个字符的地址开始计算,strlen函数开始由这个地址继续走.strlen遇到'\0'才会停下来;

3,下面各语句打印的结果是什么?

//二维数组
int a[3][4] = {0};

printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a[0][0]));//2
printf("%d\n",sizeof(a[0]));//3
printf("%d\n",sizeof(a[0]+1));//4
printf("%d\n",sizeof(*(a[0]+1)));//5
printf("%d\n",sizeof(a+1));//6
printf("%d\n",sizeof(*(a+1)));//7
printf("%d\n",sizeof(&a[0]+1));//8
printf("%d\n",sizeof(*(&a[0]+1)));//9
printf("%d\n",sizeof(*a));//10
printf("%d\n",sizeof(a[3]));//11

解析:

01        48. 数组名a单独放在sizeof内部,计算的是整个数组的大小,大小为4*3*4个字节;

02        4.a没有单独放在里面,是数组首元素的地址,a[0][0]表示拿到第一行又拿到这一行的第一个元素,是int类型,大小为4;

03        16.a没有单独放在里面,是数组首元素的地址,这里的首元素是第一行的整个数组.大小为4*4;

04        4/8.a没有单独放在里面,是数组首元素的地址,在+1,就是数组中第一行第二个元素,地址的大小是4/8;

05        4.a没有单独放在里面,是数组首元素的地址,[0]表明是第一行的元素,在+1就拿到了这一行的第2个元素的地址,在*,就拿到了这个元素,是int型,大小为4;

06        4/8.a没有单独放在里面,是数组首元素的地址,也就是这第一行.在+1就跳过跳第一行,到了第二行,拿到第二行的地址,地址的大小是4/8;

07        16.a没有单独放在里面,是数组首元素的地址,也就是这第一行.在+1就跳过跳第一行,到了第二行,拿到第二行的地址,在*,就拿到这一行的整个数组,大小为4*4;

08        4/8.a[0]拿到这一个数组第一行,在&就是这一行的地址,在+1,就跳过了这一行,拿到第二行的地址,地址的大小是4/8;

09        16.a[0]拿到这一个数组第一行,在&就是这一行的地址,在+1,就跳过了这一行,来到第二行,在*就拿到这第二行.是int类型,大小为4*4;

10        16.a没有单独放在里面,是数组首元素的地址,也就是这一行.在*,拿到这一行.是int类型,大小为4*4;

11        16.a没有单独放在里面,是数组首元素的地址,在[3],拿到第四行.这里的a[3]越界了,但是sizeof并没有去计算a[3]的大小,事实上,sizeof在计算的时候,只关心占用空间的大小,这里的a[3]在它看来,和a[0],a[1]是一样的,都是这一行的数组名,那么大小就是4*4.