指针和数组的题目辨析
一、
c
//一维数组
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.
首先强调sizeof是一个操作符(也是一个关键字),用于获取一种数据类型或一个变量所占用的字节数。
在上述代码中创建了一个整型数组a,存放了四个整型数据。(注:代码后面注释为代码所在行数,并无其他含义)
- 在该语句中,a是数组名,单独放在sizeof中表示计算整个数组的大小,也就是整个数组所占字节数。该数组是整型数组,一共存放四个元素,那么sizeof(a) = 4*4 = 16。
- 我们知道数组名指向的是数组中第一个元素的地址,在该语句中数组名并不是单独放在sizeof当中,而是sizeof(a+0),这表示a+0是一个地址,那么它的返回值便是4/8(在32位机器中一个地址所占空间大小是4字节,而在64位机器中一个地址所占空间大小为8字节)
- a是数组名指向数组中首元素的地址,*a就代表a数组中首元素,它是一个整型,当然为4字节大小。
- 该语句与2.相同,a没有单独放在sizeof当中,而是(a+1),这代表a+1是一个地址,并且指向的是数组中第二个元素的地址。那么返回值应该是4/8(在32位机器中一个地址所占空间大小是4字节,而在64位机器中一个地址所占空间大小为8字节)。
- sizeof(a[1]),a[1]代表数组中第二个元素,其实a[1] = *(a+1),不难看出a[1]是对数组中元素进行访问,且访问的是第二个元素,那么返回值就是4。
- sizeof(&a),&a表示对整个数组取地址,&a本质上是一个地址,那么它所占字节数就为4/8。
- sizeof(* &a):* &a表示先取出整个数组的地址(即&a),然后再对(&a)解引用,由于&a指向的是整个数组的内容,那么对(&a)解引用就是访问了整个数组,那么返回值就是整个数组的大小,即16.
- sizeof(&a+1):(&a+1)代表取出整个数组的地址,然后+1跳过整个数组,但本质上(&a+1)仍是一个地址,那么它的返回值便是4/8。
- sizeof(&a[0]):(&a[0])就是取出了数组中第一个元素的地址,那么一个地址的返回值是4/8 。
- sizeof(&a[0]+1):(&a[0]+1)表示取出首元素的地址然后+1跳过该元素,所以(&a[0]+1)是指向第二个元素的地址,返回值是4/8。
总结:想要知道sizeof()返回值,最重要的是要弄清sizeof()里面放的数据的数据类型是怎样的。
二、
c
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.
在该段代码中我们创建了一个字符数组arr,存放了六个字符。
sizeof(arr):将数组名单独放在了sizeof中,那么就代表计算整个数组的大小,返回值为6。
sizeof(arr+0):arr+0代表数组中首元素的地址,返回值为4/8。
sizeof(* arr):* arr表示对首元素的地址解引用,而arr所指向的是数组中的首元素,即'a'。故返回值为1。
sizeof(arr[1]):arr[1]代表访问数组中第二个元素,它是一个字符,故返回值为1。
sizeof(&arr):&arr表示对整个数组取地址,&arr指向的是整个地址,因此返回值是4/8。
sizeof(&arr+1):&arr+1是一个地址,它指向的是跳过arr数组的地址,返回值为4/8。
sizeof(&arr[0]+1):&arr[0]+1是一个地址,它指向的是数组中第二个元素,故返回值为4/8。
strlen()是一个库函数,它是用来求取一个字符串的长度,\0是读取字符串的结束标志。返回值是字符串的长度,统计\0以前的字符个数。strlen(arr):用来求取字符串的长度,但该数组中并没有存放字符串的结束标志\0,因此返回值是一个随机值。
strlen(arr+0):将数组首元素的地址传给strlen,但不知道什么时候会遇到\0,因此返回一个随机值。
strlen(* arr),* arr表示访问数组中第一个元素'a',而strlen接受的参数是指针,strlen会将'a'的ASCII码97当作一个指针,但是这是错误的,因此程序会报错。
strlen(arr[1]):这与十类似,不同的是这次是将字符'b'的ASCII码传给了strlen因此程序会报错。
strlen(&arr):将整个数组的地址传给了strlen,但不知道字符串的结束标志在哪儿,故会返回一个随机值。
strlen(&arr+1):将数组的地址+1跳过该数组,指向数组以外的下一个地址,不知道字符串的结束标志在哪儿,因此返回随机值。
strlen(&arr[0]+1):返回随机值
三、
c
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,存放了7个元素,分别是'a','b','c','d','e','f','\0'。
- sizeof(arr):返回值是7。
- sizeof(arr+0):arr+0是指向数组中首元素的地址,返回值是4/8。
- sizeof(* arr):* arr代表数组首元素'a'返回值为1。
- sizeof(arr[1]):arr[1]表示数组中第二个元素'b',返回值是1。
- sizeof(&arr):&arr表示整个数组的地址,返回值是4/8。
- sizeof(&arr+1):&arr+1表示数组的地址+1是指向数组外的一个地址,返回值为4/8。
- sizeof(&arr[0]+1):&arr[0]+1表示数组中第二个元素的地址,返回值是4/8。
- strlen(arr):求字符串的长度,统计\0以前的字符个数,返回值为6。
- strlen(arr+0):arr+0指向数组中首元素的地址,因此返回值为6。
- strlen(* arr): *arr表示数组中首元素'a',它将ASCII码97传给了strlen,这是错误的。
- strlen(arr[1]):与上述同理。
- strlen(&arr):将数组的地址传给了strlen,返回值是6;
- strlen(&arr+1):将给数组指针+1跳过了数组的指针传给了strlen,返回值为随机值
- strlen(&arr[0]+1):将数组中第二个元素的地址传给了strlen返回值为5。
四、
c
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.
rintf("%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.
该代码将一个常量字符串的地址传给了p(即字符串首元素的地址);
- sizeof§:p是一个地址,故返回值为4/8。
- sizeof(p+1):p+1指向字符串中b字符位置 ,p+1是一个地址,故返回值是4/8。
- sizeof(* p):*p表示字符串中首个字符'a',故返回值为1。
- sizeof(p[0]):p[0] = *(p+0),同上。
- sizeof(&p) :&p是一个二级指针,故返回值是4/8。
- strlen(&p+1):&p+1是一个地址,故返回值为4/8。
- sizeof(&p[0]+1):&p[0]+1是一个指向'b'字符的地址,故返回值是1。
- strlen§:求字符串长度,遇到\0停止,返回值为6。
- strlen(p+1):将字符串中'b'的地址传给strlen,返回值为5。
- strlen(*p):err。
- strlen(p[0]):p[0] = *(p+0),故err。
- strlen(&p):&p是二级指针,返回值是随机值。
- strlen(&p+1):返回值是随机值。
- strlen(&p[0]+1):返回值为5。
五、
c
//二维数组
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.
创建了一个3行4列的二维数组。
- sizeof(a):计算整个数组的大小,返回值为344 = 48。
- sizeof(a[0][0]):a[0][0]代表第一行第一列元素,返回值为4。
- sizeof(a[0]):a[0]表示第一行数组名,数组名单独放在sizeof中,计算整个数组的大小,返回值为16。
- sizeof(a[0]+1):a[0]没有取地址,没有单独放在sizeof中,表示数组中第一个元素a[0][0]的地址,a[0]+1表示数组中第一行第二个元素的地址。返回值为4/8.
- sizeof(*(a[0]+1)): *(a[0]+1) = a[0][1],返回值为4.
- sizeof(a+1):a是二维数组名,表示首元素的地址,也就是第一行的地址,a+1表示第二行地址,返回值为4/8.
- sizeof(*(a+1)): * (a+1)表示第二行的元素,返回值为16.
- sizeof(&a[0]+1):表示第二行元素的地址,返回值为4/8.
- sizeof((&a[0]+1)):(&a[0]+1)表示第二行的元素,返回值为16.
- sizeof(*a): * a表示第一行元素,返回值为16
- sizeof(a[3]):a[3]表示第四行数组名,计算第四行数组的大小,返回值为16。