c - 关于 C 中 1 元素数组的类型定义

标签 c arrays

有时,在 C 中,您会这样做:

typedef struct foo {
   unsigned int some_data;
} foo; /* btw, foo_t is discouraged */

要以面向对象的方式使用这种新类型,您可能需要这样的分配/释放对:

foo *foo_alloc(/* various "constructor" params */);
void foo_free(foo *bar);

或者,或者 init/clear 对(可能返回错误代码):

int foo_init(foo *bar, /* and various "constructor" params */);
int foo_clear(foo *bar);

我看到使用了以下习语,特别是在 MPFR 库中:

struct foo {
   unsigned int some_data;
};
typedef struct foo foo[1]; /* <- notice, 1-element array */
typedef struct foo *foo_ptr; /* let's create a ptr-type */

alloc/free 和 init/clear 对现在读作:

foo_ptr foo_alloc(/* various "constructor" params */);
void foo_free(foo_ptr bar);
int foo_init(foo_ptr bar, /* and various "constructor" params */);
int foo_clear(foo_ptr bar);

现在您可以像这样使用它(例如,init/clear 对):

int main()
{  
   foo bar; /* constructed but NOT initialized yet */
   foo_init(bar); /* initialize bar object, alloc stuff on heap, etc. */
   /* use bar */
   foo_clear(bar); /* clear bar object, free stuff on heap, etc. */
}

备注:init/clear 对似乎允许使用更通用的方式来初始化和清除对象。与 alloc/free 对相比,init/clear 对要求已经构造了一个“浅层”对象。 “深层”构造是使用 init 完成的。

问题:1 元素数组“type-idiom”是否存在任何不明显的缺陷?

最佳答案

这非常聪明(但见下文)。

它助长了 C 函数参数可以通过引用传递的误导性想法。

如果我在 C 程序中看到这个:

foo bar;
foo_init(bar);

我知道调用 foo_init不修改 bar 的值.我也知道代码传递了 bar 的值在函数尚未初始化时将其传递给函数,这很可能是未定义的行为。

除非我碰巧知道 foo是数组类型的 typedef。然后我突然意识到 foo_init(bar)未传递 bar , 但它的第一个元素的地址。现在每次我看到引用类型 foo 的内容时, 或 foo 类型的对象,我得想想怎么办foo在我理解代码之前被定义为单元素数组的 typedef。

它试图让 C 看起来像它不是的东西,就像这样:

#define BEGIN {
#define END }

等等。而且它不会导致代码更容易理解,因为它使用了 C 不直接支持的功能。它会导致代码更难理解(尤其是对于非常了解 C 的读者),因为您必须同时理解自定义声明使整个事情正常工作的底层 C 语义。

如果你想传递指针,就传递指针,然后显式地传递。例如,参见 FILE* 的使用在 <stdio.h> 中定义的各种标准函数中.没有人试图将指针隐藏在宏或 typedef 后面,C 程序员几十年来一直在使用该接口(interface)。

如果您想编写看起来像通过引用传递参数的代码,请定义一些类似函数的宏,并为它们提供全部大写的名称,以便知识渊博的读者知道发生了一些奇怪的事情。

上面我说这是“聪明”。让我想起了我刚开始学习C语言时做过的一件事:

#define EVER ;;

这让我写了一个无限循环:

for (EVER) {
    /* ... */
}

当时觉得挺聪明的。

我仍然认为它很聪明。我只是不再认为这是一件好事。

关于c - 关于 C 中 1 元素数组的类型定义,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18560660/

相关文章:

java - 在 Ubuntu Linux 中查找 C/C++ 源代码的最佳工具是什么?

javascript - 为什么这个 javascript 代码不起作用?

c - 为什么即使在 C 中分配给大的可变长度数组也有固定值 -1?

ios - Swift 2-如果值在当前日期之前,则删除数组中的NSDate值

c - 指向指针 : error in referencing members 的指针

c - 无论我运行什么代码,意外标记 `(' 附近的语法错误

C - 从链表中弹出最后一项

java - C Socket - 无法重新连接服务器

java - 如何比较具有不同顺序元素的 Json 数组

javascript - 查找嵌套数组的所有可能组合