【C语言】数组和指针一样吗?

发布于:2025-07-30 ⋅ 阅读:(12) ⋅ 点赞:(0)

目录

为什么可以像指针一样使用数组?

为什么可以像数组一样使用指针?

数组和指针的区别总结


对于一些初学的小伙伴来说,最大的误区就是认为指针和数组是一样的。这是很严重的一个问题,数组本身是来顺序存储一系列同类型数据的,而指针是指向内存地址的,虽然两者在某些地方可以相互替代使用,但这并不代表两者相同。

为什么可以像指针一样使用数组?

举一个非常常见的例子,大家可能在定义函数的时候会写到如下:

void func(int arr[]); 

这里写入的参数是一个 int 类型的数据,但是我们在实际使用的时候可能会既可以传入一个数组,又可以传入一个指针,如下:

int main() {
    // 情况1:传递数组
    int my_array[3] = {1, 2, 3};
    func(my_array); 
    
    // 情况2:直接传递指针
    int *ptr = my_array;
    func(ptr); 
    
    return 0;
}

为什么会这样呢?难道数组和指针的类型相同,是同一个东西吗?

并不是这样的, 这是因为数组在表达式中使用的时候,编译器会有一个隐式的类型转换,将他转换成一个指针常量,这个指针常量指向的就是数组首元素的地址。要注意,转换的是一个指针常量,我们是不能去修改指针的指针指向的(如a、b都是一个数组,是不可以让 a = b 的)。

但是又两种特殊情况,数组名是不能用指针常量来代替的。当对一个数组名进行 sizeof 或 & 操作的时候,并不会转换成一个指针常量。sizeof() 返回的是一个数组的长度,而不是数组的指针的长度;& 取数组名返回的是一个指向数组的指针,而不是一个指向指针常量的指针。

下面举一个例子:

int a[10];
int b[10];
int *c;

c = &a[0];

表达式 &a[0] 是一个指向数组首元素的一个指针,但那正好是数组本身的值,所以使用 c = a 和上面那条语句执行的任务是完全一样的。

b = a 和 c = a 这两个操作都是非法的。都是去尝试修改指针常量的指向了。

为什么可以像数组一样使用指针?

下面举一个例子,定义一个指针,我们去用数组的方式对其进行访问。

int main()
{
    char *p = "abcdefgh";
    char arr[] = "abcdefgh";
    char a = p[5];
    char b = arr[5];
    printf("a = %c,b = %c",a,b);
    return 0;
}
/* 打印:a = f,b = f */

在上述两种情况下,我们都可以通过下标5拿到 'f',但是两者的途径完全不一样。 

使用指针 p[5] 去引用元素的时候,编译器实际会进行以下操作:

  1. 取得符号表中 p 的地址,提取存储于此处的指针。
  2. 把下标所表示的偏移量与指针的值相加,产生一个地址。
  3. 访问上面这个地址,取得字符。

也就是说 p[5] 本质上就是进行了 *(p+5) 这样一个操作,也就是向后便宜了5个 char 的地址,去拿到了 'f' 。

我们使用数组 arr[5] 去引用元素的时候,我们上面已经说过了,数组在表达式中会转化成一个指针常量,所以同样是进行了 *(arr + 5) 这样一个操作。

虽然二者最终结果是一样的,但是两者的最终获取偏移量的一个过程并不相同。

数组和指针的区别总结

上述只是帮助大家分清了为什么有时候数组和指针可以相互替换。下面总结一下本质上的区别:

特性 数组 指针
类型 连续内存块的别名 存储地址的变量
存储内容 直接存储数据元素 存储其他变量的地址
内存分配 编译期静态分配(栈/全局区) 运行时动态分配(可指向堆/栈/全局区)
大小(sizeof) 返回整个数组的字节大小(如char[9]→9) 返回指针本身的字节大小(4或8字节)
地址性质 常量 变量

指针和数组都可以在定义中用字符串常量进行初始化,虽然看着一样,但底层的逻辑并不相同。

char *p = "abcdefgh";

定义指针的时候,编译器并不为指针所指向的对象分配空间,他只是分配指针本身的空间,除非我们在定义的时候就赋值给指针一个字符串常量进行初始化。初始化的时候,字符串常量会被设置为只读。如果通过指针修改这个字符串,就会造成未定义的行为。在有些编译器中,字符串常量存在于只允许读取的数据段中,防止被修改。

char [] = "abcdefg";

但是使用字符串常量初始化的数组是可以通过下标去修改字符串的。


网站公告

今日签到

点亮在社区的每一天
去签到