Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

They really should be listing these answers in terms of sizeof(int) instead of assuming all 64-bit platforms have sizeof(int) == 4. Pointers are confusing in C, but so is the common assumption that sizeof(int) is always 4.


sizeof(int) is either 2 or 4 on all reasonable architectures. On all modern and reasonable architectures, it must be 4.

Short answer: if sizeof(int)=8, then you lose either the 2 byte integer, or the 4 byte integer. This would make it harder to minimize memory footprint in programs which work with large amounts of data.

The reason for this is that char, short, int, long, and long long are the only names you have for various integer sizes. Since sizeof(char) is fixed at 1 and sizeof(char) <= sizeof(short) <= sizeof(int) if you make int eight bytes, you must either drop the two-byte or four-byte integer since you only have one name left for it. Dropping one of those types will make programmers unhappy since they packing structs careful is a valid thing to do for memory minimization in large-memory programs.

Note that int32_t and friends are not valid names since they MUST be a typedef for one of char, short, int, long or long long.

Disclaimer: if C11 has fixed this, I'm ignorant of it.


C99 specified stdint.h, which includes int16_t/uint16_t. So compliant compilers are required to support it even if it doesn't map to a built-in type. So you won't lose the short.

That said, it wouldn't make it any less insane; so no one does this and in fact int is 32 bits everywhere except microcontrollers (and 8086, for the tiny handful of people writing BIOS or bootloader code).


Each of the intXX_t typedefs are optional. Each typedef is available iff the implementation has a type which is exactly XX bits.


Right, which it does: we're talking about ABI variations within a single architecture. The OS and toolchain enforcing ILP64 vs. LP64 semantics on C programs has nothing to do with the i386's ability to operate on 16 bit chunks.


The "implementation" in the meaning of the C standard includes the OS and toolchain. If the C toolchain does not provide a 16 bit type, then it need not define (u)int16_t, regardless of the CPU that it is running on.


However, as mentioned recently in an HN comment somewhere there are architectures that can only operate on 32-bit or larger chunks, so sizeof(char) == sizeof(int) (I think it may have been an older Cray). I can't find the specific comment, but here's one that mentions a platform with sizeof(char) == 16: http://news.ycombinator.com/item?id=3112704


All machines were word orientated until the IBM 360's arrived and many persisted well into the 80's (the PDP-10 is a particularly famous one for hackers). Many of them got C compilers at one point or another.

That's not really the issue though. My point was that the choice of ILP64 vs. LP64 on a single architecture could not cause you to "lose" a 16 bit quantity. It can't, because those machine instructions obviously don't go away when you change your compiler's calling conventions. So a C99-compliant compiler would still be required to provide int16_t.

Which is... maybe too much minutiae even for a C minutiae thread. But it was my point, anyway.


Yes, I see. It can be annoying when someone widens the scope of an already-narrowed discussion, as my comment tried to do. Thanks for your restatement and clarification.


sizeof(char) is always 1, because the number that it returns is not in bytes but in chars. What you mean is CHAR_BIT in limits.h.

This seems to be common state of things on almost anything, that is designed to be fast first and "C-compatible" second.


D'oh! Yes, I meant CHAR_BIT. Thanks for the correction.


What if you make the byte 16 bits? C99 doesn't require it to be exactly 8 bits--just that it be large enough to represent the basic character set.


FWIW, I've actually used a really silly chip once that had a horrible-tastic toolchain that it came with, where char and int were the same size, and both either 16 or 32 bits (I forgot whether it was 16 or 32, unfortunately). (In case anyone doesn't notice: on such a system, sizeof(int) is still 1, as it is measured in units of sizeof(char).)


Which chip? ADI's SHARC has that and it's far from "really silly"


I don't remember (this was 2002); I just remember it being a really cheap part on my friend's MicroMouse motor controller (I wrote the maze searching algorithm for them), and that the C compiler didn't actually work very well.


Then breaking a little quiz like this will be the least of your worries.

Of course, that's the kind of logic that got us into this situation today. Fortunately we should to be able to live with CHAR_BIT == 8 for the forseeable future.


I have actually programmed for an architecture where sizeof(int) is 1. Yes, a very unusual one.


You mean many 8-bit micros and also any word-addressable architectures? I don't think it's that unusual.


Which 8-bit micros? avr-gcc, PIC microchip C, HC11 gcc, SDCC (for HC11, 8051, Z80, etc.) all have 16-bit ints.

Also, the C standard "Sizes of Integer Types" section sets out minimum ranges each type must allow, and I think int has always been +/-32767. ie see the section at http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf


Isn't the assumption that sizeof(int) = platform type in bytes (e.g. 4 for 32-bit and 8 for 64-bit platforms)? I expected int on 64-bit platform to be 8 bytes in size.


Typically on 32-bit:

  sizeof(char) == 1
  sizeof(short) == 2
  sizeof(int) == 4
  sizeof(long) == 4
  sizeof(long long) == 8
  sizeof(void* ) == 4
