首先,来介绍一下sizeof和strlen和数组的一些重要特征。
在C语言中,sizeof是一个关键字,它是用来求大小的,单位是字节。切记,它不是一个函数。这里用一个小程序就可以证明了。
#include <stdio.h>
int main()
{
int a = 0;
printf("%d\n", sizeof(a));
printf("%d\n", sizeof a);
return 0;
}
运行结果如图所示:
我们可以看到,将sizeof后边的括号去掉后,并不会出错,仍能正确输出结果。如果sizeof是函数的话,后边的括号是不能去掉的。因为函数是通过括号来调用的,去掉括号的话,就没法调用函数了。
现在来介绍一下strlen的用法。我们都知道'\0'是一个字符串结束的标志。而strlen就是求从字符串第一个字符到‘\0’之间字符的个数,即字符串的长度。记住,它只有遇到'\0'才会停止计数。当用strlen来求一个地址的长度时,结果往往是随机的,因为我们也不知道到底第几位才是0.('\0'其实就是0,它们的值属性和类型属性都相等)。
数组是很特殊的,只有在两种情况下数组名代表整个数组。
1、数组名单独出现在sizeof内部。
2、数组名跟在&后面
其他所有情况,数组名都代表首元素地址。
下边先来看sizeof的数组之间的爱恨纠葛:
#include <stdio.h>
int main()
{
int a[] = { 1, 2, 3, 4 };//创建一个整型数组
char b[] = { 'a', 'b', 'c', 'd', 'e', 'f' };//创建一个字符数组
printf("%d\n", sizeof(a)); //数组名单独出现在sizeof内部,代表整个数组。求得是整个数组的大小16
printf("%d\n", sizeof(b)); //求得是整个数组的大小6
printf("%d\n", sizeof(a+0)); //数组名代表首元素地址。地址+0还是首元素地址。求得是首元素地址大小4
printf("%d\n", sizeof(b+0)); //求得是首元素地址大小4,只要是地址,不管是整型还是字符,都是4
printf("%d\n", sizeof(*a)); //数组名代表首元素地址。对首元素地址解引用,求得是首元素的大小4
printf("%d\n", sizeof(*b)); //首元素是一个字符,大小为1
printf("%d\n", sizeof(a+1)); //数组名代表首元素地址。地址加1跳过四个字节求第二个元素地址的大小4
printf("%d\n", sizeof(b+1)); //由于是一个字符的地址,加1跳过一个字节,求第二个元素地址的大小4
printf("%d\n", sizeof(a[1]));//a[1]表示第二个元素,求得是第二个元素的大小4
printf("%d\n", sizeof(b[1]));//求得是第二个元素的大小1。这是一个字符数组,所以大小为1
printf("%d\n", sizeof(&a)); //数组名跟在&的后面,表示整个数组。求得是数组a地址的大小4
printf("%d\n", sizeof(&b)); //求得是数组b地址的大小为4
printf("%d\n", sizeof(&a+1));//数组名跟在&的后面,表示整个数组。取地址再加1,跳过整个数组\
//指向数组a的后边,求得是a后边的地址的大小4,虽然后边没有了\
//但求大小是根据类型来求的,又不会真正地去访问,所以不会越界。
printf("%d\n", sizeof(&b+1));//求得是数组b后边的地址大小为4
printf("%d\n", sizeof(&a[0]));//[]优先级比&高,相当于&(a[0]),即对第一个元素取地址,大小为4
printf("%d\n", sizeof(&b[0]));//求得是第一个元素地址的大小为4
printf("%d\n", sizeof(&a[0]+1));//&的优先级比+高,对第一个元素取地址再加1 ,得第二个元素地址大小4
printf("%d\n", sizeof(&b[0]+1));//第二个元素地址的大小为4
printf("%d\n", sizeof(a[10]));//a[10]表示第十个元素,大小为4,虽然不存在第十个元素\
//但是是根据类型来求大小,而不会去访问它,所以不会越界。
printf("%d\n", sizeof(b[10]));//这是一个字符数组,第十个元素大小为1
return 0;
}
运行结果如下:
下边再来看看strlen跟数组的恩怨情仇
#include <stdio.h>
#include <string.h>
int main()
{
char a[] = { 'a', 'b', 'c', 'd', 'e', 'f' };
char *p = "abcdef";
printf("%d\n", strlen(a));//随机值 a代表首元素地址,第几个是0,未知
printf("%d\n", strlen(a+0));//随机值 首元素地址加0还是首元素地址,与上一个的值应该是一样的
//printf("%d\n", strlen(*a));//错误 对首元素地址进行解引用,得到的只有一个字符 没有'\0'
//printf("%d\n", strlen(a[1]));//错误 表示首元素,没有'\0'
printf("%d\n", strlen(&a));//随机值 a跟在&后边代表整个数组,求整个数组地址的长度。第几个是0,未知
printf("%d\n", strlen(&a+1));//随机值 取整个数组的地址再加1,求得是数组后边地址的长度
printf("%d\n", strlen(&a[0]+1));//随机值 对首元素取地址再加1,表示第二个元素的地址,对其求长度
printf("%d\n", strlen(p));//6 p单独出现但不是单独出现在sizeof内部,表示首元素的地址
printf("%d\n", strlen(p+1));//5 p表示首元素地址,加1表示第二个字符的地址
//printf("%d\n", strlen(*p));//错误 对首元素地址进行解引用 得到的是第一个字符
//printf("%d\n", strlen(p[0]));//错误 相当于*(p+0)表示第一个字符
printf("%d\n", strlen(&p));//随机值 表示整个字符串的地址,对地址求长度
printf("%d\n", strlen(&p+1));//随机值 求字符串的后边地址的长度
printf("%d\n", strlen(&p[0] + 1));//5 对首元素取地址再加1 表示第二个元素的地址
return 0;
}
运行结果:
PS:本文是基于32位平台上的。