char *a 与 char a[]的区别

数组名与指针

首先,指针就是指针,数组就是数组。两个是不同的东西。这两个概念之所以经常被混淆,是因为编译器把数组名当作指向该数组第一个元素的指针。正是由于数组即数组的本身属性,使用&操作符取的是数组的地址,sizeof()的操作数得到的是整个数组的大小,而不是所指向第一个元素的大小。

#include <stdio.h>

int main(void)
{
    char str[]="abcd";

    printf(" (*str) = %c \n",*str);
    printf(" addr (str[0]) = %#x \n",&(str[0]));
    printf(" addr (str[1]) = %#x \n",&(str[1]));

    printf(" addr of arrary param = %#x \n",&str);
    printf(" sizeof str = %d \n\n",sizeof(str));
    return 0;
}

指针声明和数组声明

首先看一段崩溃代码,Segment Default报错。指针声明和数组声明若没弄清楚,分分钟让你掉坑里

#include <iostream>
using namespace std;

int main()
{
    char *chas = "ABCDE";
    char chas_1[] = "ABCDE";
    chas[0] = 'X';
    chas_1[0] = 'X';
    return 0;
}

上面代码崩溃的原因是:*chas = "ABCDE"存放在常量区是无法修改的(chas的指针值存放在栈中。而数组是局部变量,存放在栈中,是可以修改的。

这两种变量的内存布局的不同,导致了指针声明和数组声明有以下区别:
”读“ ”写“ 能力
char *a = “abcd”; 此时”abcd”存放在常量区。通过指针只可以访问字符串常量,而不可以改变它。
而char a[20] = “abcd”; 此时 “abcd”存放在栈。可以通过指针去访问和修改数组内容。

赋值时刻
char *a = “abcd”; 是在编译时就确定了(因为为常量)。
而char a[20] = “abcd”; 在运行时确定

存取效率
char *a = “abcd”; 存于静态存储区。在栈上的数组比指针所指向字符串快。慢
而char a[20] = “abcd”; 存于栈上。快

再看看下面代码

 //合法
 char a[]="abcde";
 char *b;
 b = a;

 //不合法
 char *a="abcde";
 char b[6];
 b = a;

char[] 可以隐式转换成 char*,所以合法。不存在隐式转换使得 char* 被转换成 char[],char[] 类型的变量不能被赋值,数组不能作左值,所以不合法。