理解指针(4)

1.sizeof和strlen的对比

sizeof计算变量所占内存空间大小,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。

sizeof只关注占用内存空间的大小,不在乎内存中存放什么数据。sizeof是单目操作符,不是函数。

sizeof括号中有表达式的话,表达式是不参与计算的(可变长度数组除外)。

strlen是C语言库函数,功能是求字符串的长度。

size_t strlen ( const char * str );

统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。

strlen函数会一直向后找\0字符,直到找到为止,所以可能存在越界查找。

使用:

#include <stdio.h>
int main()
{
	char arr1[3] = { 'a','b','c' };
	char arr2[] = "abc";
	printf("%d\n", strlen(arr1));//随机值
	printf("%d\n", strlen(arr2));//3

	printf("%d\n", sizeof(arr1));//3
	printf("%d\n", sizeof(arr2));//4
	return 0;
}

数组名的理解:

数组名是首元素的地址但有两个情况除外:

1、sizeof(数组名),数组名表示整个数组,计算的是整个数组的大小,单位是字节。

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

2.数组和指针的笔试题解析(一维数组)

	int a[] = { 1,2,3,4 };
(1)	printf("%d\n", sizeof(a));
(2)	printf("%d\n", sizeof(a+0));
(3)	printf("%d\n", sizeof(*a));
(4)	printf("%d\n", sizeof(a+1));
(5)	printf("%d\n", sizeof(a[1]));
(6)	printf("%d\n", sizeof(&a));       //  *a == a[0] == *(a+0)
(7)	printf("%d\n", sizeof(*&a));
(8)	printf("%d\n", sizeof(&a+1));
(9)	printf("%d\n", sizeof(&a[0]));
(10)printf("%d\n", sizeof(&a[0]+1));

(1)结果是:16;解释:sizeof(数组名)计算的是整个数组的大小,int大小为4个字节。

(2)结果是:4/8;解释:a是首元素的地址类型是int*,a+0还是首元素的地址,是地址大小就是4/8

(3)结果是:4;解释:a是首元素的地址,*a是首元素,大小为4个字节。

(4)结果是:4/8;解释:a是首元素的地址类型是int*,a+1跳过一个整型是第二个元素的地址,是地址大小为4/8。

(5)结果是:4;解释:a[1]就是第二个元素的大小为4个字节。

(6)结果是:4/8;解释:&a就是整个数组的地址,数组的地址也是地址,是地址大小为4/8。

(7)结果是:16;解释:有两个解释,第一个:*和&相互抵消了,sizeof(*&a) == sizeof(a)

第二个&a取出的是整个数组地址,类型是int(*)[4],对数组指针解引用访问的是整个数组大小为16

(8)结果是:4/8;解释:&a+1是跳过整个数组后面那个位置的地址,是地址大小为4/8

(9)结果是:4/8;解释:首元素的地址,是地址大小为4/8

(10)结果是:4/8;解释:第二个元素的地址,是地址大小为4/8

3.数组和指针的笔试题解析(字符数组)

    char arr[] = { 'a','b','c','d','e','f' };
(1)	printf("%d\n", sizeof(arr));
(2)	printf("%d\n", sizeof(arr+0));
(3)	printf("%d\n", sizeof(*arr));
(4)	printf("%d\n", sizeof(arr[1]));
(5)	printf("%d\n", sizeof(&arr));
(6)	printf("%d\n", sizeof(&arr+1));
(7)	printf("%d\n", sizeof(&arr[0]+1));

(1)结果是:6;解释:sizeof(数组名)计算的是整个数组的大小。

(2)结果是:4/8;解释:arr是数组名表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8

(3)结果是:1;解释:arr是首元素的地址,*arr表示数组第一个元素大小为1个字节

(4)结果是:1;解释:第二个元素的大小为1个字节。

(5)结果是:4/8;解释:&arr是整个数组的地址,是地址大小为4/8个字节。

(6)结果是:4/8;解释:&arr+1跳过整个数组指向数组后面的地址大小为4/8个字节。、

(7)结果为:4/8;解释:第二个元素的地址大小为4/8个字节。

	char arr[] = { 'a','b','c','d','e','f' };
