如果它不是地址常量,那么,在下面的声明中,numbers
究竟是什么?
int main() {
int numbers[3] = {1,2,3};
return 0;
}
反汇编程序显示1,2和3动态放置在本地堆栈空间中,而不是整个数组被视为常量。因此,{1,2,3}
没有静态存储持续时间,因此根据C99规范,numbers
不是地址常量。
C99,第6.6.9节:“地址常量是空指针,指向静态存储持续时间对象的左值的指针,或指向函数指示符的指针......”
但是,在声明之后添加行numbers++
会导致GCC 4.1.2中出现以下编译错误:
error: invalid lvalue in increment
所以它是常量,但不是地址常量。有没有人知道C99(或类似)中此类常数的正式名称?
答案 0 :(得分:10)
你似乎正在发明一些不存在的东西,术语明智。
numbers
是一个数组。它是int[3]
类型的自动对象。它不能用于在C中形成地址常量,因为在C地址常量中需要具有静态存储持续时间的对象。
如果使用静态存储持续时间声明numbers
,则应用于numbers
的数组到指针转换的结果将是地址常量。在这种情况下,numbers + 1
以及&numbers[2]
也将是常量。
您应该注意{ 1, 2, 3 }
没有静态存储持续时间。事实上,它根本没有存储时间。它不是一个对象,而只是一段名为 aggregate initializer 的语法糖。如果您希望它成为匿名对象,则必须使用复合文字语法:(int[]) { 1, 2, 3 }
,但无论如何它都不适用于上述语境。
numbers++
不会简单编译,因为数组到指针转换的结果不是左值。您无法将++
应用于非左值。事物是否恒定是无关紧要的。
你似乎得出一个奇怪的结论,如果你不能修改它,它必须是一个常数。那是完全错误的。在C术语中,常量的属性与可修改的属性几乎没有关系。术语常量指的是编译时已知的值。编译时未知的值永远不会被称为常量,即使它们不可修改。这是一个例子:自动数组的地址在编译时是未知的,所以即使该地址不可修改,它仍然不是地址常量。
答案 1 :(得分:8)
numbers
是函数main
的非常量自动数组变量。
因为它是自动且非常量的,所以不能具有静态存储。
因为它是一个数组变量(不你会注意到一个指针)它不能递增。
请注意,您可以执行
int main() {
int numbers[3] = {1,2,3};
int *n = numbers+1;
n++;
return 0;
}
答案 2 :(得分:3)
数组不是指针;请参阅comp.lang.c FAQ的第6部分。
答案 3 :(得分:0)
它不是地址常量的原因是因为它是堆栈上的地址,并且该位置取决于调用堆栈中的位置。如果直到运行时才知道它的值,那么它就不能是常数。
它也不是变量,这就是为什么你不能增加它。它只是存储位置的名称,恰好是基指针上的偏移量。 numbers[0]
是有效的l值,但numbers
不是。
答案 4 :(得分:-1)
numbers
无法更改,因为它必须始终指向数组中的第一个元素。