简体   繁体   中英

Pass a dummy struct or union to a function in C

This is one of those odd corner cases in C where C++ would likely handle it naturally, but where C doesn't seem to have a suitable idiom.

Background

I have a union (which could just as easily be a struct), something like this:

union foo {
    int a;
    char b;
    ...
};

The union is small: Some of its types are "nontrivial", but it's guaranteed to fit within a processor register.

Because it's register-sized, I have functions that pass it around and return it directly, and that's safe and fast:

union foo bar(union foo x) {
    ...
}

Now, I have a whole batch of functions whose prototypes are generated by a macro, like this:

#define DECLARE_QUX(__y__) \
    static void qux(__y__ a, union foo b)

(All type names and typedef s have been changed to protect the innocent.)

This works fine, and in the target code it reads quite cleanly. I can call the functions, pass around the unions, and everything looks and acts the way it should.

The Problem

But I bumped into an issue trying to call the generated qux() functions. There are scenarios where I know that the union being passed to qux() is completely irrelevant . It doesn't matter what's passed; I know the callee is going to ignore it. But I can't change the qux() function's signature, so I'm forced to do this in order to be able to pass a useless "dummy" version of the union:

static union foo dummyUnion = { 0 };

qux(realData, dummyUnion);

That works, but it's sure clunky. What I'd really love to be able to do is something like the "magic zero" of C++:

qux(realData, 0);

Or a C-ified version:

qux(realData, (foo)0);

But that doesn't work, of course, because you can't cast an integer to a union.

Reading through my copy of K&R , it doesn't look like this was ever really considered as part of the language; the ANSI standard added the ability to pass structs and unions directly (using memcpy() under the hood if necessary), mostly because every compiler already supported it. But it doesn't look like they designed a way to declare such shapes with values in-situ, in the middle of an expression.

The Question

So, tl;dr: Is there a way to declare a "dummy union" in-situ during a function call in C, or am I stuck with just declaring a static instance to pass in?

A bit of further research finds that some compilers now allow this form:

qux(realData, (foo){ 0 });

Comparing K&R (second edition) to the C99 standard , it looks like the postfix-expression production (see page 409, 6.5.2), has been extended to support a new form that didn't exist in the ANSI 1989 standard:

postfix-expression ::= ( type-name ) { initializer-list }

This solves the exact problem, and works for both structs and unions.

That said, I'm not sure which compilers are compliant with that new production (VC++ 2013 seems to accept it, and I'll bet GCC and clang would too). But since it's now defined by the C standard, it looks good enough to use in real code.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM