指针练习
一维数组
int a[] = {1,2,3,4};
printf("%d\n",sizeof(a));【16】----特例:数组名单独在sizeof内部时,计算的是整个数组的大小
printf("%d\n",sizeof(a+0));【4/8】----数组名是首元素的地址,在a+0是数组中1的地址,因为a+0是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n",sizeof(*a));【4】----数组名是首元素的地址,*是第一个元素,所以计算的是第一个元素的大小
printf("%d\n",sizeof(a+1));【4/8】----数组名是首元素的地址,a+1是数组中2的地址,因为a+1是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n",sizeof(a[1]));【4】----a[1]是数组中的第二个元素,所以计算的是第二个元素的大小
printf("%d\n",sizeof(&a));【4/8】----&a拿到的是整个数组的地址,但&a是地址,所以sizeof(地址)大小为4/8个字节
printf("%d\n",sizeof(*&a));【16】----拿出整个数组的地址,对整个数组的地址解引用
因为8a中的a是数组首元素的地址,a<==>&a[0],*&a[0]相当于a[0],这样就相当于*和&相互抵消
printf("%d\n",sizeof(&a+1));【4/8】----&a+1得到的是指向数组a后面那个位置的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n",sizeof(&a[0]));【4/8】----&a[0]得到的是第一个元素的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n",sizeof(&a[0]+1));【4/8】----&a[0]+1得到的是第二个元素的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
字符数组
## 字符数组
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));【6】----特例:arr数组名单独放在sizeof中,得到的是整个数组的大小
printf("%d\n", sizeof(arr+0));【4/8】----数组名是首元素地址,arr+0得到的是第一个元素的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n", sizeof(*arr));【1】----数组名是首元素的地址,*arr得到的是第一个元素,sizeof(char)是1个字节
printf("%d\n", sizeof(arr[1]));【1】----arr[1]是第二个元素的大小
printf("%d\n", sizeof(&arr));【4/8】----取出的是整个数组的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n", sizeof(&arr+1));【4/8】----&arr拿到的是整个数组的地址,&arr+1指向的是数组后面的那一块空间的地址,因为是地址,所以sizeof(地址)得到的是4/8个字节
printf("%d\n", sizeof(&arr[0]+1));【4/8】----&arr[0]拿到的是数组首元素的地址,&arr[0]+1指向的是数组第二个元素的地址,因为是地址,所以sizeof(地址)得到的是4/8个字节
关于strlen
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));【随机值】因为在字符数组中并没有'\0'的存在,所以在计算长度的时候,得到的是一个随机值
printf("%d\n", strlen(arr+0));【随机值】arr是数组首元素的地址,arr+0得到的也是数组首元素的地址,因为在字符数组中没有'\0'的存在,所以在计算长度的时候,得到的是一个随机值
printf("%d\n", strlen(*arr));【编译错误】----*arr得到的是第一个字符'a',strlen(97),传给strlen的应该是地址,解引用得到a以后,a的地址是野指针
printf("%d\n", strlen(arr[1]));【编译错误】----arr[1]得到的是第二个字符'b' 传给strlen的应该是地址,解引用得到b以后,b的地址是野指针
printf("%d\n", strlen(&arr));【随机值】----&arr得到的是整个数组的地址,因为字符数组中没有'\0'的存在,所以在计算长度的时候,得到的是一个随机值
printf("%d\n", strlen(&arr+1));【随机值-6】----&arr得到的是整个数组的地址,&arr+1指向的是字符数组后面那块空间的地址,所以在计算长度的时候,得到的是一个减去字符数组长度以后的大小,也就是随机值-6
printf("%d\n", strlen(&arr[0]+1));【随机值-1】----&arr[0]得到的是数组的第一个元素的地址,&arr[0]+1得到的是第二个元素的地址,所以在计算长度的时候,得到的是一个减去第一个字符以后长度的大小,也就是随机值-1
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));【7】----arr单独放在sizeof内部的时候,计算的是整个数组的大小,因为sizeof计算的是所占空间的大小,所以也包括'\0' 那么得到的就是7
printf("%d\n", sizeof(arr+0));【4/8】----arr是数组首元素的地址,arr+0得到的还是数组首元素的地址,因为是地址,所以sizeof(地址)得到的大小为4/8
printf("%d\n", sizeof(*arr));【1】----*arr是第一个元素,因为是char类型,所以是1
printf("%d\n", sizeof(arr[1]));【1】----arr[1]是数组中的第二个元素,因为是char类型,所以是1
printf("%d\n", sizeof(&arr));【4/8】----&arr是整个数组的大小,因为是地址,所以sizeof(地址)得到的大小为4/8个字节
printf("%d\n", sizeof(&arr+1));【4/8】----&arr+1指向的是数组后面那块空间的地址,因为是地址,所以sizeof(地址)得到的大小是4/8个字节
printf("%d\n", sizeof(&arr[0]+1));【4/8】----&arr[0]+1得到的是第二个元素的地址,因为是地址,所以sizeof(地址)得到的大小是4/8个字节
printf("%d\n", strlen(arr));【6】----strlen计算的是'\0'之前的元素个数,有6个
printf("%d\n", strlen(arr+0));【6】----strlen计算的是'\0'之前的元素个数,有6个
printf("%d\n", strlen(*arr));【编译错误】*arr得到的是第一个字符'a',strlen(97),传给strlen的应该是地址,解引用得到a以后,a的地址是野指针
printf("%d\n", strlen(arr[1]));【编译错误】----arr[1]得到的是第二个字符'b' 传给strlen的应该是地址,解引用得到b以后,b的地址是野指针
printf("%d\n", strlen(&arr));【6】----strlen计算的是'\0'之前的元素个数,有6个
printf("%d\n", strlen(&arr+1));【随机值】----指向的是数组后面那块空间的地址,不知道何时会遇到'\0',所以是随机值
printf("%d\n", strlen(&arr[0]+1));【5】----strlen计算的是'\0'之前的元素个数,有5个
char *p = "abcdef";
printf("%d\n", sizeof(p));【4/8】----因为p是一个指针变量,指针变量的大小为4/8个字节,取决于编译器
printf("%d\n", sizeof(p+1));【4/8】----假设p的地址为0x0012ff40那么p+1就是0x12ff41 还是一个地址,是地址,sizeof(地址)的大小为4/8个字节
printf("%d\n", sizeof(*p));【1】----因为p是char*类型的,访问一个字节,那么一个字节就是a,就得到1
printf("%d\n", sizeof(p[0]));【1】----p[0] <==> *(p+0) 是首字符a的大小,a是字符,所以是1个字节
printf("%d\n", sizeof(&p));【4/8】----&p取出的是指针变量p的地址,应该用二级指针来保存,但是二级指针也是指针,所以是4/8个字节
printf("%d\n", sizeof(&p+1));【4/8】----&p+1得到的还是地址,但特殊的是,得到的是指针变量p跳过p变量空间,后面的那一块空间的地址,是地址,还是4/8个字节
printf("%d\n", sizeof(&p[0]+1));【4/8】----&p[0]是a的地址,&p[0]+1得到的是b的地址,是地址,就是4/8个字节
printf("%d\n", strlen(p));【6】----p里面放的是a的地址,所以传给strlen的也是a的地址,strlen计算的是'\0'之前的元素个数,有6个
printf("%d\n", strlen(p+1));【5】----p里面放的是a的地址,p+1得到的是b的地址,所以传给strlen的也是b的地址,strlen计算的是'\0'之前的元素个数,有5个
printf("%d\n", strlen(*p));【编译错误】----*arr得到的是第一个字符'a',strlen(97),传给strlen的应该是地址,解引用得到a以后,a的地址是野指针
printf("%d\n", strlen(p[0]));【编译错误】----*arr得到的是第一个字符'a',strlen(97),传给strlen的应该是地址,解引用得到a以后,a的地址是野指针
printf("%d\n", strlen(&p));【随机值】----&p得到的是p的地址,与字符串完全不是一块空间,不知道什么时候会遇到\0停下来,所以是随机值
printf("%d\n", strlen(&p+1));【随机值】----&p+1得到的是p加上1的地址,与字符串完全不是一块空间,不知道什么时候会遇到\0停下来,所以是随机值
printf("%d\n", strlen(&p[0]+1));【5】----&p[0]得到的是a的地址,a的地址+1得到的是b的地址,trlen计算的是'\0'之前的元素个数,有5个
二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));【48】----数组名单独放在sizeof内部,计算的是整个数组的大小 所以是48
printf("%d\n",sizeof(a[0][0]));【4】----arr[0][0]是数组的第一行的第一列元素,是int类型的,所以是4
printf("%d\n",sizeof(a[0]));【16】----我们在访问二维数组的时候,arr[0][j] j的取值范围为0-3 在访问一维数组的时候,j的取值范围为0-9 二维数组的arr[0] arr[1] arr[2]就是二维数组每一行数组的数组名
数组名单独放在sizeof内部,计算的是那一行所有元素的大小,所以是16
printf("%d\n",sizeof(a[0]+1));【4/8】----a[0] <==>&a[0][0],&a[0][0]+1得到的是第一行第二个元素的地址,因为是地址,所以sizeof(地址)的大小为4/8个字节
printf("%d\n",sizeof(*(a[0]+1)));【4】----a[0] <==>&a[0][0],&a[0][0]+1得到的是第一行第二个元素的地址,因为是地址,对其进行解引用,得到的就是int类型的大小
printf("%d\n",sizeof(a+1));【】----a是二维数组的数组名,a表示首元素的地址,二维数组的首元素是它的第一行,a就是第一行的地址,数组的地址+1得到的是第二行的地址,因为是地址,所以是4/8个字节
printf("%d\n",sizeof(*(a+1)));【16】----*(a+1) <==> a[1] 所以sizeof(*(a+1)) <==> sizeof(a[1]),a[1]是第二行的数组名,计算的是第二行的大小
printf("%d\n",sizeof(&a[0]+1));【4/8】----&a[0]拿到的是第一行的地址,&a[0]+1得到的是第二行元素的地址,因为是地址,所以是4/8个字节
printf("%d\n",sizeof(*(&a[0]+1)));【4】----&a[0]拿到的是第一行的地址,&a[0]+1得到的是第二行元素的地址,对其进行解引用,得到的就是4
printf("%d\n",sizeof(*a));【16】----a是首元素的地址,二维数组的首元素是第一行元素,对第一行的地址进行解引用,拿到的就是第一行,第一行单独放在sizeof内部,得到的就是16
printf("%d\n",sizeof(a[3]));【16】----虽然没有第三行,但是会根据类型分析,得到16
总结: 数组名的意义:
1. sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2. &数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3. 除此之外所有的数组名都表示首元素的地址。