将虚拟结构或联合传递给 C 中的函数
Pass a dummy struct or union to a function in C
这是 C 中那些奇怪的极端情况之一,C++ 可能会自然地处理它,但 C 似乎没有合适的习惯用法。
背景
我有一个联合(它可以很容易地成为一个结构),像这样:
union foo {
int a;
char b;
...
};
联合很小:它的一些类型是 "nontrivial",但它保证适合处理器寄存器。
因为它是寄存器大小的,所以我有一些函数可以传递它并 return 直接传递它,这样既安全又快速:
union foo bar(union foo x) {
...
}
现在,我有一整批函数,其原型由宏生成,如下所示:
#define DECLARE_QUX(__y__) \
static void qux(__y__ a, union foo b)
(所有类型名称和 typedef
均已更改以保护无辜者。)
这很好用,而且在目标代码中读起来很干净。我可以调用函数,传递联合,一切都按照它应该的方式进行。
问题
但是我在尝试调用生成的 qux()
函数时遇到了问题。在某些情况下,我知道传递给 qux()
的联合 完全不相关 。过去了什么并不重要;我知道被叫方会忽略它。但是我无法更改 qux()
函数的签名,所以我不得不这样做,以便能够传递无用的 "dummy" 联合版本:
static union foo dummyUnion = { 0 };
qux(realData, dummyUnion);
这行得通,但肯定很笨重。我真正希望能够做的是类似于 C++ 的 "magic zero":
qux(realData, 0);
或 C 化版本:
qux(realData, (foo)0);
但这当然行不通,因为您不能将整数转换为并集。
通读我的 K&R 副本,看起来这并没有真正被视为语言的一部分; ANSI 标准增加了直接传递结构和联合的能力(必要时在幕后使用 memcpy()
),主要是因为每个编译器都已经支持它。但看起来他们并没有设计出一种方法来在表达式中间用原位值声明此类形状。
问题
那么,tl;dr:有没有办法在 C 中的函数调用期间就地声明 "dummy union",或者我是否坚持只声明要传入的 static
实例?
一些进一步的研究发现一些编译器现在允许这种形式:
qux(realData, (foo){ 0 });
比较 K&R(第二版)和 C99 standard,它看起来像 postfix-expression 产生式(见第409, 6.5.2), 已被扩展以支持 ANSI 1989 标准中不存在的新形式:
postfix-expression ::= ( type-name ) { initializer-list }
这解决了确切的问题,并且适用于结构和联合。
就是说,我不确定哪些编译器符合该新产品(VC++ 2013 似乎接受它,我敢打赌 GCC 和 clang 也会接受)。但由于它现在由 C 标准定义,它看起来足以在实际代码中使用。
这是 C 中那些奇怪的极端情况之一,C++ 可能会自然地处理它,但 C 似乎没有合适的习惯用法。
背景
我有一个联合(它可以很容易地成为一个结构),像这样:
union foo {
int a;
char b;
...
};
联合很小:它的一些类型是 "nontrivial",但它保证适合处理器寄存器。
因为它是寄存器大小的,所以我有一些函数可以传递它并 return 直接传递它,这样既安全又快速:
union foo bar(union foo x) {
...
}
现在,我有一整批函数,其原型由宏生成,如下所示:
#define DECLARE_QUX(__y__) \
static void qux(__y__ a, union foo b)
(所有类型名称和 typedef
均已更改以保护无辜者。)
这很好用,而且在目标代码中读起来很干净。我可以调用函数,传递联合,一切都按照它应该的方式进行。
问题
但是我在尝试调用生成的 qux()
函数时遇到了问题。在某些情况下,我知道传递给 qux()
的联合 完全不相关 。过去了什么并不重要;我知道被叫方会忽略它。但是我无法更改 qux()
函数的签名,所以我不得不这样做,以便能够传递无用的 "dummy" 联合版本:
static union foo dummyUnion = { 0 };
qux(realData, dummyUnion);
这行得通,但肯定很笨重。我真正希望能够做的是类似于 C++ 的 "magic zero":
qux(realData, 0);
或 C 化版本:
qux(realData, (foo)0);
但这当然行不通,因为您不能将整数转换为并集。
通读我的 K&R 副本,看起来这并没有真正被视为语言的一部分; ANSI 标准增加了直接传递结构和联合的能力(必要时在幕后使用 memcpy()
),主要是因为每个编译器都已经支持它。但看起来他们并没有设计出一种方法来在表达式中间用原位值声明此类形状。
问题
那么,tl;dr:有没有办法在 C 中的函数调用期间就地声明 "dummy union",或者我是否坚持只声明要传入的 static
实例?
一些进一步的研究发现一些编译器现在允许这种形式:
qux(realData, (foo){ 0 });
比较 K&R(第二版)和 C99 standard,它看起来像 postfix-expression 产生式(见第409, 6.5.2), 已被扩展以支持 ANSI 1989 标准中不存在的新形式:
postfix-expression ::= ( type-name ) { initializer-list }
这解决了确切的问题,并且适用于结构和联合。
就是说,我不确定哪些编译器符合该新产品(VC++ 2013 似乎接受它,我敢打赌 GCC 和 clang 也会接受)。但由于它现在由 C 标准定义,它看起来足以在实际代码中使用。