笔试题解析——sizeof()和strlen()内放数组名

目录

1.数组名指代的类型

1.1.特例

1.1.1sizeof()里“单独”放一个数组名,这里计算的是数组名所代表的数组的总大小

1.1.2.(&数组名),这里取出来的是数组的地址,类型就是数组指针

1.2.一般情况

1.2.1.一般情况的数组名与*和&结合的分析

1.2.2.[]与*的转化

1.2.3.加减运算

2.sizeof()笔试题

3.strlen()笔试题


1.数组名指代的类型

1.1.特例

当遇到数组名时不要急着给它定类型,大部分情况下,数组名指的是数组首元素的地址,但是,有两个例外:

1.1.1sizeof()里“单独”放一个数组名,这里计算的是数组名所代表的数组的总大小

1.1.2.(&数组名),这里取出来的是数组的地址,类型就是数组指针

这里的数组名可以是一维数组arr[]的名字arr,也可以是二维数组里arr[][]的arr和arr[](arr代表整个数组,而arr[]代表某一行的数组)众所周知,[]运算符与*()是等价的,故在二维数组里*(arr+x)==arr[x],也就是*(arr+x)也算是数组名。

1.2.一般情况

考虑完这两个特殊情况后,就可以按一般的思路进行判断了,也即把数组名当成数组首元素的地址,如一维数组arr[]的arr等价于&(arr[0]),其类型就是对应数组元素的指针变量,二维数组arr[][]中arr[]==&(arr[][0]),其类型也是对应数组元素的指针变量,需要注意的是:arr==&(arr[]),前面也说了,二维数组中arr[]是指某一行的数组名,故一般情况下二维数组的数组名 arr 的类型是数组指针,可见数组名都是指针类型,就算二维数组的数组名的类型是数组指针,但数组指针也是指针,大小也是4/8个字节。

1.2.1.一般情况的数组名与*和&结合的分析

*相当于给所结合变量的类型上减去*,如*(int*)== int

&则相反,是加*,如&(int)==int*

1.2.2.[]与*的转化

对于计算机而言,[]比*() 更加难操作,故在编译过程中,arr[x] 会被转化成*(arr+x),然后像指针一样进行解引用操作,但反过来,在遇到比较复杂的*()结构的语句时,我们转化成[]结构可能易读性更高,如(*(arr+0))[2],转换一下就能得到其等价于arr[0][2],就能轻松地判断它的信息了,但如果你是经验丰富的程序员,转不转化就看个人习惯了。

1.2.3.加减运算

一个变量加减一个常数,其类型不会改变。

2.sizeof()笔试题

sizeof操作符,注意,sizeof是操作符!!!

它是用于判断()内数据类型的大小的

补:判断数据的类型不像计算一样要把表达式一步步执行到最后才能有答案,试着运行下列语句你就明白了:

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

所以sizeof的()内的表达式不会执行,但是sizeof的结果是正确的。

答案放在题目的后面,这里的是无注释版,留给想做题的小伙伴:

//一维数组
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));

//字符数组
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));

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));

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));


//二维数组
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]));

---------------------------------------------------------------------------------------------------------------------------------

//一维数组
int a[] = {1,2,3,4};
答案速对:
16
4/8
4
4/8
4
4/8
16
4/8
4/8
4/8

答案详解:
printf("%d\n",sizeof(a)); 
//答案:16   
//sizeof()里单独放数组名,属特例,数组名指代整个数组,整个数组的大小是4*4= 16

printf("%d\n",sizeof(a+0));
//4/8
//这里不是单独一个数组名,+0不能忽略,所以这里属于一般情况,数组名指数组首元素的地址
//一维数组的首元素的地址是相应元素类型的指针,指针进行加减,指向空间变化,而类型不变
//指针的大小为4/8(在32位平台上指针的大小为4个字节,64位平台上为8个字节)

printf("%d\n",sizeof(*a));
//4
//一般情况,*解引用让操作数的类型减去一个*:int*->
//int 的大小为4个字节

