在《c程序设计语言》一书中看到一句话一直不太明白,说外部变量和静态变量的初始化表达式必须是常量表达式,可是在之后的章节中又看到这样的代码
#define ALLOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char *allcop = allocbuf;
求教这里面的allcop指针变量的初始化表达式为什么可以用?是因为数组名其实不是一个真正的变量吗?那数组名到底算什么呢?就是一个代表数组第一个元素的地址常量吗?再将数组改为一个指针变量以后也确实编译失败了,请问数组名到底是个什么存在呢?常量?
数组名当右值使用时,是指针常量,指向数组首元素。 如:printf("%c", *allocbuf)
数组名当左值使用时(左值代表一块内存空间),代表数组所在的那块内存空间。如:sizeof(allocbuf)
还有一点值得注意,由于C语言函数传参传的是值,因此把数组名当参数传过去时,会退化成指针。
数组是数组,指针是指针,二者是两回事。数组名在某些情况下可以隐式转换(或称作退化)为指向数组首个元素的指针。
例如,定义一个数组:
int a[10];
则数组a
包含10个保存int
类型变量的内存空间。你可以把任意一个int
类型的变量赋值给a
中的任一元素
a[4] = 2; a[0] = 8;
而定义一个指针:
int *p;
则指针p
包含1个保存int
类型变量的地址的内存空间,不能直接保存int
类型变量。你可以把任意一个int
类型的变量的地址赋值给p
p = &a[4]; p = &a[0];
这两个例子很好理解,我们把数组a
中下标为4或0的元素的地址赋值给了指针p
。再看一个例子
p = a; // (1) 正确
p = &a; // (2) 错误
在语句(1)
中,当我们直接使用数组名a
来进行赋值的时候,数组名到指针的隐式转换(退化)发生了,此时数组名a
退化成了这个数组的首个元素的地址(即&a[0]
),它的类型退化成了int *
。所以语句(1)
的效果与上一个例子中的p = &a[0];
相同。
在语句(2)
中,&a
并不会发生数组名到指针的隐式转换(退化),它返回的类型实际上是int (*)[10]
,并不会自动退化成int *
,所以语句(2)
的赋值是错误的。
另一个不会发生数组名到指针的隐式转换(退化)的例子是sizeof
。
sizeof(a)
表示数组a
的大小,即10 * sizeof(int)
。sizeof(a[0])
或sizeof(*a)
表示数组a
中一个元素的大小,即sizeof(int)
。(注意在sizeof(*a)
中发生了数组名到指针的退化。)
上面的回答已经说过此处数组名隐式转换为指向数组的指针,也就是赋给变量的是数组的地址。因为数组的地址在编译阶段就可以确定了,所以可以算是常量。
其实我只想说推荐看一下《C专家编程》里面关于数组和指针的部分,以及左值和右值的定义,看了这些之后我感觉对数组和指针就理解得比较清楚了。
数组名其实可以理解成 char const *,
也就是 不能改变指向的指针,也就是 指针常量。。
全局类的指针,都要声明成const比较好
static char const * allcop = allocbuf;
C里面数组就是指针 一定要记住
也就是说 数组名 和 &数组名[0] 地址是一样的
数组名就是一个指针 指向自己第一个元素