(1)	printf("%d\n", strlen(arr));
(2)	printf("%d\n", strlen(arr+0));
(3)	printf("%d\n", strlen(*arr));
(4)	printf("%d\n", strlen(arr[1]));
(5)	printf("%d\n", strlen(&arr));
(6)	printf("%d\n", strlen(&arr+1));
(7)	printf("%d\n", strlen(&arr[0]+1));

(1)结果是:随机值;解释:arr是首元素的地址,数组中没有\0就会导致越界访问结果就是随机值

(2)结果是:随机值;解释:arr+0是首元素地址,数组中没有\0就会导致越界访问结果就是随机值

(3)结果是:代码出现问题;解释:arr是首元素地址,*arr是首元素,就是'a','a'的ASCII码值是97,就相当于把97作为地址传给了strlen,strlen得到的是野指针,代码有问题。

(4)结果是:代码有问题;解释:arr[1]指向的是第二个元素'b',和上一个一样的都是有问题的。

(5)结果是:随机值;解释:&arr是数组的地址起始位置是第一个元素地址和(1)的计算是相同的。

(6)结果是:随机值;解释:&arr+1是跳过整个数组之后的地址,但是也是随机值,只是比&arr计算的随机值少了6。

(7)结果是:随机值;解释:&arr[0]+1得到的是第二个元素的地址,计算的随机值比&arr计算的随机值少了1。

    char arr[] = "abcdef";
(1)	printf("%d\n", sizeof(arr));
(2)	printf("%d\n", sizeof(arr+0));
(3)	printf("%d\n", sizeof(*arr));
(4)	printf("%d\n", sizeof(arr[1]));
(5)	printf("%d\n", sizeof(&arr));
(6)	printf("%d\n", sizeof(&arr+1));
(7)	printf("%d\n", sizeof(&arr[0]+1));

(1)结果是:7;解释:sizeof(数组名)计算的是整个字符串的大小,要加上一个\0。

(2)结果是:4/8;解释:arr表示首元素的地址,arr+0还是首元素的地址,是地址就是4/8

(3)结果是:1;解释:arr是首元素的地址,*arr表示字符串第一个元素大小为1个字节

(4)结果是:1;解释:第二个元素的大小为1个字节。

(5)结果是:4/8;解释:&arr是整个字符串的地址,是地址大小为4/8个字节。

(6)结果是:4/8;解释:&arr+1跳过整个字符串指向字符串后面的地址大小为4/8个字节。、

(7)结果为:4/8;解释:第二个元素的地址大小为4/8个字节。

	char arr[] = "abcdef";
(1)	printf("%d\n", strlen(arr));
(2)	printf("%d\n", strlen(arr+0));
(3)	printf("%d\n", strlen(*arr));
(4)	printf("%d\n", strlen(arr[1]));
(5)	printf("%d\n", strlen(&arr));
(6)	printf("%d\n", strlen(&arr+1));
(7)	printf("%d\n", strlen(&arr[0]+1));

(1)结果是:6;解释:strlen计算\0之前的数组大小。

(2)结果是:6;解释:arr表示首元素的地址,arr+0也是首元素的地址,计算整个字符串的大小。

(3)结果是:代码运行错误;解释:arr是首元素地址,*arr是首元素,就是'a','a'的ASCII码值是97,就相当于把97作为地址传给了strlen,strlen得到的是野指针,代码有问题。

(4)结果是:代码有问题;解释:arr[1]指向的是第二个元素'b',和上一个一样的都是有问题的。

(5)结果是:6;解释:&arr是字符串的地址,也是从第一个元素向后计算。

(6)结果是:随机值;解释:&arr+1是指向跳过整个字符串的地址,大小为随机值。

(7)结果是:5;解释:&arr[0]+1指向第二个元素,计算第二个元素之后的大小。

    char *p = "abcdef";
(1)	printf("%d\n", sizeof(p));
(2)	printf("%d\n", sizeof(p+1));
(3)	printf("%d\n", sizeof(*p));
(4)	printf("%d\n", sizeof(p[0]));
(5)	printf("%d\n", sizeof(&p));
(6)	printf("%d\n", sizeof(&p+1));
(7)	printf("%d\n", sizeof(&p[0]+1));

(1)结果是:4/8;解释:p是指针变量,计算的是指针变量的大小为4/8

(2)结果是:4/8;解释:p+1是b的地址。

