欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 房产 > 家装 > 指针,数组 易混题解析(一)

指针,数组 易混题解析(一)

2025/3/26 1:28:07 来源:https://blog.csdn.net/HDSTQTW/article/details/146444555  浏览:    关键词:指针,数组 易混题解析(一)

目录

一.相关知识点

1.数组名是什么?

两个例外:

2.strlen

3.sizeof

4. * (  ) 与 [  ]  的互换

二.一维数组

三.字符数组

1. 字符

(1)sizeof

(2)strlen

2.字符串

(1)sizeof

(2)strlen

3.字符指针

(1)sizeof

(2)strlen

四.二维数组


一.相关知识点

1.数组名是什么?

一维数组数组名是首元素的地址。

二维数组数组名是首元素地址,是第一行的地址(一维数组的地址)。

        

两个例外:

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

2. &数组名,这里的数组名是表示整个数组,& 数组名取出的是数组的地址

2.strlen

库函数,用来求字符串长度,统计的是\0之前出现的字符个数,一定要找到 ' \0 ' 才算结束,所以可能存在越界访问的。

头文件:#include <stdio.h>

注意:strlen 的函数参数是字符指针类型,我们要传给它开始统计字符长度位置的地址

3.sizeof

操作符,只关注变量占用内存空间的大小,单位是字节,不关心内存中存放的是什么

注意:1.sizeof 内部的表达式不计算

int main()
{int a = 0;short s = 5;printf("%d\n", sizeof(s = a + 3));//2printf("%d\n", s);//5return 0;
}

原因:

2.sizeof 根据类型判断大小,不会访问对应空间(不存在越界访问数组的情况)

变量是有类型的,数组也是有类型的。去掉名字就是类型

int main()
{int a = 0;int arr[10];printf("%d\n", sizeof(a));printf("%d\n", sizeof(int));printf("%d\n", sizeof(arr));printf("%d\n", sizeof(int [10])); //数组 arr 的类型:int [10]return 0;
}

4. * (  ) 与 [  ]  的互换

二.一维数组

int main()
{int a[] = { 1,2,3,4 };return 0;
}

易混例题: 

printf("%d\n", sizeof(a));
printf("%d\n", sizeof(a + 0));
printf("%d\n", sizeof(a + 1));

1. 这里是数组名的两个例外情况之一,计算的是整个数组的大小。答案:4 * 4 = 16

2.3. 注意:这里sizeof( ) 里面不止有数组名,不是两个例外情况之一。

a 是数组首元素的地址,a + 0 也是数组第一个元素的地址,a + 1是第二个元素的地址。是地址就是4/8字节。答案:4/8

printf("%d\n", sizeof(*a));
printf("%d\n", sizeof(a[1]));

不是两个例外,a 是数组首元素地址。

*a是数组首元素,a[1] 是第二个元素。计算的是数组首,第二个元素的大小,单位字节。答案:4

printf("%d\n", sizeof(&a));
printf("%d\n", sizeof(*&a));
printf("%d\n", sizeof(&a + 1));

1. &a是整个数组的地址,整个数组的地址也是地址,地址的大小就是4/8字节

&a 的类型:int (*)[4] 数组指针 

2. &a是数组的地址,*&a就是拿到了数组。*&a --> a,a就是数组名,sizeof(*&a)-->sizeof(a)。计算的是整个数组的大小,单位是字节-16。

3. &a是整个数组的地址。&a+1,跳过整个数组,指向数组后边的空间,是一个地址,大小是4/8字节。

&a+1 的类型还是 int (*)[4] 数组指针

是否会越界访问?

不会。&a 与 &a+1 类型相同。sizeof 根据类型判断大小,不会访问对应空间。所以大小也相同。

printf("%d\n", sizeof(&a[0]));
printf("%d\n", sizeof(&a[0] + 1));

&a[0]是首元素的地址,&a[0] + 1是第二个元素的地址,计算的是首元素地址的大小,地址的大小就是4/8字节

三.字符数组

1. 字符

int main()
{char arr[] = { 'a','b','c','d','e','f' };return 0;
}

(1)sizeof

printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));

1. arr单独放在sizeof内部,计算的是整个数组的大小,单位是字节,6

2. arr 是首元素的地址,arr + 0 还是数组首元素的地址,4/8

3. arr 是首元素的地址,*arr是数组的首元素,计算的是首元素的大小:1字节

4. arr[1]是第二个元素,大小1字节

printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));

1. 取出的数组的地址,数组的地址也是地址,是地址大小就是4/8

2. &arr+1是跳过整个,指向数组后边空间的地址,4/8

3. &arr[0] + 1是数组第二个元素的地址,是地址4/8字节

(2)strlen

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[0] + 1));

1.2. 两个传的都是首元素地址,让 strlen 从首元素位置开始统计。但没有 ' \0 '  不止何时停止,随机值。

3. &arr虽然是数组的地址,但是也是从数组起始位置开始的,计算的还是随机值

&arr 的类型:char (*)[6] 数组指针

