Jens Gustedt's Blog

September 12, 2010

struct tags are not identifiers in C++

Filed under: C++, C99 — Jens Gustedt @ 14:05

It seems a common mistake to think that a declaration like struct toto { ... }; in C++ implies the definition of the identifier toto as a type. In reality the rule for this is much more subtle than that: it only implies some sort of implicit typedef struct toto toto;. When and if in the corresponding scope there is no other identifier of the same name the toto refers to the struct.

This comes e.g in effect when you try to use the tools from “sys/stat.h” in C++. It defines a function stat and a struct stat that coexist in the same scope.

This kind of implicit definition is a pitfall when you think of code sharing between C and C++. In the following we will consider four codes that are slight variations of the same idea.

/* Compiles in C and C++, output will usually differ for both*/
#include <stdio.h>
static char T = 'a';
int main(int argc, char** argv) {
    struct T { char X[2]; };
    printf("size of T is %zu\n", sizeof(T));
}

Here the implicit typedef in C++ comes to its full beauty: for C++ the sizeof operator refers to the type and not to the variable. Thus the output in C will be 1 (this is a char variable, not a character literal) and in C++ it will at least be 2.

/* Compiles in C and C++, output will be 1 for both*/
#include <stdio.h>
int main(int argc, char** argv) {
    static char T = 'a';
    struct T { char X[2]; };
    printf("size of T is %zu\n", sizeof(T));
}

In this example, the variable T in the function scope inhibits the lookup of T as a struct tag . So the sizeof operator will refer to the variable in both languages. Since sizeof(char) is always 1 in both cases, this is what will always be printed.

/* Compiles in C but not in C++ */
#include <stdio.h>
static char T = 'a';
int main(int argc, char** argv) {
    struct T { char X[2]; };
    printf("size of T is %zu\n", sizeof T);
}

Here T will be interpreted differently by C and C++ as in the first example. Since the keyword sizeof is only valid as a prefix expression before another expression and not in front of a type, this is invalid code in C++.

/* Compiles in C and C++, output will be 1 for both*/
#include <stdio.h>
int main(int argc, char** argv) {
    static char T = 'a';
    struct T { char X[2]; };
    printf("size of T is %zu\n", sizeof T);
}

This last example is equivalent to the second, only that omitting the parenthesis in the sizeof expression ensures that T is not taken as a type, here.

Things get even worse. If you define an object with the same name later in the code, the output changes:

/* Compiles in C and C++, output will usually differ for both*/
#include <stdio.h>
static char T = 'a';
int main(int argc, char** argv) {
  struct T { char X[2]; };
  printf("size of T is %zu\n", sizeof(T));
  static char T = 'a';
  printf("size of T is %zu\n", sizeof(T));
}

In C++ this prints two different values.

This answer on stackoverflow may give you further insight into this question.

About these ads

2 Comments »

  1. Very interesting. Particularly the differing behaviour of sizeof with and without the parentheses.

    Comment by Matt Joiner — September 12, 2010 @ 15:45

    • I think this is to disambiguate a construct like sizeof(int)-1. Without a special rule this could be read as sizeof((int)-1) or (sizeof(int)) - 1. Stated as this, it looks a bit unnatural to have chosen the later as the wanted interpretation. But if you look at a very common usage like malloc(sizeof(int)+4) everybody wants it to be interpreted as malloc((sizeof(int))+4) and not malloc(sizeof((int)+4)).

      Comment by Jens Gustedt — September 12, 2010 @ 22:19


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Silver is the New Black Theme. Create a free website or blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 25 other followers

%d bloggers like this: