进阶C语言——指针(二)【题目练习】
在C语言的世界里,指针和数组就像一对双胞胎,长得有点像,但本质上又不完全是同一个人。今天我们就来聊聊这对“双胞胎”之间的爱恨情仇,搞清楚它们到底是什么关系,以及在实际编程中如何避免掉进一些常见的“坑”里。
首先,数组可以理解为一个“仓库”,用来存放相同类型的元素。比如,一个整型数组就相当于一个放满整数的箱子。而指针则像一个“指示牌”,指向内存中的某个位置,告诉你“你要找的东西在这里”。虽然数组名看起来像是个“指示牌”,但它并不是指针,而是一个指向数组第一个元素的“常量指针”。不过,它有两大例外:当你在sizeof运算符或者取地址运算符(&)后面使用数组名时,它才会显露出它代表整个数组的“真面目”。
举个例子,int a[4] = {1,2,3,4};,这里的a并不是一个指针变量,而是代表着整个数组的大小。但在大多数情况下,a会被当作指向第一个元素的指针,这也是为什么你可以用指针运算来遍历数组的原因。
那么问题来了,为什么数组名有时候是整个数组,有时候只是第一个元素的地址?这是因为C语言在设计时为了兼容,让数组名在大部分情况下可以被当作指针使用,这样可以更方便地通过指针来操作数组的元素。但是,这种灵活性也带来了一些潜在的混淆。
比如,当你写sizeof(a)的时候,它返回的是整个数组所占的内存空间,而不是一个指针的大小。而当你写sizeof(a + 0)的时候,它又回到了指针的大小(通常是4或8个字节,取决于系统架构)。这种差异经常会让新手程序员感到困惑。
还有一个常见的问题,就是当我们在处理多维数组时,数组名和指针之间的关系会更加复杂。比如,一个二维数组int a[2][3],它的数组名a并不是指向整个二维数组的指针,而是指向第一个子数组的指针。所以当你试图用指针的运算来遍历整个二维数组时,需要考虑每个子数组的长度。
那么,如何避免在这些地方出错呢?记住以下几点:
1. 数组名的本质:数组名在大部分情况下会被编译器理解为指向第一个元素的指针,但这并不代表数组名就是指针变量。只有在sizeof和&运算符的情况下,数组名才代表整个数组。
2. 指针的运算规则:当你对指针进行运算时,记得考虑它指向的数据类型。例如,int指针每增加1,实际上是增加了4个字节(在32位系统中),而不是简单地增加一个内存地址。
3. 谨慎使用强制类型转换:在C语言中,可以将数组名强制转换为指针类型,但这种操作需要谨慎,尤其是在处理多维数组时,确保你清楚指针所指向的内存布局。
最后,记住在编程过程中多做实验,多写代码,多调试,逐步理解指针和数组之间的微妙关系。毕竟,实践才是掌握C语言的不二法门!
文章目录
- 1.指针和数组概念的理解
- 2.指针和数组笔试题解析
-
- 一维数组
- 字符数组
- 二维数组
1.指针和数组概念的理解
指针和数组
- 数组:能够存放一组相同类型的元素,数组的大小取决于数组的元素个数和元素类型
- 指针:也是地址或指针变量,大小是4或8个字节
- 数组是数组,指针是指针,二者不等价
- 数组名是数组首元素的地址,这个地址就可以存放在指针变量中,我们可以使用指针来遍历数组
数组名大部分情况下就是首元素地址,但是有两个例外:
sizeof(数组名) —— 数组名表示整个数组,计算的是整个数组的大小
&数组名 —— 数组名表示整个数组,取出的是数组的地址
2.指针和数组笔试题解析
一维数组
#include <stdio.h>
#include <stdio.h>
int main()
{int a[] = { 1,2,3,4 };printf("%d\\n", sizeof(a));//16//sizeof(a)就是数组名单独放在sizeof内部,计算的数组总大小,单位是字节printf("%d\\n", sizeof(a + 0));//4/8 个字节//a+0不是单独的数组名//a+0 其实是数组首元素的地址printf("%d\\n", sizeof(*a));//4//a是数组首元素的地址 - &a[0]//*a -> *&a[0] -> a[0]printf("%d\\n", sizeof(a + 1));//4/8//a是数组首元素的地址 -- int*//a+1 跳过1个整型, 是第二个元素的地址printf("%d\\n", sizeof(a[1]));//4//数组第二个元素的大小printf("%d\\n", sizeof(&a));//&a - 取出的是数组的地址,但是数组的地址也是地址呀,是地址大小就是4/8字节//int (*pa)[4] = &a;//int(*)[4]printf("%d\\n", sizeof(*&a));//16//sizeof(a)//int(*)[4]printf("%d\\n", sizeof(&a + 1));//4/8//&a --> int (*)[4]//&a+1 跳过一个数组printf("%d\\n", sizeof(&a[0]));//取出首元素的地址 4/8printf("%d\\n", sizeof(&a[0] + 1));//第二个元素的地址return 0;
}
运行结果:(x86环境下的运行结果)
a+1与&a+1的区别
字符数组
类型一
数组为arr[] = { ‘a’,‘b’,‘c’,‘d’,‘e’,‘f’ }的字符
#include <string.h>
int main()
{char arr