前言
在日常敲代码的过程中我们会遇见这样一个问题
//例子1
void mian()
{
int a;
scanf("%d", &a);
}
例子1:这里我们看到,在为int a赋值的时候我们需要取a的地址对其赋值
void mian()
{
int dwCount;
int* a = &dwCount;
scanf("%d", a);
}
例子2:这里我们换成一个指针,对指针int* a赋值,则不需要加取地址符号&,原因不难理解,上一个例子对a赋值需要其地址,所以我们需要加&,而这里指针int* a本身就是一个地址,所以没必要再加&取指针变量a本身的地址。
//例子3
void mian()
{
char a[10];
scanf("%s", a);
}
例子3:这里在对字符数组a[]赋值的时候,并没有使用取地址符号,而是直接用的数组名。
综上
我们不得不得出一个疑问,数组a[]和指针int* a在赋值时都没有使用取地址符号&,那它们有什么相同点呢?区别又在哪里呢?
字符指针和字符数组的区别
首先我们先要搞清楚指针和数组的工作原理
指针
void mian()
{
int dwNum = 0;
int* a = &dwNum;
}
我们画图说明:(地址随便假设的)
我们可以看到:编译器在内存中创建了两个变量a和dwNum,dwNum的值为0,首地址为0x11,a的值为0x11(也就是dwNum的首地址),首地址为0x11。这样指针a就指向的dwNum。
那么在使用指针创建字符串时,肯定和指针的工作原理一样的,看下面这段代码:
int main()
{
char* a = "Hello World!";
printf("%p\n", a);
printf("%p\n", &a[1]);
printf("%p\n", &a[2]);
printf("%p\n", a);
printf("%p\n", a + 1);
printf("%p\n", a + 2);
return 0;
}
运行结果都一样:
到这里我们不难得出一个结论,当我们用指针创建字符串的时候,编译器会自动在内存中开辟一段连续内存存放每一个字符,并将字符串的首地址存放在指针char* a中。那么我们可以画图理解(和指针的图差不多的):
数组
同样我们看例子:
void main()
{
char a[10];
printf("%p\n", a);
printf("%p\n", a + 1);
printf("%p\n", a + 2);
printf("%p\n", a);
printf("%p\n", &a[1]);
printf("%p\n", &a[2]);
}
运行结果:
这里我们看到了和指针一样的结果,都是在内存中开辟一段连续的空间来存放数据,并将字符数组的首地址赋值给了数组名。那我们同样可以画一个图说明数组的工作原理:
总结
在功能上,字符指针和字符数组都时在内存中开辟空间存放字符串,并将首地址赋值给指针和数组名。通过下标法(a[0])或者地址法(*a)对其数据进行访问。
通过字符指针和字符数组的图我们可以发现不同在于,指针可以更改指向,所以可以直接更改其字符串。而数组的地址不能更改,其数据也不能直接赋值更改,只能用strcpy()等函数进行覆盖。
int main()
{
char* a = "Hello World!";
printf("%p\n", a);
a = "Hello C!";//a指向新开辟的内存并存放"Hello C!",从而达到修改字符串的目的
printf("%p\n", a);
return 0;
}
运行结果:
void main()
{
char a[10] = { '1','2','3' };
a = { '4','5','6' };//直接更改 报错:表达式必须是可修改的左值
}
运行结果: