C语言-对数组名的深入了解

我们知道一般情况下,c语言中的数组名一般是指首元素的地址,但是有两种特殊的情况除外

第一种情况就是:&(取地址符)+数组名,比如 &arr 其实取出的是整个数组的地址

不管是什么地址,大小都是4 or 8

int arr[5]={0};
我们来尝试比较下面几组案例
printf("%p",arr);
printf("%p",arr+1);
//我们常规的认知告诉我们数组名就是首元素的地址,当然这里也不例外
//所以第一个打印的就是第一个元素的地址,第二个打印就是第二个元素的地址
printf("%p",&arr[0]);
printf("%p",&arr[0]+1);
//这两行代码打印出来的结果和上面的结果一致
上面两组中的数据的地址都相差4,也就是sizeof(int).
但是下面这段代码的结果就不一样了
printf("%p",&arr);
printf("%p",&arr+1);
下面我们来分析以下,arr是一个数组,那我们&arr得到的其实是整个数组的地址
而整个数组的地址其实也就是第一个元素的地址,所以&arr与arr,&arr[0]打印的结果一致
但是&arr+1,因为是整个数组的地址+1,所以就是跳过了整个数组,两个的地址相差20,
这个20也就是sizeof(int)*5所得

而第二种情况就是:sizeof(数组名),记住是严格的sizeof(数组名),而其他的不行

在我们的日常认知中,数组名就是首元素的地址,所以sizeof(数组名)算的大小应该是4 or 8,因为既然是地址,那么大小就应该是4 or 8,但是这里计算的结果却是整个数组的大小!

*比较sizeof与strlen*

首先我们要认识一下sizeof,这个东西并不是一个函数,只是一个操作符,所以不用引用相关头文件,其次sizeof可以计算任何空间的大小,基本上没有限制

但是strlen函数参数为(const char* s),返回值为unsigned int,遇到\0处就结束,列属头文件<string.h>

所以只针对字符串

下面我们给出几组例子进行区分

1.一维数组

1.一维数组
int arr[] = { 1,2,3,4 };
	printf("%d\n", sizeof(arr));
//结果为16,原因是这里计算的整个数组的大小
	printf("%d\n", sizeof(arr+0));
//我们上面说,sizeof(数组名)计算的是数组的大小,但是要严格按照这个格式
//这里看起来好像没什么区别,但是这里的arr其实又当作了首元素的地址
//arr+1其实就是第一个元素的地址,是地址就是4/8
	printf("%d\n", sizeof(*arr));
//这里直接就是第一个元素,所以是int类型,所以为4
	printf("%d\n", sizeof(arr+1));
//这里同第二个计算的是第二个元素的地址,所以为4/8
	printf("%d\n", sizeof(arr[1]));
//计算的第二个元素的大小所以为4
	printf("%d\n", sizeof(&arr));
//我们知道&arr表示的是整个数组的地址,与第一个元素的地址一致,
//是地址那么就是4/8
	printf("%d\n", sizeof(*&arr));
//*&抵消,所以这里其实就是sizeof(arr),结果为16
	printf("%d\n", sizeof(&arr+1));
//&arr表示把整个数组的地址取出来,+1之后跳过了一个数组的长度
//代表该数组后面的第一个元素的地址,是地址就是4/8
	printf("%d\n", sizeof(&arr[0]));
//没什么可说的,就是第一个元素的地址,4/8
	printf("%d\n", sizeof(&arr[0]+1));
//同上,表示第二个元素的地址,4/8

2.字符数组(sizeof)

2.字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));
//这里仍然记录的是整个数组的大小,所以结果为6
printf("%d\n", sizeof(arr+0));
//这个表示的第一个字符的地址,是地址就是4/8
printf("%d\n", sizeof(*arr));
//对一个字符解引用就是'a',所以是1
printf("%d\n", sizeof(arr[1]));
//同上'a'所以是1
printf("%d\n", sizeof(&arr));
//取出的整个数组的地址,是地址就是4/8
printf("%d\n", sizeof(&arr+1));
//类比整形,就是跳过了整个数组,但是还是地址,所以为4/8
printf("%d\n", sizeof(&arr[0]+1));
//就是第二个字符的地址,是地址就是4/8

3.字符数组(strlen)

由于字符数组没有结束标志\0,所以一般都为一个随机数
记作rand_number
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));
//为rand_number
printf("%d\n", strlen(arr+0));
//与上面那个完全一致,也是rand_number
printf("%d\n", strlen(*arr));
//*arr其实就是字符'a',ascii码值为97,所以相当于访问内存地址为97的数据
//相当于对不属于自己的内存进行操作,系统会挂掉
printf("%d\n", strlen(arr[1]));
//类比上面的那个,相当于从'b'开始,也就是从地址98开始,也会挂掉
printf("%d\n", strlen(&arr));
//&arr其实就相当于第一个元素的地址,所以结果应该是rand_number
printf("%d\n", strlen(&arr+1));
//&arr+1相当于跳过了整个数组,所以结果应该是rand_number-6
//这个6其实是整个数组的大小
printf("%d\n", strlen(&arr[0]+1));
//相当于从第二个字符的地址开始,所以结果应该是rand_number-1

4.字符串(用数组存储)

char arr[] = "abcdef";
与字符数组不同的是,自带\作为结束标志,所以这个数组内的元素个数应该是7
1.sizeof
printf("%d\n", sizeof(arr));
//这里计算的整个数组的大小,也就是7
printf("%d\n", sizeof(arr+0));
//第一个元素的地址,4/8
printf("%d\n", sizeof(*arr));
也就是第一个字符的大小,为1
printf("%d\n", sizeof(arr[1]));
//第二个字符大小,为1
printf("%d\n", sizeof(&arr));
//相当于整个数组的地址,所以为4/8
printf("%d\n", sizeof(&arr+1));
//跳过了一个数组,但是仍是地址,是地址就是4/8
printf("%d\n", sizeof(&arr[0]+1));
//第二个元素地址,是地址就是4/8

2.strlen
printf("%d\n", strlen(arr));
//字符串长度6
printf("%d\n", strlen(arr+0));
//字符串长度6
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));
//从第二字符开始就是5

5.字符串(用指向首元素的指针存储)

char *p = "abcdef";
//这个与上面存储字符串的方式不同的地方就是,这个字符串是只读的,不可改
//位于字符串常量区,但是访问元素的方式与上面的那个类似
1.用sizeof
printf("%d\n", sizeof(p));
//表示第一个字符地址,是地址就是4/8
printf("%d\n", sizeof(p+1));
//表示第二个字符地址,是地址就是4/8
printf("%d\n", sizeof(*p));
//表示第一个字符'a',所以为1
printf("%d\n", sizeof(p[0]));
//是'a',就是1
printf("%d\n", sizeof(&p));
//二级指针,但是仍然是地址,是地址就是4/8
printf("%d\n", sizeof(&p+1));
//是地址就是4/8
printf("%d\n", sizeof(&p[0]+1));
//第二个字符的地址,是地址就是4/8

2.strlen
printf("%d\n", strlen(p));
//字符串的长度6
printf("%d\n", strlen(p+1));
//从第二个字母开始的长度为5
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));
//是第二元素的地址,是地址就是4/8

*总结*

数组名的意义:

1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。

2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。

3. 除此之外所有的数组名都表示首元素的地址。

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值