经过这些例子,可以加深对sizeof,数组,数组名,取数组地址,地址加一,指针,指针加一的理解,一定要特别注意数组名在不同场景下的含义
一:数组名是数组首元素的地址
但是有2个例外
除此之外,所有的数组名都是数组首元素的地址
二:指针的大小:32位平台下都是4字节,64位平台下都是8字节
三: strlen -函数:求字符串长度的,找’\0’之前出现的字符个数;sizeof -操作符:算变量/类型所占内存大小,单位是字节
strlen函数原型:size_t strlen ( const char * str ); 参数是指向字符类型的指针
记住上面的规则后,让我们开始吧~
int a[ ] = { 1,2,3,4 }; //4*4=16
printf( "%d\n", sizeof(a)) ; //16 整个数组的大小是16
printf("%d\n", sizeof(a + 0)); /*4或8 a + 0是第一个元素的地址,sizeof(a + 0)计算的是地址的大小,sizeof后面跟的不是单 个a,就不是一整个数组*/
printf ("%d\n", sizeof(*a)); //4 *a是数组的第一个元素,sizeof(*a)计算的是第一个元素的大小
printf ("%d\n", sizeof(a + 1)); //4或8 a + 1是第二个元素的地址,sizeof(a+1)计算的地址的大小
printf ( "%d\n", sizeof(a[1])); //4 计算的是第二个元素的大小
printf ("%d\n", sizeof(&a)); //4/8 &a取出的是整个数组的地址,但也是地址,计算的是一个地址的大小
printf ( "%d\n", sizeof(*&a)); //16 先取出整个数组的地址,再解引用,得到的还是整个数组,计算的数组的大小
printf ("%d\n", sizeof(&a + 1)); /*4/8 &a得到一整个数组的地址,+1后跳过一整个数组,是数组最后一个元素后面的 空间的地址*/
printf ( "%d\n", sizeof(&a[0])); //4/8 第一个元素的地址
printf ( "%d\n", sizeof(&a[0] + 1)); //4/8 第二个元素的地址
char arr[ ]= { ‘a’, ‘b’,‘c’, ‘d’ , ‘e’, ‘f’ };
printf ("%d\n", sizeof(arr)); //6 整个数组的大小为6
printf ("%d\n", sizeof(arr + 0)); //4/8 首元素地址+0还是地址
printf ("%d\n", sizeof(*arr)); //1 首元素地址解引用得到字符a,大小是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 &arr[0]是第一个元素的地址,+1后是第二个元素的地址
printf("%d\n",strlen(arr)); //随机值,从首元素地址开始找,strlen会一直找到'\0'为止
printf ("%d\n", strlen(arr + 0)); //随机值,首元素地址加0还是首元素地址
printf ("%d\n", strlen(*arr)); /*error,首元素地址解引用得到的是字符'a',ASCII码值是97,而strlen函数的参数是(char* str),接收的是地址*/
printf ("%d\n", strlen(arr[1])); //error,同理,把字符'b'传过去也是出错
printf ("%d\n", strlen(&arr)); /*随机值,取一整个数组的地址传给strlen函数时,也会被强制类型转换为char*类型,也是从首 元素地址开始找起*/
printf ("%d\n", strlen(&arr + 1)); /*随机值-6,取一整个数组地址后+1,就跳到了该数组最后一个元素的后一个地址,相比从首元素开始找,此时直接跳过了数组的长度,所以要-6,但找的结果仍然是随机值*/
printf ("%d\n", strlen(&arr[0]+ 1)); /*随机值-1,取首元素的地址后+1,得到第二个元素的地址,跳过了一个元素长度,所以要-1;*/
char arr[ ]= “abcdef” ;
内存存放形式:[a b c d e f \0]
printf ("%d\n", sizeof(arr)); //7 双引号""默认在最后加上'\0',sizeof会把'\0'也算上
printf ("%d\n", sizeof(arr + 0)); //4/8 首元素地址+0还是地址
printf ("%d\n", sizeof(*arr)); //1 首元素地址解引用得到字符'a','a'的大小
printf ("%d\n", sizeof(arr[1])); //1 字符'b'的大小
printf ("%d\n", sizeof(&arr)); //4/8 取一整个数组的地址
printf ("%d\n", sizeof(&arr + 1)); //4/8 跳过一整个数组后还是地址
printf ("%d\n", sizeof(&arr[0]+ 1)); //4/8 第二个元素的地址
printf ("%d\n", strlen(arr)); //6 strlen从首元素开始向后检索字符,遇到'\0'就停下,不包括'\0'
printf ("%d\n", strlen(arr + 0)); //6 首元素地址+0还是从首元素开始检索
printf ("%d\n", strlen(*arr)); //error
printf ("%d\n", strlen(arr[1])); //error
printf ("%d\n", strlen(&arr)); //6 一整个数组的地址,传给strlen也是从首地址开始
printf ("%d\n", strlen(&arr + 1)); //随机值 取出一整个数组的地址后+1,跳过一整个数组,跳到'\0'的后一个地址,开始检索时不知什么时候会找到'\0'
printf ("%d\n", strlen(&arr[0] + 1)); //5 从第二个元素开始找
char* p = “abcdef” ;
指针p指向一块连续的常量空间,[a b c d e f \0]
printf ("%d\n", sizeof(p)); //4/8 求的是p指针的大小
printf ("%d\n", sizeof(p + 1)); //4/8 p指向的是字符a的地址,+1就指向字符b的地址,终究还是地址
printf ("%d\n", sizeof(*p)); //1 p指针解引用得到字符a,大小为1
printf ("%d\n", sizeof(p[0])); //1 p[0] == *(p+0),得到字符a,大小为1
printf ("%d\n", sizeof(&p)); //4/8 取指针p自己的地址
printf("%d\n", sizeof(&p + 1)); //4/8 跳过一个p的地址,即指针p的后一块地址空间
printf("%d\n", sizeof(&p[0] + 1)); //4/8 &p[0]得到第一个元素的地址,+1得到第二个元素的地址
printf("%d \n", strlen(p)); //6
printf ("%d \n", strlen(p + 1)); //5 p指向第一个字符地址,+1后指向第二个字符地址
printf ("%d\n", strlen(*p)); //error
printf ("%d\n", strlen(p[0])); //error
printf ("%d\n", strlen (&p)); //随机值 取p指针自身的地址,因为p占4/8个字节,从首字节开始找,不知何时才找到'\0'
printf ("%d \n", strlen (&p + 1)); //随机值 从p指针最后一个字节的后一个地址开始找,也不知何时找到'\0',因为不确定p指针中有没有'\0',所以这个随机值并没有-1,跟上一个随机值没有联系
printf ("%d\n", strlen ( &p[0] + 1)); //5 从第二个元素开始找
int a[ 3] [4]={ 0 };
a[0]:第一行一维数组的数组名
a[1]:第二行一维数组的数组名
a[2]:第三行一维数组的数组名
printf ("%d\n", sizeof(a)) ; //48 3*4*sizeof(int),sizeof里是单独的二维数组名,就表示一整个二维数组的大小
printf ("%d\n", sizeof(a[0][0])); //4 第一行第一个元素值,整型元素大小是4
printf ("%d\n", sizeof(a[0])); //16 a[0]表示整个第一行,数组名a[0]单独放在sizeof内部,sizeof(a[0])计算的就是第一行一维数组的大小!
printf ("%d\n", sizeof(a[0]+ 1)); //4/8 a[0]作为数组名并没有单独出现在sizeof内,也没取地址,所以a[0]就是第一行第一个元素的地址,a[0]+1就是第一行第二个元素的地址
printf ("%d\n", sizeof(*(a[0] + 1))); //4 第一行第二个元素值
printf ("%d\n", sizeof(a + 1)) ; //4/8 a是二维数组的数组名,并没有取地址,也没有单独放在sizeof内,所以表示的是二维数组首元素的地址,即第一行的地址,a+1就是二维数组第二行的地址
printf ("%d\n", sizeof(*(a + 1))); //16 因为*(a+1) == a[1],a[1]表示的是第二行的地址,由因为sizeof(a[1])是单独放在sizeof内部的,表示第二行一整个一维数组的地址,所以求的是一整个一位数组的大小
printf ("%d\n", sizeof(&a[0] + 1)); //4/8 &a[0]+1 == a+1 a[0]是第一行的数组名,&a[0]取出的是第一行整个一维数组的地址,+1后就是第二行整个一维数组的地址
printf ("%d\n", sizeof(*(&a[0]+ 1))); //16 *(&a[0]+1) == *(a+1) &a[0]+1得到的就是第二行整个一维数组的地址,解引用得到一整个第二行一维数组,所以大小是16
printf ("%d\n", sizeof(*a)); //16 *a == *(a+0) == a[0],a是二维数组的数组名,并没有取地址,也没有单独放在sizeof内,表示第一行的地址,等于第一行数组名单独放到sizeof中,相当于求第一行整个一维数组的大小
printf ("%d\n", sizeof(a[3])); //16 a[3]的类型是 int [4],其实是第四行的数组名(如果有的话),此时sizeof并不会真正去访问a[3]的地址,只是根据其类型计算出大小,sizeof()内部的表达式是不算的! 比如表达式:3+5 具有:1.值属性 -> 8 2.类型属性 -> int,sizeof就是推测出类型属性从而计算大小的