printf("%d\n",sizeof(a+1));
//4/8
//同上上上题的sizeof(a+0),因为加减不会改变元素类型

printf("%d\n",sizeof(a[1]));
//4
//a[1]指数组中第二个元素,元素的类型为int,大小为4个字节

printf("%d\n",sizeof(&a));
//4/8
//虽然数组名不是单独放在sizeof内部的,但是&与数组名单独结合了
//故属于特殊情况:&取出的是整个数组,属于数组指针
//可是数组指针也是指针啊!大小是不变的,故为4/8

printf("%d\n",sizeof(*&a));
//16
//&的优先级和*一样,故从右至左运算
//先是&的特殊情况:取出数组的地址:int(*)[]
//再是*解引用,解引用数组指针得到的就是整个数组:int(*)[] -> int[]
//故大小为4*4=16

printf("%d\n",sizeof(&a+1));
//4/8
//同sizeof(&a),因为加减操作不改变数据类型

printf("%d\n",sizeof(&a[0]));
//4/8
//&没有单独与数组名结合,因为[]的优先级高于&
//故属于一般情况,a[0]指的是数组第一个元素,取出其地址后,类型是int*,大小为4/8

printf("%d\n",sizeof(&a[0]+1));
//4/8
//同上,加减不改变数据的类型

//字符数组
char arr[] = {'a','b','c','d','e','f'};
答案速对:
6
4/8
1
1
4/8
4/8
4/8

答案详解:
printf("%d\n", sizeof(arr));
//6
//特殊情况:计算整个数组的大小,为1*6 = 6

printf("%d\n", sizeof(arr+0));
//4/8
//一般情况,指针类型,加减不改变其类型,故为4/8个字节大小

printf("%d\n", sizeof(*arr));
//一般情况
//*arr -> *(&arr[0])
//&arr[0]的类型为char*,再*解引用减去一个*为char,大小为 1 个字节

printf("%d\n", sizeof(arr[1]));
//1
//arr[1]指的是数组中的第二个元素,类型为char,大小为 1 个字节

printf("%d\n", sizeof(&arr));
//4/8
//特殊情况:取出的是数组的地址,类型为数组指针,大小为4/8字节

printf("%d\n", sizeof(&arr+1));
//4/8
//同&arr,加减不改变数据类型,故为4/8

printf("%d\n", sizeof(&arr[0]+1));
//4/8
//一般情况:取出的是元素的地址,类型是char*,加减不改变类型,故大小为4/8个字节

char arr[] = "abcdef";
答案速对:
7
4/8
1
1
4/8
4/8
4/8

答案详解:
printf("%d\n", sizeof(arr));
//7
//特殊情况:计算整个数组大小,注意!字符串的最后隐藏了一个'\0',故大小为6+1 = 7

printf("%d\n", sizeof(arr+0));
//4/8
//一般情况,指针类型,加减不改变其类型,故为4/8个字节大小

printf("%d\n", sizeof(*arr));
//1
//*arr -> *(&arr[0])
//&arr[0]的类型为char*,再*解引用减去一个*为char,大小为 1 个字节

printf("%d\n", sizeof(arr[1]));
//1
//arr[1]指的是数组中的第二个元素,类型为char,大小为 1 个字节

printf("%d\n", sizeof(&arr));
//4/8
//特殊情况:取出的是数组的地址,类型为数组指针,大小为4/8字节

printf("%d\n", sizeof(&arr+1));
//4/8
//同&arr,加减不改变数据类型,故为4/8

printf("%d\n", sizeof(&arr[0]+1));
//4/8
//一般情况:取出的是元素的地址,类型是char*,加减不改变类型,故大小为4/8个字节

char *p = "abcdef";
答案速对:
4/8
4/8
1
1
4/8
4/8
4/8

答案详解:
printf("%d\n", sizeof(p));
//4/8
//p变量的类型是指针,指针大小为4/8个字节

printf("%d\n", sizeof(p+1));
//4/8
//加减后类型不变,指针类型的大小为4/8个字节

printf("%d\n", sizeof(*p));
//1
//对char*指针解引用:char*->char,大小为1个字节

