C语言指针与数组 部分笔试题解析

一:本文简介:

首先,介绍一下该类型笔试题的考查方式:该类型题目一般考察通过sizeof()和strlen对与数组,指针相关的,不同类型的数据进行空间长度或元素个数的计算。由于初学者在指针和数组的学习中,相应概念易混淆,故该类型笔试题易出错。下面,我将就此讲解原理,梳理概念并对相应题型分类讲解。

二:相应概念原理:

1.在C语言中,sizeof()并非函数,它是一个C语言关键字(单目操作符),是一个用于判断某种数据类型长度或者某种表达式长度 (所占内存空间大小)(单位是一个字节)的运算符。

sizeof()不在乎内存中存放的是什么,只在乎内存大小。

注:sizeof计算数组或者字符串所占内存空间大小包含末尾的'\0'.

2.在 C语言中,strlen()是头文件#include<string.h>下的一个库函数,功能是计算一个字符串的长度,直到遇到'\0'停止,不包含'\0'.

strlen()函数的括号中需要传参类型是const char*(常量字符指针类型),该函数的返回值类型是size_t(无符号整型)。

strenlen函数求字符串长度,从给定的地址向后访问字符,统计'\0'之前出现的字符个数(字节数)

(注:由于strlen函数返回值类型是无符号整型,因此,在某些类型的笔试题中,应注意strlen函数的返回值用于加减的一些情况。)

3.一些归总:对于一个数组:数组名和数组首元素地址和取地址数组名的值都是相同的 :即arr = &arr[0] = &arr。

但是意义不同 :&arr表示对整个数组取地址 ,arr或者&arr[0]则表示对数组首元素取地址。

数组名+1加的是数组单个元素大小的字节数 ,而取地址数组首元素+1加的是数组中单个元素大小的字节数 , 取地址数组名+1加的是所有数组元素总共的字节数。

4.数组名通常来说是数组首元素的地址,但有两个特例:

一:sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小。

二:&数组名(取地址数组名),取出的是整个数组的地址。

5.在X86平台(32位)中,地址所占内存空间大小为4个字节,在X64平台(64位)中,地址所占内存空间大小为8个字节。只要是地址,所占内存空间大小就是4或8个字节。

6.二维数组的理解:将二维数组想象成一维数组,每一行都是一个一维数组,char *p = arr( 数组名) , 则arr[i][j]=*(*(p+i)+j).

三:题目分类:

一.sizeof与一维数组

二.sizeof与字符数组

三.strlen与字符数组(大括号初始化)

四.strlen,sizeof与字符数组(“双引号初始化)

五.sizeof,strlen与字符指针

六.sizeof与二维数组

四:题目讲解:

(相应头文件及主函数名,括号已省略)

一.

1.例题:

int a[]={1,2,3,4};

1  printf("%d\n",sizeof(a));

2  printf("%d\n",sizeof(a+0));

3  printf("%d\n",sizeof(*a));

4  printf("%d\n",sizeof(a+1));

5  printf("%d\n",sizeof(a[1]));

6  printf("%d\n",sizeof(&a));

7  printf("%d\n",sizeof(*&a));

8  printf("%d\n",sizeof(&a+1));

9  printf("%d\n",sizeof(&a[0]));

10  printf("%d\n",sizeof(&a[0]+1));

2.解析:

1  sizeof(a)计算整个数组的大小,该数组有4个整形元素,一共4*4=16个字节。

2  sizeof(a+0)这里sizeof的括号内不再是数组名了,这里的a表示数组首元素地址,a+0仍是数组首元素地址,而地址所占内存大小为4或8个字节。

3  sizeof(*a)a表示数组首元素地址,*a表示数组的第一个元素,该数组的第一个元素为整型,所占内存大小为4个字节。

4.  sizeof(a+1)a表示数组首元素地址,a+1表示数组第二个元素的地址,sizeof(a+1)就是数组第二个元素的地址的大小,所占内存大小为4或8个字节。

5.  sizeof(a[1]) a[1]是数组的第二个元素,也为整型,大小为四个字节。

6.  sizeof(&a) &a是数组的地址,只要是地址,所占内存大小就是4或8个字节。

7.  sizeof(*&a) a取地址再解引用等价于a本身,因此 sizeof(&*a)==sizeof(a)==16

8.  sizeof(&a+1) &a表示数组的地址,+1跳过整个数组,指向原数组最后一个元素后的地址,而只要是地址,所占内存空间大小就是4或8个字节。

9.  sizeof(&a[0]) 表示数组首元素地址,大小为4或8字节。

10.  sizeof(&a[0]+1)数组首元素地址+1指向数组第二个元素的地址,大小为4或8字节。

二.

1.例题:

char arr[]={'a','b','c','d','e','f'};

1.  printf("%d\n",sizeof(arr));

2.  printf("%d\n",sizeof(arr+0));

3.  printf("%d\n",sizeof(*arr));

4.  printf("%d\n",sizeof(arr[1]));

5.  printf("%d\n", sizeof(&arr));

