最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

c - Accessing structure member that is identical to macro name - Stack Overflow

programmeradmin4浏览0评论

Is there a way to access a structure member which is identical to a macro name? Consider this code:

struct test {
      int foo;
};

#define foo bar

int main(int argc, char *argv[])
{
    struct test t;
    t.foo = 5;
    return 0;
}

This code will obviously fail to compile because bar is not a member of struct test. In this question it is described that putting a function name in parentheses will disable macro expansion. So I thought that maybe this is possible with structures too and I've tried the following:

t.(foo) = 5;

But it didn't work. That's why I'd like to ask the question if it's possible to access the foo member even though there is a macro that has the same name or can I only access the structure member foo by undefining the macro foo first?

Ideally, I'm looking for a portable solution but anything that works with gcc is also fine.

Is there a way to access a structure member which is identical to a macro name? Consider this code:

struct test {
      int foo;
};

#define foo bar

int main(int argc, char *argv[])
{
    struct test t;
    t.foo = 5;
    return 0;
}

This code will obviously fail to compile because bar is not a member of struct test. In this question it is described that putting a function name in parentheses will disable macro expansion. So I thought that maybe this is possible with structures too and I've tried the following:

t.(foo) = 5;

But it didn't work. That's why I'd like to ask the question if it's possible to access the foo member even though there is a macro that has the same name or can I only access the structure member foo by undefining the macro foo first?

Ideally, I'm looking for a portable solution but anything that works with gcc is also fine.

Share Improve this question asked Mar 17 at 18:41 AndreasAndreas 10.2k11 gold badges56 silver badges114 bronze badges 16
  • 4 putting a function name in parentheses will disable macro expansion - this is valid only to functional-like macros. – 3CxEZiVlQ Commented Mar 17 at 18:46
  • 3 In this particular case, where the member is the first member of the structure, then * (int *) &t is a defined way to access that member. – Eric Postpischil Commented Mar 17 at 18:56
  • 4 Technically, the requirements stated in your post can be met by inserting the line #define bar foo, then using t.foo, then following it with the line #undef bar. If this is not what you want, you should update the post with full requirements. – Eric Postpischil Commented Mar 17 at 19:05
  • 1 You could also save the offset to foo before defining the macro. const size_t fo = offsetof(struct test, foo); and then *(int*)((char*)&t + fo) = 5; – Ted Lyngmo Commented Mar 17 at 20:43
  • 4 Patient: "Doctor, doctor, it hurts when I define a macro with the same name as a structure member" — Doctor: "Then don't do it!" – Jonathan Leffler Commented Mar 17 at 23:54
 |  Show 11 more comments

2 Answers 2

Reset to default 5

anything that works with gcc

If you really want to preserve the macro, just:

struct test {
      int foo;
};

#define foo bar

int main(int argc, char *argv[])
{
    struct test t;
#pragma push_macro("foo")
#undef foo
    t.foo = 5;
#pragma pop_macro("foo")
    return 0;
}

Obviously the correct and proper solution is to have good names so there's no namespace collisions in the first place.

Failing that (because you are maintaining some old rotten code base?) then I guess these are various alternatives:

  • The obvious solution is to either #undef foo or temporarily define another macro that counters the first one, only to #undef the temporary macro.

  • You could assign to the whole struct using a whole compound literal, but that overwrites all members:

    t = (struct test){ 5, t.x };
    

    Where t.x is some other struct member you'd like to preserve.

  • The address of the struct is the same as the address of the first member, so this is safe:

    int val = 5;
    memcpy(&t, &val, sizeof(int));
    

    Similarly, *(int*)&t is a safe conversion printing the contents of foo.

    Alternatively if the member is in the middle of the struct, pre-calculate the offset using offsetof before the macro is defined.

发布评论

评论列表(0)

  1. 暂无评论