10

是否可以 typedef 一个数组?

我有一组向量函数,它们都接受一个指向浮点数的指针,浮点数是三个浮点数的数组。我可以 typedef float* vec3_t,但是它不会让我通过简单地将其设置为等于括号中的数组来创建对象。

typedef float* vec3_t;

vec3_t a = {1,1,1}; // Does not work
vec3_t b = (float[]){1,1,1}; // Works
float c[] = {1,1,1}; // Works

void f(vec3_t x);

f({1,1,1}); // Error
f((float[]){1,1,1}; // OK

有人可以解释一下为什么会这样吗?

4

3 回答 3

7

指针和数组不是一回事。尽管它们的行为方式通常相同,但存在重大差异,您刚刚发现了其中之一。

你的代码实际上做了什么

我已将 typedefed 类型替换为 real 类型,以使解释更清楚。

float c[] = {1,1,1};

您只是创建并初始化了一个数组

f({1,1,1});

上面的代码既不是左值也不是右值。该{val1,...,valn}语法只不过是一个初始化程序,不能在其他地方使用。

float* b = (float[]){1,1,1};

在这里,您已经创建并初始化了一个数组,然后将它的位置存储在一个指针中。

f((float[]){1,1,1};

这种情况与上述情况相同,但不是存储指针,而是将其作为参数传递给函数。

float* a = {1,1,1};

您正在尝试将三个变量写入尚未分配的内存位置。一般来说,{valn,...,valn}, 是一个初始化器。此时你没有任何东西可以初始化。因此,此语法无效。您正试图将气体倒入尚未制造的罐中。

虽然我了解您想要实现的目标,但您似乎误解了内存和指针的整个概念。想象一下这段代码,它(在一些肮脏的逻辑中)相当于你正在尝试做的事情:

float* a = NULL;
a[0] = 1;
a[1] = 1;
a[2] = 1;

如果你执行这段代码会发生什么?

所以现在你知道为什么编译器禁止它了。

于 2013-06-10T13:31:59.520 回答
2

您必须将许多不同的功能堆积到您的代码中,因此“为什么这样工作”并不完全清楚您的意思。“这”具体是什么?

无论如何,为了“typedef an array”,你必须 typedef 一个数组,而不是指针

typedef float vec3_t[3];

之后你就可以做

vec3_t a = { 1, 1, 1 };

您的其余代码与类型定义数组无关。您只是发现了复合文字语法,它(non-scalar-type) { initializers }创建了一个给定类型的无名临时对象。该(non-scalar-type)部分是复合文字语法的重要组成部分。你不能省略它。

所以,而不是做

vec3_t a = { 1, 1, 1 };
f(a);

如果你不想拥有一个命名数组对象a,你可以简单地做

f((vec3_t) { 1, 1, 1 });

或者

f((float [3]) { 1, 1, 1 });

或者

f((float []) { 1, 1, 1 });

具有相同的效果。

于 2013-06-11T06:42:33.573 回答
1

数组不是指针。数组一个基指针。但无论如何,最适用于您要实现的数据结构将类似于:

struct{
    float x;
    float y;
    float z;
} myFloat3;

数组对于可变长度结构和东西很方便,但不是最有效的选择,因为你知道你有 3 个浮点数,你可以利用它。让编译器有效地打包你的大量结构,并从堆中分配你需要的东西。

于 2013-06-10T14:13:17.240 回答