在C中,如果这不是';t地址常数,它是什么?

在C中,如果这不是';t地址常数,它是什么?,c,c99,C,C99,如果不是地址常量,那么下面的声明中的numbers是什么 int main() { int numbers[3] = {1,2,3}; return 0; } 反汇编程序显示1、2和3动态地放置在本地堆栈空间中,而不是将整个数组视为常量。因此,{1,2,3}没有静态存储持续时间,因此根据C99规范,numbers不是地址常量 C99,第6.6.9节:“地址常量是一个空指针,一个指向指定静态存储持续时间对象的左值的指针,或者一个指向函数指示符的指针…” 但是,在声明后添加行num

如果不是地址常量,那么下面的声明中的
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中出现以下编译错误:

错误:增量中的左值无效


所以它是常量,但不是地址常量。有人知道C99(或类似版本)中此类常量的正式名称吗?

numbers
无法更改,因为它必须始终指向数组中的第一个元素。

numbers
是函数
main
的非常量、自动数组变量

因为它是自动的、非恒定的,所以不能有静态存储

因为它是一个数组变量(而不是指针),所以不能递增

请注意,您可以这样做


就术语而言,你似乎在发明一些并不存在的东西

数字
是一个数组。它是类型为
int[3]
的自动对象。它不能用于在C中形成地址常量,因为在C中地址常量需要具有静态存储持续时间的对象

如果使用静态存储持续时间声明了
numbers
,则应用于
numbers
的数组到指针转换的结果将是地址常量<在这种情况下,code>numbers+1以及
&numbers[2]
也将是地址常量

您应该注意到,
{1,2,3}
没有静态存储持续时间。事实上,它根本没有存储持续时间。它不是一个对象,只是一块叫做聚合初始值设定项的语法糖。如果希望它成为匿名对象,则必须使用复合文字语法:
(int[]){1,2,3}
,但在上述上下文中它无论如何都不起作用

numbers++
不会编译,因为数组到指针转换的结果不是左值。不能将
++
应用于非左值。事物是否恒定是无关紧要的


你似乎得出了一个奇怪的结论,如果你不能修改它,它一定是一个常数。这是完全错误的。在C术语中,常量的属性与可修改的属性关系不大。常量是指编译时已知的值。编译时未知的值永远不会被称为常量,即使它们不可修改。这是一个例子:自动数组的地址在编译时是未知的,因此即使该地址不可修改,它仍然不是地址常量。

数组不是指针;请参阅。

的第6节。它不是地址常量的原因是因为它是堆栈上的地址,而该位置取决于调用堆栈中它上面的位置。如果某个对象的值在运行时之前未知,则该对象不可能是常量


它也不是一个变量,这就是为什么不能增加它。它只是存储位置的名称,正好是基指针上的偏移量
numbers[0]
是有效的l值,但
numbers
不是。

对,我知道它是一个常量。但是这种常量的正式名称是什么?
numbers
无法更改,因为它是数组,而不是指针。听起来似乎有道理,但C99规范中根本没有“数组变量”这个术语。这就是我们所画的确切区别吗?@Carlo:我不能以标准回答你。只是关于语义。您不能在
数字
上使用增量后运算符,因为它是数组类型的变量,并且该操作未在数组上定义;而且它的存储不能存在于数据段(或任何其他用于部署静态存储的机制)中,因为变量是非常量和自动的。@Carlo:Er。。。不,你的最终结论是完全错误的。数组是左值。数组到指针转换的结果不是左值,而是数组本身。例如,如果声明
double d
,则变量
d
是左值,但
(int)d
表达式的结果不是左值。数组也会发生同样的情况
numbers
是左值,但是
(int*)numbers
不是左值,除非在这种情况下,
(int*)
转换是隐式执行的。数组是左值,但不是可修改的左值。(6.3.2.1)且后缀增量的操作数必须是可修改的左值。(6.5.2.4)@Carlo:在表达式
&numbers
中,
numbers
用作左值。我相信这是唯一可以证明数组“左值”的情况。是的。我感兴趣的是数组到指针的转换不是左值。然而,我希望在语义上比规范给出的“数组隐式地类似于指针,但不是左值”的答案更清晰。@Carlo:这不是标准所说的。它说数组是一种“聚合类型”(与结构类型类似)——数组是“一组连续分配的非空对象,具有特定的成员对象类型”。@Carlo:array通常不“像指针”。数组仅在一组定义良好的特定上下文中“像指针”。运算符
++
恰好是这些上下文之一。自动变量通常在堆栈上分配,但这是一个im
int main() {
    int numbers[3] = {1,2,3};
    int *n = numbers+1;
    n++;
    return 0;
}