6.  printf("%d\n", sizeof(&arr+1));

7.  printf("%d\n", sizeof(&arr[0]+1));

2.解析:

1.  sizeof(arr) 该数组一共六个字符元素元素,每个元素占一个字节,因此该数组占六个字节。

2.  sizeof(arr+0) arr+0是首元素地址,占4或8个字节。

3.  sizeof(*arr)arr为首元素地址,*arr为首元素,占一个字节。

4.  sizeof(arr[1]) arr[1]是数组的第二个元素,大小为一个字节。

5.  sizeof(&arr) &arr是该数组的地址,占4或8个字节。

6.  sizeof(&arr+1) 数组地址+1表示跳过整个数组后的地址,大小为4或8个字节。

7.  sizeof(&arr[0]+1) &arr[0]+1表示数组第二个元素的地址,大小为4或8个字节。

三.

1.例题:

#include<string.h>

char arr[]={'a','b','c','d','e','f'};

//该初始化方式意味着该数组中有且仅有六个字符元素,无'\0';

1.  printf("%d\n",strlen(arr));

2.  printf("%d\n",strlen(arr+0));

3.  printf("%d\n",strlen(*arr));

4.  printf("%d\n",strlen(arr[1]));

5.  printf("%d\n", strlen(&arr));

6.  printf("%d\n", strlen(&arr+1));

7.  printf("%d\n", strlen(&arr[0]+1));

2.解析:

1  strlen(arr)  arr表示首元素地址,strlen(arr)表示从首元素地址开始,求直到'\0'之前的元素个数。arr数组中不包含'\0',strlen会继续向后寻找'\0',统计'\0'之前出现的字符个数。因此结果为>=6的随机值。

2  strlen(arr+0)  arr+0仍为数组首元素地址,结果仍为随机值。

3  strlen(*arr) *arr是数组的首元素,是字符'a'。 字符'a'的ascii值为97,被 strlen函数当作地址并求从该地址开始直到'\0'之前的元素个数,导致访问出错。

4  strlen(arr[1]) arr[1]是数组的第二个元素,是字符'b'。 字符 'b'的ascii码值为98,被strlen函数当作地址并求从该地址开始直到'\0'之前的元素个数,导致访问出错。

5  strlen(&arr) &arr表示整个数组的地址,相当于数组的首元素地址,结果为随机值(参考 1)

6  strlen(&arr+1) &arr+1指向跳过一个数组长度后的地址,结果仍为随机值,该随机值与1和5中的随机值相差6(跳过一个该数组跳过6个元素)。

7  strlen(&arr[0]+1) &arr[0]+1表示数组第二个元素额地址,即字符'b'的地址,结果仍为随机值且该随机值比1中求得随机值小1,解析原理与1相同。

四.

1.例题:

#include<string.h>

char arr[]=“abcef"

1.  printf("%d\n",sizeof(arr));

2.  printf("%d\n",sizeof(arr+0));

3.  printf("%d\n",sizeof(*arr));

4.  printf("%d\n",sizeof(arr[1]));

5.  printf("%d\n", sizeof(&arr));

6.  printf("%d\n", sizeof(&arr+1));

7.  printf("%d\n", sizeof(&arr[0]+1));

8.  printf("%d\n",strlen(arr));

9.  printf("%d\n",strlen(arr+0));

10.  printf("%d\n",strlen(*arr));

11.  printf("%d\n",strlen(arr[1]));

12.  printf("%d\n", strlen(&arr));

13.  printf("%d\n", strlen(&arr+1));

14.  printf("%d\n", strlen(&arr[0]+1));

2.解析:

"abcdef" <=> [a b c d e f \0]

1  sizeof(arr) 数组7个元素,7*1=7。

2  sizeof(arr+0) arr+0为数组首元素地址,4或8个字节。

3.sizeof(*arr) *arr为数组首元素,是字符'a',长度为一个字节。

4  sizeof(arr[1]) arr[1]为数组第二个元素,是字符'b',长度为一个字节。

5  sizeof(&arr)  &arr为整个数组地址,大小为4或8个字节。

6  sizeof(&arr+1)&arr=1表示'\0'之后的地址,大小为4或者8个字节。

7  sizeof(&arr[0]+1) &arr[0]+1表示该数组第二个元素的地址,大小为4或8个字节。

8  strlen(arr)该数组中存在'\0',该数组中'\0'之前有六个字符(六个字节),因此返回值为6.

9  strlen(arr+0) arr+0表示首元素地址,函数返回值仍为6.

10 strlen(*arr) *arr表示首元素,即字符'a',ascii码值为97,为非法访问内存,访问出错。

11 atrlen(arr[1])  arr[1]表示第二个圆度,即字符'b',ascii 码值为97,为非法访问内存,会导致访问出错。

12 strlen(&arr) &arr为整个数组地址,也从首元素地址开始向后数字符,返回值为6.

13 strlen(&arr+1)从'\0'之后开始数字符,无法确定之后'\0'的位置,答案为随机值。

