2

Of course int and long are not guaranteed to be the same type, but on a platform such as Windows when compiling in 32-bit mode where they happen to be the same size, is the compiler allowed to regard them as the same type?

I'm not sure how to definitively test whether the compiler regards two types as the same, but I tried a heuristic test with int *a; long *b = a; and the Microsoft compiler accepts this without complaint whereas GCC gives a warning. Is either compiler behaving improperly or is it implementation dependent whether they name two different types or just one?

rwallace
  • 31,405
  • 40
  • 123
  • 242
  • Pointers to data tend to have the [same size regardless of their type](http://stackoverflow.com/questions/6751749/size-of-a-pointer), which is probably why you can assign one to another. I'm guessing the MS compiler just isn't giving you a warning. – Waleed Khan Feb 14 '13 at 12:11
  • To clarify, the Microsoft compiler does warn for int *a; char *b = a; – rwallace Feb 14 '13 at 12:12
  • They are technically not "the same type", but they are indeed the same size by the ABI definition. I'm also guessing that there are enough places where some code was written with the knowledge that `int` and `long` are the same size that a warning from MS compilers would just be downright annoying for the MS inhouse developers. – Mats Petersson Feb 14 '13 at 12:14
  • Definitely not (though I leave it to an answer to dig it up in the standard). Ok, in *C*, which has neither function overloading nor `typeid` I don't know how to easily check this off the top of my head, though. But I also guess your check isn't that reliable. – Christian Rau Feb 14 '13 at 12:15
  • Interesting comparing this behavior to c++ - in c++ they certainly should NOT be the same type and the assignment would be an error. For C, you can assign a void* to any pointer type.. so not sure on the rules here. long should not be the same type as int from function overloading standpoint in c++ (not an issue in C). – Pete Feb 14 '13 at 12:17
  • Your heuristic doesn't work: whether `X*` can be implicitly converted to `Y*` is a separate issue from whether `X` and `Y` are the same type. For example your heuristic risks concluding that every type is the same type as `void`, which is not true. Anyway C is not strict about type safety when converting pointers. – Steve Jessop Feb 14 '13 at 12:25
  • Are you turning on ALL warnings for GCC and MSVC? It might be a default warning for GCC (assuming you used -Wall) and not for VC (/W3 i believe is the default, but /W4 might show this problem). – Neil Feb 14 '13 at 13:00
  • Btw as far as the warnings are concerned both implementations conform. C doesn't require a diagnostic for converting any pointer-to-object type to any other pointer-to-object type. Neither does it forbid implementations from warning. – Steve Jessop Feb 14 '13 at 15:41

2 Answers2

5

The standard (N1570 draft of C2011 standard) says in 6.2.5 (4):

There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.) There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types.

and in paragraph 14 of the same section:

The type char, the signed and unsigned integer types, and the floating types are collectively called the basic types. The basic types are complete object types. Even if the implementation defines two or more basic types to have the same representation, they are nevertheless different types.

so that says that int and long (another way of designating long int) are different types. They may have the same representation, behaviour, and alignment requirements, but they are not the same type as far as the language is concerned.

Daniel Fischer
  • 181,706
  • 17
  • 308
  • 431
  • In C++, types being different implies that you can have overloads, template specializations and whatnot based on the fact that the types are different. What practical implications does different types have in C if they have the same representation, alignment requirements, and behavior? – Armen Tsirunyan Feb 14 '13 at 12:24
  • Paragraph 14 of this section is even better to state that they are distinc types, see my answer. – Christian Rau Feb 14 '13 at 12:25
  • @ChristianRau Right. I can't read (much less type) that fast, though, so I was still in the process of locating and incorporating that. – Daniel Fischer Feb 14 '13 at 12:27
  • @ArmenTsirunyan: there are things that you could do if they're the same type that, because they're different, are UB. Accessing an `int` through a `long*`, for example. I can't off-hand think of anything you can do in C thanks to them being different types, that you could not do if they were the same. But if nothing else, them being different types means that compilers can warn for *potentially* narrowing implicit conversions that happen not to be narrowing on the implementation doing the warning. So it's useful in practice even if it doesn't guarantee anything. – Steve Jessop Feb 14 '13 at 12:28
  • @ArmenTsirunyan In fact probably not many practical implications, which is the reason why you cannot test for their distinctness that easily (while in C++ it is quite easy using function overloading or just `typeid`). – Christian Rau Feb 14 '13 at 12:32
  • Oh, C11 has `_Generic` of course, but I don't think it would stand up if we claimed that the reason C99 requires them to be distinct types is to help out with a feature introduced much later :-) – Steve Jessop Feb 14 '13 at 12:34
  • @DanielFischer Ah, so it was an unfinished half-answer? ;) – Christian Rau Feb 14 '13 at 12:37
  • @ChristianRau I'd give it at least 78% for the initial posting. – Daniel Fischer Feb 14 '13 at 12:40
  • @SteveJessop Ah crap, you're right, I didn't know about `_Generic`, but a quick Google search indicates it will indeed break if you don't implements the abstract integer types exactly. Okay, thanks. – rwallace Feb 14 '13 at 12:44
  • @DanielFischer Meh, max 50%, §14 is really the important part. But nevermind, it's complete now and nobody will notice anyway, even if unfinished during-construction answers are discouraged. – Christian Rau Feb 14 '13 at 12:46
3

Ok, the C99 standard says in section 6.5.6 Types:

There are five standard signed integer types, designated as signed char, short int, int, long int, and long long int. (These and other types may be designated in several additional ways, as described in 6.7.2.) There may also be implementation-defined extended signed integer types. The standard and extended signed integer types are collectively called signed integer types.

And furthermore:

The type char, the signed and unsigned integer types, and the floating types are collectively called the basic types. Even if the implementation defines two or more basic types to have the same representation, they are nevertheless different types.

Which makes it pretty clear that they have to be distinct types, even if in C, which doesn't have templates, function overloading and typeid it may not be that practically important as in C++, where those types being the same type would definitely break much code.

EDIT: In fact because of this lesser practical relevance of type distinctness in C and the absence of the above mentioned language features, I cannot come up with a reliable way to test the absolute distinctness of two types right away.

Christian Rau
  • 45,360
  • 10
  • 108
  • 185
  • Right, so that's clear enough as far as the language definition in the abstract is concerned, thanks. Now what I'm still wondering is this: working on a compiler for a language designed to be a superset of C, _without_ the C++ features you mention, am I free to go ahead and just represent the types internally as i8, i16, i32, i64 anyway, or are there any situations where that would cause the compiler to fail to generate correct code? – rwallace Feb 14 '13 at 12:36
  • @rwallace You mean you want to be able to correctly do everyting that C can do, too, while not strictly adhering to the C standard? Hard to say, since I don't know if there might really be any practical implication of type distinctness, however small that may be. – Christian Rau Feb 14 '13 at 12:43