首先要知道的一点就是C数组的底层实现是指针。
◆对于单条字符串:
char ar1[] = "Something is pointing at me.";
char *pt1 = "Something is pointing at me.";
通过常量指针、指针常量、指向常量的指针常量,我们知道所有的数组都是“常量指针”,而"Something is pointing at me."是字符串字面量,所以ar1
能改变指向但不能通过ar1
修改字符串的值。而pt1
是指针,它指向字符串的首地址。pt1
既能改变指向又能通过它修改字符串的值。
◆对于多条字符串:
char fruit1[3][7] = {"Apple", "Pear", "Orange"};
char *fruit2[3] = {"Apple", "Pear", "Orange"};
fruit2
中的指针指向初始化时所用的字符串字面量的位置,这些字符串字面量被储存在静态内存中。而fruit1
中的数组则储存着字符串字面量的副本,所以每个字符串都被储存了两次。此外,为字符串数组分配内存的使用率较低。fruit1
中的每个元素的大小必须相同,而且必须是能储存最长字符串的大小。
我们可以把fruit1
想象成矩形二维数组,每行的长度都是最大字符串的长度,此为7字节,它的元素是连续储存在内存中的。符号“*”优先级很低,低于“[]”,所以一维数组fruit2[3]
的每个元素都是指针(对于字面量就是匿名的指向字符串字面量首元素的指针)。可以把fruit2
想象成不规则的数组,每行的长度不同。实际上,fruit2
数组的指针元素所指向的字符串不必储存在连续的内存中。
fruit1
与fruit2
表示同一个二维数组,它们的区别:一个是直接存储的字符串字面量,一个是存储的指针。所以,它们占用的内存大小是不一样的。
访问它们的方式:
两种表示方式访问同一元素
fruit1
是‘常量指针’:指向不能变,可通过指针修改数据。fruit2
也是‘常量指针’:指向不能变,但对于指针fruit2[N]
而言,它是一个常量指针,没有限制。要如同fruit1
一样的性质,通常加const
声明,像这样const *fruit2[3]
,这样fruit2[N]
就是一个‘常量指针了’,这样防止了fruit2[N]
被赋值其他地址(试想如果真被赋予值了,它的二维数据性质就变了。
网友评论