abe*_*nky 2 c static initialization compound-literals language-lawyer
我试图声明一个静态结构数组,并且可以在全局声明它时这样做,但在函数内声明静态时则不行。
这是一些可以正常工作的示例代码:
#include <stdio.h>
enum
{
Mammals,
Amphibians,
Avians,
Fish,
Human, Elephant, Horse,
Frog, Salamander,
Eagle, Sparrow, Duck,
Salmon, Carp, Tuna
};
typedef struct
{
int category;
int* examples;
int num_examples;
} classification_t;
static classification_t classifications[] = {
{ Mammals, (int[]){Human, Elephant, Horse}, 3 },
{ Amphibians, (int[]){Frog, Salamander}, 2 },
{ Avians, (int[]){Eagle, Sparrow, Duck}, 3 },
{ Fish, (int[]){Salmon, Carp, Tuna}, 3 }
};
int main(void)
{
for(int i=0; i<4; ++i)
{
printf("Category %d has %d examples\n", classifications[i].category, classifications[i].num_examples);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
Category 0 has 3 examples
Category 1 has 2 examples
Category 2 has 3 examples
Category 3 has 3 examples
Run Code Online (Sandbox Code Playgroud)
这是可行的,因为大分类表是一个静态全局变量。
但是,当我尝试在(或任何其他函数)内移动表格时main,出现错误:
prog.c:25:17: error: initializer element is not constant { Mammals, (int[]){Human, Elephant, Horse}, 3 },
Run Code Online (Sandbox Code Playgroud)
在此代码中:
#include <stdio.h>
enum
{
Mammals,
Amphibians,
Avians,
Fish,
Human, Elephant, Horse,
Frog, Salamander,
Eagle, Sparrow, Duck,
Salmon, Carp, Tuna
};
typedef struct
{
int category;
int* examples;
int num_examples;
} classification_t;
int main(void)
{
//
// The ONLY change is to move the table from outside main to inside main.
// error: initializer element is not constant { Mammals, (int[]){Human, Elephant, Horse}, 3 },
//
static classification_t classifications[] = {
{ Mammals, (int[]){Human, Elephant, Horse}, 3 },
{ Amphibians, (int[]){Frog, Salamander}, 2 },
{ Avians, (int[]){Eagle, Sparrow, Duck}, 3 },
{ Fish, (int[]){Salmon, Carp, Tuna}, 3 }
};
for(int i=0; i<4; ++i)
{
printf("Category %d has %d examples\n", classifications[i].category, classifications[i].num_examples);
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我完全不清楚为什么数组初始化在第一个示例中起作用,但在第二个示例中不起作用。
是否有一种简单的技术可以使这个大表静态,但在函数作用域内声明?
static int* foo = (int[]) { 3, 4, 5 };
// This is Valid; apparently, the anonymous array is a constant-pointer
int main()
{
static int* foo = (int[]) { 3, 4, 5 };
// This is NOT valid; the anonymous array is likely on the stack.
static int* foo = (static int[]) { 3, 4, 5 };
// This is NOT valid; the static keyword is invalid before int[]
// But it was an attempt to make the array "static"
}
Run Code Online (Sandbox Code Playgroud)
有没有办法在函数中声明静态、匿名数组?
区别在于用作静态对象初始值设定项的复合文字的存储持续时间。
\n当您在文件范围内使用它们时,它们具有静态存储持续时间,并且可以用作常量表达式来初始化对象,
\n当您在 main (块作用域)中使用它们时,它们具有自动存储持续时间,即它们不能用作常量表达式来初始化具有静态存储持续时间的对象。
\n来自 C 标准)6.6 常量表达式)
\n\n\n2 常量表达式可以在翻译期间而不是运行时求值,因此可以在常量所在的任何地方使用。
\n7初始化程序中的常量表达式允许有更多的自由度。\n这样的常量表达式应为以下之一,或计算为以下之一:\n
\n//...
\n\xe2\x80\x94一个地址常量,或者
\n//...
\n
和
\n\n\n9地址常量是空指针、指向指定静态存储持续时间的对象的左值的指针、或指向函数指示符的指针;它应使用一元 &\no 运算符或将整型常量转换为指针类型显式创建,或通过使用数组或函数类型的表达式隐式创建。\n数组下标 [] 和 member-access 。和 -> 运算符、地址 &\n 和间接 * 一元运算符以及指针强制转换可用于创建地址常量,但不得使用这些运算符来访问对象的值。
\n
请注意用作数组初始值设定项并具有数组类型的复合文字,例如
\n(int[]){Human, Elephant, Horse}\nRun Code Online (Sandbox Code Playgroud)\n隐式转换为指向其第一个元素的指针。
\n