5 ms·
C's normal integer types work the closer to the way you want. When you say you're returning an int, you're not really specifying the exact size at all. For tho
by tbirdz 10y ago
C's normal integer types work the closer to the way you want. When you say you're returning an int, you're not really specifying the exact size at all.
For those who don't know, C's char, short, int and long data types aren't really "fixed size". The standard defines their order: sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long), but the actual size of these integer types depends on the platform and compiler. If you want to use fixed size ints, you'd need to use the uint8_t, uint16_t, uint32_t types from stdint.h. Although interestingly enough C99 doesn't require the platform to provide these types, it only mandates the uint_least_n_t and uint_fast_n_t types (n=8,16,32..) which are guaranteed to be at least, but not necessarily exactly the requested width.
Now you may be thinking "sure the standard says they could be different, but they aren't really, a char is 8bit, a short is 16-bit an int is 32-bit a long is 64-bit". So here's a couple examples for you: many DSP platforms have a C compiler where char is 16-bit. Also Microsoft Visual c++ on windows on x86_64 compiles longs as 32-bit while GCC on Linux on x86_64 compiles longs as 64-bits.
>Notice how smooth the 32-bit to 64-bit transition went? (and yes, it was smooth.)
I know you said it was smooth, and maybe it was for some applications. But for many others, the 32-bit to 64-bit transition actually caused a lot of problems! Andrey Karpov has already done a great job of categorizing many of them, so I won't waste my time repeating him, but you can read his list here: http://www.viva64.com/en/a/0065/ http://www.viva64.com/en/a/0065/
- mieko 10y agoYeah, I'm arguing that the situation you describe (accurately) is better than baked-in sizes all over the source code. Use the platform-native types (whatever size they may be) unless you have a reason not to, then use <stdint.h> or an analogue. If CHAR_BIT is 13, let char be 13 bits: the platform probably chose that for a reason. When you have to pack it into a TCP header, do your strict fixed-width stuff there.
- tbirdz 10y agoI completely agree with you when it comes to function return types. For data structure fields, especially structs used many, many times like in very large arrays, I'd say it's sometimes worth using fixed size types to get better control over memory use. Using a 64-bit int for a field a 16-bit integer can handle will use up 4x as much memory. And if you've got a ten or a hundred million structs of that type, then it really adds up. For example size_t is 64-bit on my x86_64 system. But modern x86_64 systems can only use 48-bit address spaces, so a 64-bit sized object can't even be addressed! Even worse is my cpu and motherboard have a 32gb maximum of RAM (for an effective 35-bit physical addressing limitation). And size_t is supposed to be able to store the size of any object in memory, but on this platform it stores things that won't fit in memory. So most of these 64-bits are wasted on modern systems. For files you can use off_t if you're on POSIX, but the C standard doesn't say anything about requiring size_t to be able to store any filesize in a filesystem. Just using size_t is not enough to make your code work correctly on 64-bit size quantities either. For example, you make your strlen implementation return size_t, and you use size_t everywhere you do anything with a string. But can your application really handle strings that are bigger than the system RAM , or the hardware address space? Are your algorithms even efficient enough to handle the 4,294,967,295 byte maximum string size for a 32-bit system? The effort to get your program to work efficiently on >32-bit quanities is often much harder than just using size_t instead of int. So to me, when I see 64-bit size_ts being used everywhere in code that won't actually be able to handle working with >32-bit quantities, it just feels a little useless. Of course this is really more a complaint about how big size_t is on the x86_64 platform than it is a complaint about the idea of size_t in general. If only we had 48-bit size_ts (24-bit would be handy too!)
- gcr 10y agoI strongly disagree with your sentiment. If you wrote an application that's as efficient as possible without any wasted bits in the size_t type, it then only works on your machine. If I wanted to run such an application on my supercomputer with 2TB of RAM (such machines exist), I would then have to recompile for a 41-bit size_t. We use machine-neutral (but architecture-specific) size_t for these kinds of things explicitly to avoid recompiling on different machines that are instances of the same platform. Said another way, binary distributions could not exist if everything was made efficient for the underlying hardware. It would stink to have to recompile the world after upgrading RAM. I'd rather have a few bits of wasted space (which are typically lost anyway due to struct packing) than lose intra-platform comparability.
- andrioni 10y ago2TB of RAM isn't close to a supercomputer nowadays, you can even get one of those at AWS now (the appropriately named x1.32xlarge instance).
- tbirdz 10y agoA 48-bit size_t like I suggested could address up to 256TB of RAM. All modern x86_64 cpus are limited to 48-bits of address space, you're not losing any portability here. Also consider my strlen example. Say you compute strlen by iterating through the whole string until you find a 0, then you return a size_t for the number of bytes you iterated through. That operation is O(n) in the length of the string. If you were to use my strlen function on a string whose length is greater than would fit into a 32-bit integer, say a 1TB string or something, then the function would take so long to compute it that it would be useless. To be efficient, you'd probably have to redesign your program to do some special things to handle 1TB strings, maybe some special algorithms, or some kind of indexing. Returning a 64-bit integer type does not mean that the function can actually handle working with 64-bit sized quantities. So if you have a lot of datastructures where you keep string length, why store them as a 64-bit size_t when your application would be completely unable to handle strings of that size without keeling over? Of course you wouldn't really use a 48-bit size_t, because x86_64 cpus don't work well with 48-bit quantities.
- 10y ago
- corndoge 10y agoThis is basic knowledge for C programmers. I believe the parent was positing that the relative sizes you desribe are better than fixed sizes, and as a systems programmer I'm inclined to agree.
- lgieron 10y agoIs there any advantage in practice to using these loosely defined types (char, short, int, long) vs their precise counterparts?
- accatyyc 10y agoOne example is that if you don't need a specific size, using the loosely defined types may be faster. For example, if you specify int32_t, but your program compiles for a 16-bit platform, then instructions operating on this variable may need to run twice, since the registers can only fit 16 bits of data. And the other way around: If you specify int8_t, but your program runs on a 64-bit platform which only can address memory in 64 bit chunks, then you might waste 32-bits of memory for this variable, and addressing it can be slower since the program has to find the 8 interesting bits in a 64-bit register, and discard the rest of the bits so they don't affect calculations. The only reason to use specific sizes IMO is if you work with loads of data and need to pack it efficiently, or work with bit-specified protocols like TCP packets or files. If you need _at least_ 16 bit of data for example, then you can use the int_least_16_t, which may be 64-bit or 16-bit depending on the architecture.