printf("%d\n", sizeof(p[0]));
//1
//对于指针变量p,p[0]的格式不便理解,将[]转换为*()的格式就好了:p[0]->*(p+0)
//相当于对p进行解引用,解引用后为char类型,大小为1个字节

printf("%d\n", sizeof(&p));
//4/8
//取出的是指针的地址,为二级指针,大小为4/8个字节

printf("%d\n", sizeof(&p+1));
//4/8
//同&p,为二级指针类型,进行加减后类型不变,故大小为4/8个字节

printf("%d\n", sizeof(&p[0]+1));
//4/8
//p[0] = *(p+0),类型为char类型,再&其地址,为char*类型,大小为4/8个字节

//二维数组
int a[3][4] = {0};
答案速对:
48
4
16
4/8
4
4/8
16
4/8
16
16
16

答案详解:
printf("%d\n",sizeof(a));
//48
//特殊情况:取出的是整个二维数组,大小为4*3*4 = 48、

printf("%d\n",sizeof(a[0][0]));
//4
//a[0][0]指的是数组第一行的第一个元素,类型为int, 大小为4个字节

printf("%d\n",sizeof(a[0]));
//16
//特殊情况:二维数组中,a[]代表每一行数组的数组名,故是一行数组的大小:4*4= 16

printf("%d\n",sizeof(a[0]+1));
//4/8
//a[0]为二维数组第一行的数组名
//单独使用,指代数组首元素的地址,为int*,加减类型不变
//故大小为4/8个字节

printf("%d\n",sizeof(*(a[0]+1)));
//4
//a[0]为二维数组第一行的数组名
//单独使用,指代数组首元素的地址,为int*,加减类型不变
//再对其使用解引用,int*->int,大小为4个字节

printf("%d\n",sizeof(a+1));
//4/8
//这里的二维数组名a指的是二维数组中首元素的地址,即第一行数组的地址
//类型为数组指针:int(*)[],加减后类型不变,大小为4/8个字节

printf("%d\n",sizeof(*(a+1)));
//16
//这里的二维数组名a指的是二维数组中首元素的地址,即第一行数组的地址
//类型为数组指针:int(*)[],加减后类型不变
//再对其进行解引用:int(*)[] -> int []
//又第一行有4个元素,大小为4*4 = 16

printf("%d\n",sizeof(&a[0]+1));
//4/8
//特殊情况:&与二维数组第一行数组的数组名结合,取出的是第一行数组的地址
//类型为int(*)[],加减后类型不变,故大小为4/8个字节

printf("%d\n",sizeof(*(&a[0]+1)));
//16
//特殊情况:&与二维数组第一行数组的数组名结合,取出的是第一行数组的地址
//类型为int(*)[],加减后类型不变
//再解引用:int(*)[] -> int []
//又第一行有4个元素,大小为4*4 = 16

printf("%d\n",sizeof(*a));
//16
//这里的二维数组名a指的是二维数组中首元素的地址,即第一行数组的地址
//类型为数组指针:int(*)[]
//再对其进行解引用:int(*)[] -> int []
//又一行中有4个元素,大小为4*4 = 16

printf("%d\n",sizeof(a[3]));
//16
//特殊情况:二维数组第一行的数组名单独放在sizeof中,计算的是整行数组的大小
//4*4 = 16

3.strlen()笔试题

strlen()是计算字符串有效长度的函数,参数是地址,所谓有效长度,指的就是从所给地址开始,一个一个字节地访问,直至访问到'\0'就结束。

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[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));

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));

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));

---------------------------------------------------------------------------------------------------------------------------------

char arr[] = {'a','b','c','d','e','f'};
答案速对:
随机值
随机值
error
error
随机值
随机值
随机值

答案详解:
printf("%d\n", strlen(arr));
//随机值
//arr为数组名,指代数组首元素的地址
//因为所给字符数组不以'\0'结尾,故不确定内存中下一个'\0'出现在哪
//故为随机值

