4
#include <stdio.h>
int T;
int main()
{
    struct T { double x; };  
    printf("%zu", sizeof(T));
    return 0;
}

If I run this code in C, the result is 4, while in C++ it is 8.

Can someone explain why the difference?

robinCTS
  • 5,746
  • 14
  • 30
  • 37
developer.ahm
  • 180
  • 10
  • 25
    That's because c and c++ are different languages. – haccks Nov 17 '17 at 09:40
  • 5
    Well, the language used? It's undefined in any language btw, `%d` expects an `int` and not a `size_t`. –  Nov 17 '17 at 09:40
  • 4
    In one language `T` is a type-name, in the other language it's not. – Some programmer dude Nov 17 '17 at 09:41
  • 1
    @Someprogrammerdude maybe silly, but this should be an answer .... –  Nov 17 '17 at 09:42
  • 1
    I've made an edit to remove the mismatched `printf` formatter. I don't think it invalidates any of the answers, but if you disagree, do please roll back. Nice quiz question though. – Bathsheba Nov 17 '17 at 10:01
  • 3
    Why downvotes?? I think, this is not bad question. – msc Nov 17 '17 at 10:05
  • 1
    This is an in fact very interesting question. I agree. – iBug Nov 17 '17 at 10:18
  • 1
    @rsp: It had some UB in it at first, and that together with the multiple language tags were probably grounds for causing offence. Questions like this tend to end up with a positive score though, particularly if the answers are brilliant, which the current top one certainly is. – Bathsheba Nov 17 '17 at 10:32

4 Answers4

16

Short answer: Because they aren't the same identifier, in fact.

In C, structure names and variable names fall into different namespaces, so in C,

sizeof(T) == sizeof(int) // global variable T
sizeof(struct T) == sizeof(struct T) // not the same namespace

In C++, however, structure/class names goes into the same namespace as variables. The "nearest" (most local) name is the result of name lookup, so now

sizeof(T) == sizeof(struct T) // structure T
sizeof(::T) == sizeof(int) // Note the scope resolution operator

And therefore the result is 4 and 8, respectively.

In C++, you can get 4 with sizeof(::T). The "double-colon" scope resolution operator forces the compiler to take T as the name in external namespace, so ::T is the variable of type int that you want.


In C, (structures/unions/enums) and (variables/functions/typedefs) have separate namespaces, so you can write this without worrying about names conflicting.

struct T T;

note the parentheses, that structs, unions and enums share one namespace while the other three share another.

If you try to do this in C++, you'll immediately run into problems.


I like hacck's comment. He got the point that the fundamental reason is that C and C++ are different languages, despite their similarity.

iBug
  • 35,554
  • 7
  • 89
  • 134
4

You are getting different results because C and C++ are different languages.

In C++, when you declare a struct (a special class),

struct T { 
    double x; 
};  

then you can use it as

T sobj;  // sobj is an object of type T

T is a type here. while in C, T is not a type but struct T is

struct T sobj; 

Now use sizeof(T) or sizeof(struct T) in C++ and sizeof(struct T) in C and they will give you the size of struct.

haccks
  • 104,019
  • 25
  • 176
  • 264
3

In C, the T in struct T is a struct tag. Struct tags reside in a different namespace than variables and types. To get a type in C, you would have to write struct T.

sizeof() expects either a type or an expression, and a struct tag is neither. You do you however have the variable T. A variable name is a valid expression in sizeof().

In C++ however, the T in struct T is a type name since a struct in C++ is essentially just a class with all members public. Therefore sizeof(T) matches the struct type in C++.


Notable here is that the sizeof operator has two different syntax cases:

sizeof unary-expression
sizeof ( type-name )

In case of the former, sizeof only accepts expressions, but not types. In case of the latter, it excepts either expressions or types. So had you written sizeof T instead of sizeof (T), you would have gotten a compiler error in C++, since T would then have been a type and not an expression.

Lundin
  • 195,001
  • 40
  • 254
  • 396
2

I believe in C to refer to the structure you would need to write struct T while in C++ since a struct is a public class it can be refered to as just T So both are just taking the most local definition of T they have.

FrankM
  • 772
  • 7
  • 11