2010-06-11 373 views
10

当我看到这个符号时,我感到非常惊讶。它是做什么的,它是什么样的C概念?什么是“int * a =(int [2]){0,2};”准确地做?

+0

在C模式下编译时无法用VC++进行编译。你试过什么编译器? – AraK 2010-06-11 14:49:00

+0

它适用于GCC,所以也许它不在C标准? – Dpp 2010-06-11 14:53:36

+0

我猜你是对的 - 这是另一个GCC扩展。不知道你从中获得什么。 – 2010-06-11 14:56:13

回答

19

这是C99标准第6.5.2.5节定义的复合字面值。

它不是C++语言的一部分,因此C++编译器不编译它并不奇怪。 (或Java或Ada编译器)

复合文字的值是由 初始值设定项列表初始化的未命名对象的值。如果复合文字出现在函数体外部,则对象 具有静态存储持续时间;否则,它具有与 封闭块关联的自动存储持续时间。

所以不,它不会破坏堆栈。编译器为该对象分配存储空间。

括号放在类型中,然后是一个初始化列表 - 它不是一个强制转换,因为在C99语法中,初始化列表没有意义;相反,它是应用于产生给定类型对象的类型的后缀运算符。您不是创建{ 0, 3 }并将其转换为数组,您正在使用值0和3初始化int[2]


至于为什么它的使用,我看不到一个很好的理由在你的单行线,虽然它可能是一个可以被重新分配在其他一些阵列点带面,所以这是一个较短的方式这样做的前两行:

int default_a[] = { 0, 2 }; 
int *a = default_a; 

if (some_test) a = get_another_array(); 

我已经找到了通过临时工会职能

// fills an array of unions with a value 
kin_array_fill (array, (kin_variant_t) { .ref = value }) 
+0

很好的解释! 联合的好例子,它是初始化并传递指向函数的一个简短方法。它看起来像匿名数组。遗憾的是它没有在C++中实现 – Dpp 2010-06-11 16:39:32

+0

我刚刚查找了C++中的匿名数组,并且似乎有点类似的东西将在C++ 0x中实现:std :: initializer_list <>,例如,对于我们的示例,您可以在函数原型中指定std :: initializer_list 作为参数,并为该函数提供一个初始化程序列表,如{0,2}。 – Dpp 2010-06-11 16:50:31

-2
  • {0, 2}为包括0和2
  • (int[2])它转换为一个数组的数组符号(不知道为什么)
  • int * a =将它分配给int指针a。
+0

没有强制转换,编译器将其视为试图将多个值分配给标量变量。 – eemz 2010-06-11 14:50:15

+5

-1这不是演员。 – Artefacto 2010-06-11 15:23:40

0

(int [2])告诉编译器,下面的表达式应该被转换为int [2]。这是必需的,因为可以将{0,2}转换为不同的类型,如long [2]。 Cast在编译时发生 - 而不是运行时。

整个表达式在内存中创建一个数组,并将a指向该数组。

1
  1. 在堆栈上为[数组]两个int s分配空间。
  2. 将两个int的[数组]分别填入值02
  3. 声明类型为int*的局部变量,并为该变量分配两个int的[数组]的地址。
6

这是C99结构有用,称为复合文字

从2005年5月委员会节6.5.2.5草案:

即由 带括号的类型名称后面 初始化 的brace-封闭列表后缀表达式是字面的化合物。它提供了一个 未命名对象,其值由初始值列表 给出。

...

实施例1的文件的范围定义

int *p = (int []){2, 4}; 

初始化p 指向一个 阵列2个整数的第一元件,所述第一具有 的价值二和第二,四。 这个复合词 的表达式必须是常量。 未命名对象的持续时间为静态存储 。

相关问题