4. &arr是数组的地址,&arr+1是跳过整个数组的地址,求字符串长度也是随机值

5. &arr[0] + 1是第二个元素的地址,是'b'的地址,求字符串长度也是随机值

printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));

*arr 和 arr[1] 分别是数组第一元素 'a'  ASCII码值是97;第二元素 'b'  ASCII码值是98

strlen('a')    等价于   strlen(97)。直接让 strlen 从内存编号97的地址开始统计。非法访问,这样写是错的!

97作为地址访问内存,抱歉,97这个地址不能直接访问。只有把这片空间分配给你,你才有权限访问它。

2.字符串

int main()
{char arr[] = "abcdef"; // 数组是7个元素// [ a b c d e f \0 ]return 0;
}

(1)sizeof

printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr + 0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));

1. 数组名单独放在sizeof内部,计算的是数组的总大小,单位是字节:7

2. arr+0是首元素的地址,大小是4/8

3. *arr是数组首元素,大小是1字节

4. arr[1]是数组的第二个元素,大小是1字节

printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr + 1));
printf("%d\n", sizeof(&arr[0] + 1));

1. &arr是数组的地址,数组的地址也是地址,是4/8字节

2. &arr + 1是跳过整个数组的地址,是4/8字节

3. &arr[0] + 1是第二个元素的地址,是4/8字节

(2)strlen

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[0] + 1));

1. arr是数组首元素的地址,strlen从首元素的地址开始统计\0之前出现的字符个数,是6

2. arr + 0是数组首元素的地址,同第一个,结果是6

3. &arr虽然是数组的地址,但是也是从数组起始位置开始的,直至 \0 。 6

4. &arr + 1是跳过数组后的地址,统计字符串的长度是随机值

5. &arr[0]+1是b的地址,从第二个字符往后统计字符串的长度,大小是5

printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));

非法访问

3.字符指针

int main()
{const char* p = "abcdef";return 0;
}

错:把字符串 abcdef 放到指针 p 里           对:把首字符的地址放到 p 里

字符串里面的内容,地址是连续的

字符串打印只要告诉我起始位置,就可以打印,直到 \0

(1)sizeof

printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p + 1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));

1. p是指针变量,大小就是4/8字节

2. p + 1是b的地址,是地址,就是4/8个字节

3. *p是'a',sizeof(*p)计算的是字符的大小,是1字节

4. p[0] --> *(p+0) --> *p  就同上一个,1字节

printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p + 1));
printf("%d\n", sizeof(&p[0] + 1));

1. 取出 p 的地址,p 是 char* 类型的指针,&p 取出 char* 的地址,是二级指针 char* *。是指针大小就是4/8

2. &p + 1是跳过p变量后的地址,4/8字节

3. p[0] 就是‘a’ , &p[0]就是a的地址,+1,就是b的地址,是地址就是4/8

    也可以这样理解:

(2)strlen

printf("%d\n", strlen(p));
printf("%d\n", strlen(p + 1));

1. p 指向 a 的地址,从 a 开始统计长度。6

2. p+1 指向 b 的地址,从 b 开始统计长度。5

printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));

*p 和 p[0] 都是 ' a '    非法访问 

printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p + 1));
printf("%d\n", strlen(&p[0] + 1));

1. &p拿到的是p这个指针变量的起始地址,从这里开始求字符串长度完全是随机值

2. &p+1是跳过p变量的地址,从这里开始求字符串长度也是随机值

3. &p[0] + 1是b的地址,从b的地址向后数字符串的长度是5

四.二维数组

int main()
{int a[3][4] = { 0 };return 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)));

1. 计算整个数组的大小 3*4 * 4 = 48

2. a[0][0] 的第一行第一个元素。4

3. a[0]是第一行的数组名,数组名单独放在sizeof内部,计算的就是数组(第一行)的大小,16个字节

4. a[0]是第一行的数组名。没有单独放在sizeof内部;没有取地址。表示的就是数组首元素的地址,是a[0][0]的地址。

    a[0]+1就是第一行第二个元素的地址,是地址就是4/8个字节

5. *(a[0] + 1)是第一行第2个元素,计算的是元素的大小。4个字节

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));

1. a是二维数组的数组名,数组名表示首元素的地址,就是第一行的地址,a+1就是第二行的地址。

   第二行的地址也是地址,是地址就是4/8

a - int (*)[4]    a+1--> int(*)[4]

2. a+1是第二行的地址,*(a+1)表示的就是第二行。16              *(a+1)--a[1]

3. &a[0]是第一行的地址,&a[0]+1是第二行的地址,地址的大小就是4/8

4. *(&a[0] + 1) 是对第二行的地址解引用,得到的就是第二行,计算的就是第二行的大小。16

5. a表示首元素的地址,就是第一行的地址,*a就是第一行,计算的就是第一行的大小。     *a -- *(a+0)--a[0]

printf("%d\n", sizeof(a[3]));

类型:int [4]    大小:16

如果数组存在第四行,a[3]就是第四行的数组名,数组名单独放在sizeof内部,计算的是第四行的大小

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com