C语言强化指针与数组练习
目标
1.掌握sizeof和strlen的具体用法。
2.掌握指针与数组。
进入正题之前,请大家牢记以下几点
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3.除此之外,所有的数组名都表示首元素的地址。
然后我们来看下面的题目
题目:
sizeof() 是一个判断数据类型或者表达式长度的运算符
int main()
{
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));
return 0;
}
题目分析:
printf("%d\n", sizeof(a)); // 16
a是数组名,sizeof(数组名)表示计算整个数组的大小
printf("%d\n", sizeof(a + 0));// 4或8
这里的sizeof(a+0) 数组名不是单独放在sizeof中的,所以这里的a表示数组首元素的地址,那么首元素地址+0,就还是首元素地址,所以sizeof(a+0)计算的是数组首元素的地址的大小。(注意:无论什么类型数据地址的大小在32位系统环境下是4字节,在64位系统环境下是8字节)
printf("%d\n", sizeof(*a)); // 4
a是首元素的地址,*a就得到了 1。所以sizeof(*a),就是计算int在内存中的大小。(int在内存中的大小为4)
printf("%d\n", sizeof(a + 1)); // 4或8 这里与第二个同理
printf("%d\n", sizeof(a[1])); // 4 a[1]取到a下标为1的数字2,所以还是计算int在内存中的大小
printf("%d\n", sizeof(&a)); // 4或8 &a取到的是整个数组的地址,所以是计算地址大小
printf("%d\n", sizeof(*&a)); // 16 &a取到的是整个数组的地址,*&a得到1,2,3,4 所以4x4=16
printf("%d\n", sizeof(&a + 1)); // 4或8 &a+1的位置如图,计算地址大小。
printf("%d\n", sizeof(&a[0])); // 4或8 a[0]拿到1,&a[0]拿到1的地址,计算地址大小。
printf("%d\n", sizeof(&a[0] + 1)); // 4或8 如图位置的地址,计算地址大小
题目:
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));
题目解析:
printf("%d\n", sizeof(arr)); // 6
sizeof(arr)表示计算整个arr,char类型在内存中占1个字节,1X6=6
printf("%d\n", sizeof(arr+0)); // 4或8
sizeof(arr+0) arr不是单独存在在sizeof()中,所以arr+0表示的是a元素的地址,所以计算的是地址。
printf("%d\n", sizeof(*arr));// 1
arr是数组名表示数组首元素的地址,*arr取到数组首元素a,a是char类型在内存中占1个字节的大小
printf("%d\n", sizeof(arr[1]));// 1
arr[1]取到数组下标为1的元素b,b是char类型再内存中占1字节
printf("%d\n", sizeof(&arr)); //4/8
&arr取出的是整个数组的地址,所以在sizeof()中计算的是地址的大小4字节或8字节
printf("%d\n", sizeof(&arr+1)); // 4或8
&arr取的是整个数组的地址,&arr+1表示到这个数组的下一个位置中,如图
printf("%d\n", sizeof(&arr[0]+1));// 4或8
&arr[0]取到的是a元素的地址,&arr[0]+1表示b元素的地址。如图
题目:
strlen():计算的是字符串str的长度,从字符的首地址开始遍历,以 ‘\0’ 为结束标志,然后将计算的长度返回,计算的长度并不包含’\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));
题目解析:
printf("%d\n", strlen(arr)); // 随机数
arr取到是首元素的地址,strlen函数遇到’\0’才会停,但arr在内存中是这么存放的。如图
没有\0,所以会在arr内存后一直找,直到找到\0。
printf("%d\n", strlen(arr+0)); // 随机值
arr+0拿到的是a的地址,拿到a的地址之后接着往后找'\0',同上图
printf("%d\n", strlen(*arr)); // error
*arr拿到了a元素,但srtlen函数需要接收一个地址,直接传元素会出错
printf("%d\n", strlen(arr[1])); //error
arr[1]取到的是元素b,srtlen函数需要接收一个地址,直接传元素会出错
printf("%d\n", strlen(&arr)); //随机值
&arr 取到的是整一个数组的地址,如图
printf("%d\n", strlen(&arr+1)); // 随机值-6
如图
printf("%d\n", strlen(&arr[0]+1)); //随机值-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));
题目分析:
printf("%d\n", sizeof(arr)); // 7
sizeof(数组名)会计算整个数组的大小,并且会计算'\0'
如图:
printf("%d\n", sizeof(arr+0)); // 4或8
arr+0拿到的是地址,计算的地址的大小
printf("%d\n", sizeof(*arr)); // 1
*arr取到的是数组首元素a,sizeof(*arr)计算的a的大小 1*1=1
printf("%d\n", sizeof(arr[1])); // 1
arr[1]取到数组下标为1的元素 b,计算大小 1*1=1
printf("%d\n", sizeof(&arr)); // 4或8
&arr取到的是整个数组的地址,sizeof(&arr)计算的是地址的大小
printf("%d\n", sizeof(&arr+1)); // 4或8
如图,计算该位置地址的大小
printf("%d\n", sizeof(&arr[0]+1)); // 4或8
如图,计算该位置的地址
题目:
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));
题目分析:
printf("%d\n", strlen(arr)); // 6
arr是数组名,这里表示首元素的地址,strlen遇到’\0‘ 返回首元素到到‘\0’的元素个数。
printf("%d\n", strlen(arr+0)); // 6
arr+0,也是首元素的地址。同上。
printf("%d\n", strlen(*arr)); // error
arr表示首元素地址,*arr拿到单个元素a,而strlen接收的是地址(size_t strlen (const char* str)),传入单个元素会导致报错
printf("%d\n", strlen(arr[1])); //error
arr[1]取到数组下标为1的元素 b,同上
printf("%d\n", strlen(&arr)); //6
&arr取到的是整个数组的地址,如图
printf("%d\n", strlen(&arr+1)); // 随机值
如图 直到找到’\0‘
printf("%d\n", strlen(&arr[0]+1)); //5
如图
题目:
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));
题目分析:
printf("%d\n", sizeof(p)); // 4或8
p中存了的是a的地址,这里计算的是地址的大小
printf("%d\n", sizeof(p+1)); //4或8
同上
printf("%d\n", sizeof(*p)); // 1
*p拿到的是元素a,a的大小 1*1 = 0
printf("%d\n", sizeof(p[0])); // 1
p[0]拿到的是元素a,a的大小1*1=0
printf("%d\n", sizeof(&p)); // 4或8
&p取到的是p的地址,所以是计算地址的大小
printf("%d\n", sizeof(&p+1)); // 4或8
如图
printf("%d\n", sizeof(&p[0]+1)); 4或8
p[0]是a元素,&p[0]取到p的元素,+1找到b的地址。计算b地址大小
题目:
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));
题目分析:
printf("%d\n", strlen(p)); // 6
p中存的是a的地址,传给strlen后直接计算字符串的大小。
printf("%d\n", strlen(p+1)); // 5
a的地址加一,得到b的地址,从b处开始计算字符串的大小
printf("%d\n", strlen(*p)); //error 取到字符a
printf("%d\n", strlen(p[0])); // error 取到字符a
strlen需要是的地址,直接传字符会报错!
printf("%d\n", strlen(&p)); //随机值
如图
printf("%d\n", strlen(&p+1)); //随机值
如图
printf("%d\n", strlen(&p[0]+1)); //5
p[0]是a元素,&p[0]取到p的元素,*p[0]+1找到b的地址,从b处开始计算字符串大小
题目:
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]));
题目分析:
printf("%d\n", sizeof(a)); // 48
3*4*sizeof(int) = 3*4*4 = 48
printf("%d\n", sizeof(a[0][0])); //4或8
代表第一行第一个元素
printf("%d\n", sizeof(a[0])); //16
这里将a[0]理解为二维数组第一行的数组名
那么sizeof(a[0])就是计算第一行数组的大小,4*sizeof(int) = 4*4 = 16
printf("%d\n", sizeof(a[0]+1)); // 4或8
a[0]作为数组名没有单独存放在sizeof()中
可以将a[0]+1理解为 a[0][1]
也没有取地址,所以a[0]算是第一行第一个元素地址
a[0]+1就是第一行第二个元素地址。
printf("%d\n", sizeof(*(a[0]+1))); // 4
*(a[0]+1) 可以看做 *(a[0][1]) 拿到的是第一行第2个元素,计算的是元素的大小.
printf("%d\n", sizeof(a+1)); // 4或8
a是二维数组的数组名,并没有取地址,也没有单独放在sizeof()中
所以a就表示首元素的地址,即第一行的地址,a+1就是第二行的地址,计算的是地址的大小。
printf("%d\n", sizeof(*(a+1))); // 16
a+1是第二行的地址,*(a+1)取到第二行的所以元素,计算的是元素大小,4*4= 16
printf("%d\n", sizeof(&a[0]+1)); //4或8
a[0]是数组名,&a[0]取到第一行的地址,&a[0]+1就表示第二行的地址,计算地址大小
printf("%d\n", sizeof(*(&a[0]+1))); // 16
&a[0]+1表示第二行的地址,*(&a[0]+1)拿到第二行的所以元素,计算元素大小,4*4 = 16
printf("%d\n", sizeof(*a)); // 16
a是数组名,即没有取地址,也没有单独放在sizeof()中,所以在这里表示首元素的地址,即第一行的地址
*a就是取到第一行所有的元素,所以计算的是元素的大小 4*4 = 16
printf("%d\n", sizeof(a[3])); //16
a[3]是第4行的数组名(如果有的话),所以不存在,也可以通过类型来计算大小的
总结
1.sizeof(数组名),这里的数组名表示整个数组,计算的是整个数组的大小。
2.&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。
3.除此之外,所有的数组名都表示首元素的地址。
4.strlen函数接收的是地址,并且遇到’\0’才会返回。
5.数组arr可以 arr[2] <=>*(arr+2) <=> *(2+arr) <=> 2[arr]
以上。