printf("%d\n", strlen(arr+0));
//随机值
//数组名代指数组首元素的地址
//arr为数组名,指代数组首元素的地址,加0后指针不移动
//因为所给字符数组不以'\0'结尾,故不确定内存中下一个'\0'出现在哪
//故为随机值

printf("%d\n", strlen(*arr));
//error
//*arr 指代的是数组首元素:'a'
//'a'的ascii码值为97,被解读成地址时为:0x00000061
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(arr[1]));
//error
//arr[1] 指代的是数组的第二个元素:'b'
//'b'的ascii码值为97,被解读成地址时为:0x00000062
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(&arr));
//随机值
//取出数组的地址,虽然地址的类型是char(*)[]
//但是在传给strlen()时,会进行强制类型转换成char*
//仍旧是一个一个字节地访问
//因为所给字符数组不以'\0'结尾,故不确定内存中下一个'\0'出现在哪
//故为随机值

printf("%d\n", strlen(&arr+1));
//随机值
//取出的是数组的地址,+1后跳过整个数组
//因为所给字符数组不以'\0'结尾,故不确定内存中下一个'\0'出现在哪
//故为随机值

printf("%d\n", strlen(&arr[0]+1));
//随机值
//取出的是数组首元素的地址,+1跳过一个元素
//因为所给字符数组不以'\0'结尾,故不确定内存中下一个'\0'出现在哪
//故为随机值


char arr[] = "abcdef";
答案速对:
6
6
error
error
6
随机值
5

答案详解:
printf("%d\n", strlen(arr));
//6
//双引号表示给数组初始化的值是字符串,故数组最后还有个隐藏的'\0'
//将数组首元素的地址传过去,数组以'\0'结尾,故为6

printf("%d\n", strlen(arr+0));
//6
//双引号表示给数组初始化的值是字符串,故数组最后还有个隐藏的'\0'
//将数组首元素的地址传过去,数组以'\0'结尾,故为6

printf("%d\n", strlen(*arr));
//error
//*arr 指代的是数组首元素:'a'
//'a'的ascii码值为97,被解读成地址时为:0x00000061
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(arr[1]));
//error
//arr[1] 指代的是数组的第二个元素:'b'
//'b'的ascii码值为97,被解读成地址时为:0x00000062
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(&arr));
//6
//取出数组的地址,虽然地址的类型是char(*)[]
//但是在传给strlen()时,会进行强制类型转换成char*
//仍旧是一个一个字节地访问
//数组以'\0'结尾,故为6

printf("%d\n", strlen(&arr+1));
//随机值
//取出的是数组的地址,+1后跳过整个数组
//跳过整个数组后不确定内存中下一个'\0'的位置
//故为随机值

printf("%d\n", strlen(&arr[0]+1));
//5
//取出的是数组首元素的地址,+1跳过一个元素
//数组以'\0'结尾,故为5

char *p = "abcdef";
答案速对:
6
5
error
error
随机值
随机值
5

答案详解:
printf("%d\n", strlen(p));
//6
//指针变量p指代的是数组首元素的地址
//数组以'\0'结尾,故为6

printf("%d\n", strlen(p+1));
//指针变量p指代的是数组首元素的地址,+1跳过一个元素
//数组以'\0'结尾,故为5、

printf("%d\n", strlen(*p));
//error
//*p指代的是'a'
//'a'的ascii码值为97,被解读成地址时为:0x00000061
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(p[0]));
//error
//p[0] 等价于 *(p+0),等价于*p,*p指代的是'a'
//'a'的ascii码值为97,被解读成地址时为:0x00000061
//由于此块空间指向的空间大概率是不能访问的,故为error

printf("%d\n", strlen(&p));
//随机值
//取出的是指针p的地址
//不确定此地址开始后'\0'的位置在哪,故为随机值

printf("%d\n", strlen(&p+1));
//随机值
//取出的是指针p的地址,+1后跳过一个一级指针大小的空间
//不确定此地址开始后'\0'的位置在哪,故为随机值

printf("%d\n", strlen(&p[0]+1));
//5
//取出的是数组首元素的地址,+1跳过一个元素
//数组以'\0'结尾,故为5

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值