经过查询,标题这句话是正确滴!C语言中指针和数组的关系确实紧密,但它们并不等价。数组名是一个指向数组首元素的指针常量,而指针是一个可以改变指向的变量的地址的变量。
1.常量指针
常量指针,用大白话翻译一下就是指向常量的指针。常量我们都明白,就是指在程序运行过程中其值不会发生改变的量,那么指针指向常量就说明指针所指向的内容不能被修改,但是指针本身的值(即它所指向的内存地址)是可以改变的。说到这里,可能大家还一头雾水,别慌,我举个例子大家肯定就能明白(PS:一定要看注释!):
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main(void) {
const int a1 = 11; //const功能是声明常量,这行代码的作用是定义一个int类型的常量a1,并将11复制给它
const int* p = &a1; //定义一个常量指针p,p用刚刚的大白话就可以理解为指向常量a1的指针
*p = 12; //系统报错,因为常量指针p指向的是常量,数值为11,不能再次修改为12
const int a2 = 12; //重新定义一个常量a2
p = &a2; //系统不报错,p可以指向另一个新的常量a2
}
总结: 常量指针,其实就是定义了一个指针,不过它指向的是常量,因此指针所指向的内容不能被修改,但是指向的内存地址可以被改变。
2.指针常量(const指针)
指针常量,用大白话翻译一下就是指针是一个常量。常量刚刚已经介绍,指针是一个常量也就意味着指针指向的内存地址不能改变,但是可以改变指针所指向的值。说到这里,聪明的是可能已经发现,指针常量与常量指针的定义和用法正好相反,指针常量能改变的常量指针不能变,常量指针能改变的指针常量不能变。举个例子:
#include<iostream>
#include<string>
#include<fstream>
using namespace std;
int main(void) {
int a1 = 11; //定义一个变量a1,注意,这里不能再定义为一个常量
int* const p = &a1; //定义一个指针常量p,刚刚的大白话就可以理解为指针p是一个常量,一旦赋予初始值,指向的内存地址将不能再改变
*p = 12; //系统不会报错,因为指针常量可以改变指针所指向的值
int a2 = 12; //重新定义一个变量a2
p = &a2; //报错,指针常量p指向的内存地址不能改变,必须为&a1
}
总结: 指针常量,其实就是定义了一个指针,该指针是一个常量,因此指针指向的内存地址不能改变,但是指向的内容可以被修改。
数组名作为指针常量的特点如下:
- 不可修改:数组名是一个指针常量,它的值在程序执行期间不能被改变。这意味着你不能给数组名赋一个新的地址。
- 指向首元素:数组名表示的是数组首元素的地址。例如,
arr
和&arr[0]
通常表示相同的地址。 - sizeof操作:对数组名使用
sizeof
运算符得到的是整个数组的大小,而不是指针的大小。
指针作为变量的特点如下:
- 可修改:指针是一个变量,它可以被赋予不同的地址值,从而指向不同的内存位置。
- 指针运算:指针可以进行加减运算,以移动到不同的内存位置。例如,
ptr++
将指针向前移动到下一个数据类型的位置。 - sizeof操作:对指针使用
sizeof
运算符得到的是指针本身的大小,这通常是在32位系统上4个字节,在64位系统上8个字节。
下面是一个简单的例子,展示了数组和指针的不同:
#include <stdio.h>
int main() {
int arr[5] = {1, 2, 3, 4, 5}; // 定义一个数组
int *ptr = arr; // 定义一个指针,指向数组的第一个元素
// 输出数组名和指针的地址
printf("Array address: %p\n", arr);
printf("Pointer address: %p\n", ptr);
// 尝试修改数组名(编译错误)
// arr = ptr; // 错误,不能修改数组名
// 修改指针
ptr = &arr[2]; // 正确,可以修改指针的值
// 输出修改后的指针地址
printf("Modified pointer address: %p\n", ptr);
return 0;
}
在这个例子中,arr
是数组的名字,它是一个指针常量,指向数组的首元素。ptr
是一个变量指针,最初指向数组的首元素,但后来被修改为指向数组的第三个元素。我们不能修改 arr
的值,因为它是常量,但我们可以修改 ptr
的值,因为它是一个变量。