14 strlen(&arr[0]+1)  &arr[0]+1表示第二个元素的地址,strlen(&arr[0]+1)表示从第二个元素(字符'b'开始向后数直到遇见'\0',一共五个元素,返回值为5.

五.

1.例题:

char* p="abcdef"

(注:该写法表示字符指针p中存放的是该字符串首元素字符'a'的地址

1  printf("%d\n",sizeof(p));

2  printf("%d\n",sizeof(p+1));

3  printf("%d\n",sizeof(*p);

4  printf("%d\n",sizeof(p[0]));

5  printf("%d\n",sizeof(&p);

6  printf("%d\n",sizeof(&p+1);

7  prntf("%d\n",sizeof(&p[0]+1);

8  printf("%d\n",strlen(p));

9  printf("%d\n",strlen(p+1));

10  printf("%d\n",strlen(*p);

11  printf("%d\n",strlen(p[0]));

12  printf("%d\n",strlen(&p);

13  printf("%d\n",strlen(&p+1);

14  prntf("%d\n",strlen(&p[0]+1);

2.解析:

1  sizeof(p)  p是指针变量,计算的是指针变量的大小,为4或8个字节。

2  sizeof(p+1)   p+1为第二个字符(字符 ’b'的地址),大小为4或8个字节。

3  sizeof(*p)  *p表示字符'a',大小为一个字节。

4  sizeof(p[0])   p[0] <=> *(p+0) <=> *p 表示字符'a',大小为一个字节。

5  sizeof(&p)  &p是指针变量p的地址,大小为4或8个字节。

6  sizeof(&p+1)  &p+1表示p的地址跳过一个字节之后的地址,大小仍为4或8个字节。

7  sizeof(&p[0]+1)  &p[0]+1表示字符'b'的地址,大小为4或8个字节。

8  strlen(p)  p存放的是'a'的地址,该字符串末尾存在'\0',因此函数返回值==6.

9  strlen(p+1)  p+1存放字符'b'的地址,函数返回值==5.

10  strlen(*p)    *p和p[0]都表示字符串首元素字符'a',ascii码值为97,被strlen视为内存(strlen的输入

11   strlen(p[0])    参数应为char*类型, 97为非法访问内存,访问出错。

12  strlen(&p)  &p是指针p的地址,之后'\0'的位置未知,因此返回值为随机值。

13  strlen(&p+1)  &p+1是指针p的地址跳过4或8个字节后的地址,函数返回值仍为随机值。

14  strlen(&p[0]+1)  &p[0]表示'a'的地址,+1表示'b'的地址,返回值为5.

六.

1.例题:

int  a[3][4] = {0};

1 printf("%d\n",sizeof(a));

2  printf("%d\n",sizeof(a[0][0]));

3  printf("%d\n",sizeof(a[0]));

4  printf(”%d\n",sizeof(a[0]+1));

5  printf("%d\n",sizeof(*(a[0]+1)));

6  printf("%d\n",sizeof(a+1));

7  printf("%d\n",sizeof(*(a+1));

8  printf("%d\n",sizeof(&a[0]+1));

9  printf("%d\n",sizeof(*(&a[0]+1)));

10  printf("%d\n",sizeof(*a));

11 printf("%d\n",sizeof(a[3]));

2.解析:

1  sizeof(a) 计算整个数组大小,单位是字节。3*4*4=48占48个字节大小的内存

2  sieof(a[0][0])  计算第一行第一列元素的大小, 为整型,占四个字节。

3  sizeof(a[0])  a[0]是第一行的数组名,它单独放在sizeof()的括号内,计算的是第一行的大小,sizeof(a[0])计算的是第一行这一整个一维数组的大小,占4*4=16个字节。

4  sizeof(a[0]+1) a[0]是第一行这个一维数组的数组名,这个数组名并没有单独放在sizeof()的括号内,那么就表示第一行第一个元素的地址,+1则表示第一行第二个元素的地址,是地址那么所占内存空间就是4或8个字节。

5  sizeof(*(a[0]+1))  a[0]+1表示第一行第二个元素的地址,解引用表示第一行第二个元素,是一个整型元素,占4个字节。

6  sizeof(a+1)  a表示首元素地址,就是第一行的地址,(a+1)则表示第二行的地址,占4或8字节。

7  sizeof(*(a+1))  解引用第二行的地址访问的就是第二行,占4*4=16个字节

    (sizeof(*(a+1) <=> sizeof(a[1])计算的是第二行的大小,占16个字节)

8  sizeof(&a[0]+1)  a[0]是第一行的数组名,&a[0]+1表示第二行的地址,占4或8字节。

9  sizeof(*(&a[0]+1))  &a[0]+1是第二行的地址,解引用找到第二行,占4*4=16个字节。

10  sizeof(*a)   a就是首元素(第一行的地址) *a表示第一行,占16个字节(sizeof(*a)<=>sizeof(a[0]))

11  sizeof(a[3])  

乍一看越界访问了,但是我们只需要判断a[3]是什么数据类型即可求出其所占内存大小。

a[3]是数组名,类型是int a[4],占4*4=16个字节。

 

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值