(3)结果是:1;解释:p的类型是const char*,*p就是char类型,p指向第一个元素大小为1个字节

(4)结果是:1;解释:p[0] == *(p+0) == *p = 'a',大小1个字节。

(5)结果是:4/8,解释:取出的是p的地址,大小为4/8个字节。

(6)结果是:4/8,解释:&p+1是跳过p指针变量后的地址,是地址大小就是4/8个字节

(7)结果是:4/8;解释:&p[0]+1指向的是第二个元素的地址。

	char *p = "abcdef";
(1)	printf("%d\n", strlen(p));
(2)	printf("%d\n", strlen(p+1));
(3)	printf("%d\n", strlen(*p));
(4)	printf("%d\n", strlen(p[0]));
(5)	printf("%d\n", strlen(&p));
(6)	printf("%d\n", strlen(&p+1));
(7)	printf("%d\n", strlen(&p[0]+1));

(1)结果是:6;解释:strlen计算\0之前的字符串大小。

(2)结果是:5;解释:p表示首元素的地址,p+1计算的是第二个元素之后的字符串大小。

(3)结果是:代码运行错误;解释:p是首元素地址,*p是首元素,就是'a','a'的ASCII码值是97,就相当于把97作为地址传给了strlen,strlen得到的是野指针,代码有问题。

(4)结果是:代码有问题;解释:p[0]指向的是第一个元素'a',和上一个一样的都是有问题的。

(5)结果是:随机值;解释:&p是指针变量p的地址,和字符串"abcdef"关系不大。

(6)结果是:随机值;解释:&p+1是指针变量的地址+1,和字符串"abcdef"关系不大。

(7)结果是:5;解释:&p[0]+1指向第二个元素,计算第二个元素之后的大小。

4.数组和指针的笔试题解析(二维数组)

	int a[3][4] = { 0 };
(1)	printf("%d\n", sizeof(a));
(2)	printf("%d\n", sizeof(a[0][0]));
(3)	printf("%d\n", sizeof(a[0]));
(4)	printf("%d\n", sizeof(a[0]+1));
(5)	printf("%d\n", sizeof(*(a[0]+1)));
(6)	printf("%d\n", sizeof(a+1));       
(7)	printf("%d\n", sizeof(*(a+1)));
(8)	printf("%d\n", sizeof(&a[0]+1));
(9)	printf("%d\n", sizeof(*(&a[0]+1)));
(10)printf("%d\n", sizeof(*a));
(11)printf("%d\n",sizeof(a[3]));

(1结果是:48;解释:a是数组名,单独放在sizeof内部,计算的是数组的大小。

(2)结果是:4;解释:a[0][0]是第一行第一个元素,大小4个字节。

(3)结果是:16;解释:a[0]是第一行的数组名,数组名单独放在sizeof内部。

(4)结果是:4/8;解释:a[0]第一行的数组名,但是a[0]并没有单独放在sizeof内部,所以这时的数组名a[0]就是数组首元素的地址a[0][0],+1后是a[0][1]的地址,是地址大小为4/8个字节。

(5)结果是:4;解释:*(a[0]+1)表示第一行第二个元素大小为4个字节。

(6)结果是:4/8;解释:a作为数组名并没有单独放在sizeof内部,a表示首元素的地址,是二维数组的首元素的地址,也就是第一行的地址,a+1跳过了一行指向第二行,,a+1是第二行的地址。

(7)结果是:16;解释:a+1就是第二行的地址,*(a+1)就是第二行,计算第二行的大小为16。

或者*(a+1) == a[1],a[1]是第二行的数组名,就相当于sizeof(a[1]),计算的是第二行的大小。

(8)结果是:4/8;解释:a[0]是第一行的数组名。&a[0]取出的是数组第一行的地址,&a[0]+1就是第二行的地址,地址的大小为4/8个字节。

(9)结果是:16;解释:*(&a[0]+1)就是对第二解引用,第二行的大小为16字节。

(10)结果是:16;解释:a作为数组名并没有单独放在sizeof内部,a为二位数组的首元素的地址就是第一行的地址,*a就是第一行,计算的是第一行大小。

(11)结果是:16;解释:a[3]无需真实存在仅通过类型的推断就能计算出长度,a[3]是第四行的数组名单独放在sizeof内部,计算的是第四行的大小。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值