Typically on 64-bit:

  sizeof(char) == 1
  sizeof(short) == 2
  sizeof(int) == 4
  sizeof(long) == 8
  sizeof(long long) == 8
  sizeof(void* ) == 8


You'll see this typically listed as a LP64 model. The other common option is ILP64, where int == long == long long == void * == 8.

It should also be noted that this has nothing to do with the underlying hardware. Instead it's a decision made by the OS ABI. There's nothing that says you can't have sizeof(int) == 8 on a 32-bit system.


Just to add: Windows x64 is LLP, int = 4, long = 4, long long = 8, void* = 8


While it has nothing to do with hardware per se, ILP64 is often seen on platforms, where some significant 32 bit operations (often memory accesses, but surprisingly sometimes even ALU ops) are (or used to be) slower than 64 bit.


Absolutely not, on Windows 64 for example sizeof(void *) == 8 and sizeof(int) == 4.


It depends on your platform AND on your compiler, so just saying "Windows 64" isn't enough information. Conceivably, there are compilers for "Windows 64" such that sizeof(int) == 8.

Your point (that int isn't a qword on all 64bit architectures) still stands. But your statement is potentially incorrect.


The OS ABI basically defines what the compiler will do. While it's possible to run a compiler in ILP64 mode on Windows 64, you won't get too far if you try to pass a 64-bit integer >4^32 into a Windows system call.


... or pass any 64-bit integer. Windows API calls are mostly "stdcall" and use stack for parameter passing - pushing 8 bytes instead of 4 could be disasterous in many ways - especially considering that the callee cleans the stack in this case.


There is no stdcall/ccall distinction on 64-bit Windows, there is only one ABI convention that sadly uses a different set of registers for parameter passing than Linux. Only the first four parameters uses registers, the rest is passed on the stack.


That is true on 64-bit Linux too, but on Windows64 sizeof(long)==4. See LP64 versus LLP64.


Even on 64bit machines an int has 4 bytes. I don't think this is mandated by the standard, though. I guess that many implementations believe that this is better than having a huge size difference between 32 and 64 architectures. There is always long int if you want a 64bit integer.


That's precisely the error I made in this quizz :)


I don't disagree, but I thought it was nicer for there to be a more concrete, actual memory address for the answer.

I thought about explicitly stating "sizeof(int) is 4 on this system" in the intro blurb, but that primes you a bit more than I'd like for the answer to #2, so I thought it was a little cleaner not to.


I feel that anyone who doesn't already know "it depends on sizeof(int)" isn't going to get it anyway; I was briefly thrown off because I thought "surely if sizeof(int) matters like I think it does, I would have been told what it is?"

But I'm more annoyed that I failed the last two by not understanding C than that I failed the second by guessing sizeof(int) incorrectly.


My first instinct was that sizeof(int) was the same width as the system architecture (64 bits)... specifically because you mentioned it was a 64 bit system.

Either way, after I realised that sizeof(int) == 4 the test was surprisingly simple. Are pointers really that hard to grasp?


Or they could use C99's int32_t in the problem's code to make the size of the integer explicit... (Or just state that sizeof(int) == 4 on this hypothetical system.)


Is there a common 64 bit architecture that is ILP64 as opposed to LP64?


No. The gotcha of course is on the other side. Win64 is P64, so a long won't (!!?@#!) hold a pointer.

Edit: also, pedantry: the assignment of types to sizes is part of the ABI, not the architecture.


http://en.wikipedia.org/wiki/64-bit#64-bit_data_models has a few examples -- but I think the answer is basically no?


In AIX on POWER you can choose between LP64, LLP64, or ILP64.


Well, sizeof(int) (and short, and long!) could also be 1, and %p could print out the pointer address as a roman numeral. All legal according to standard.

What commonly used platforms have a 64-bit ints? The only one I vaguely recall are really, really old versions of Solaris. After a while IIRC they decided that ILP64 was too much of a PITA and went with LP64.


The standard requires that "int" be able to represent from -32767 to +32767. Unless "byte" is redefined to contain a different number of bits, this means that sizeof(int) >= 2. Similarly, long has a range that requires at least 32 bits.


sizeof(char) is 1 per definition and also one byte, but not necessarily 8 bits.

Apparently some DSPs cannot address an 8-bit quantity -- they're not easy to find but I've found a comp.lang.c posting where Jack Klein mentions a 32-bit Sharp DSP with CHAR_BIT = 32 (so sizeof(char) == sizeof(int) == 1 !) and a Texas Instruments TMS32F28xx DSP with a 16 bit CHAR_BIT.

On such a system, C99 might not define int8_t but you could use int8_least8_t.

My guess is that they are more common than 64-bit ints but they might be supported by their own weird C Compiler/toolchain.


The interesting thing about such architectures is that the common stdio idiom:

  int c;

  while ((c = getchar()) != EOF) {
does not work properly on them.


Yep.

I could have used the hint about what the output of %p looks like (I missed the leading 0x). Of course nobody's keeping score, but that doesn't seem essential to the question.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: