5 ms·
IMHO the point of the author is backwards. unsigned char c = UCHAR_MAX; // e.g. 65'535 for CHAR_BIT = 16 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ This is li
by stephc_int13 4y ago
IMHO the point of the author is backwards.
unsigned char c = UCHAR_MAX; // e.g. 65'535 for CHAR_BIT = 16
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This is line that feels wrong for me.
CHAR_BIT = 16 is a corner case, I don't even understand why it is allowed by the standard.
- beached_whale 4y agoThere is apparently a bunch of dsps and small hw that has char bit at 16 or 32. Someone would have to tell them that they’re compilers are no longer conforming
- stephc_int13 4y agoThis is where the standard should have been more strict. For historical reasons the original C types bit-width were not strongly defined as most hardware of the time had "exotic" registers and addresses by today standards. But it was a long time ago. It is reasonably safe to assume that 14bits ints and 21bits pointers are deprecated. Why would DSPs would need to change the bit-width of chars? We already have shorts and ints that are better candidates for 16bits and 32bits width. I would not mind if the C standard was made both stricter and simpler, and I maintain that the author is wrong, fputc (and all other IO libs depending on it) should not be modified to take into account this kind of absurd corner cases. Doing so will introduce more bugs and complexity that would have to be maintained.
- beached_whale 4y agoBecause char is loaded here. It is the minimum addressable bit size. So they need to do it because it is faster and cheaper to address larger chunks. The issue in the article is that calls to fputc/fwrite to a binary file will truncate to 8bits still on some of those platforms. A byte type that is always 8bits would be a better approach, i think. But c++ bungled this too, it is the size of a char still. I dont think it should exist on systems that cannot address 8bits
- stephc_int13 4y agoEither the char type should not exist on hardware that can't address 8bits, or better yet, the compiler can help with like 2-3 asm instructions instead of one. Slower, maybe, but saner and conformant to a pre-existing standard.
- adrian_b 4y ago"char" is supposed to match the smallest addressable object in the memory, which is why "sizeof" returns the ratio between the size of an object and the size of "char". So if a DSP cannot address bytes separately, but it can address 16-bit words, the size of a "char" must be 16 bits. This is independent of choosing to define "short" as a 16-bit integer. It is useful to have a type corresponding to the smallest addressable part of the memory, but it should not have been named "char", which is a name that should have been reserved for ASCII or UTF-8 data, and never used for numbers or bit strings.
- stephc_int13 4y agoIf the hardware can't directly write or read 8-bit chars in memory, it is easy to solve by the compiler with some bit masks, not by creating an artificial CHAR_BIT constraint that will annoy every other implementers down the line. This is beyond ridiculous.
- dezgeg 4y agoThere is even some precedent, for example original Alpha AXP instruction set only supports 32-bit and 64-bit memory reads/writes, while still having 8-bit char. Although, I guess the bigger problem is to how to represent pointers to 8-bit values - on Alpha a pointer with value 1 would point to the octet at offset 1 in memory, where presumably on this 16-bit DSP such 1-pointer would point at the octet at offset 2.
- nuc1e0n 4y agoThe main point of contention seems to be that fputc is defined to return the value that was written to the stream. However, TI's implementation of it returns the character passed in as a parameter (eg 0x1600), but actually writes (unsigned char)(0x1600 & 0xff) to the stream.
- masklinn 4y agoThat doesn’t seem to be the case. The tests are strangely interleaved, but if you read carefully: - cread and cwritten are always the same, which is required by the standard - they differ from c Meaning fputc does return the value actually written, not the value input. And OP spends the entire essay freaking out about that. Well really that fputc would operate on octets when the implementation’s char is larger than that. You can see it in the second section, TFA complains that TI / DSPs return 2. Which, mind, is the entire point of fputc returning what it wrote.
- nuc1e0n 4y agoAh ok. Well if that's the case then that's correct, fputc does operate on octets right? The only reason it returns an int is to distingush EOF AFAIK. To be honest I found the article hard to follow.
- masklinn 4y ago> Well if that's the case then that's correct, fputc does operate on octets right? That is what I would think obvious here, as it's generally how char-based functions operate, and doing CHAR_BITS IO would be a complete mess for portable IO (and would introduce ambiguities due to endianness). Although technically what it says is: > The fputc() function shall write the byte specified by c (converted to an unsigned char) to the output stream pointed to by stream So if you have CHAR_BITS=16 and WORD_BIT=16 things get dicey. But indeed the easiest way to resolve the ambiguity is to assume that like everywhere else it only operates on the "minimum" char boundaries (an octet), and `int` is only used to allow or return `EOF`. This is what usually occurs in other char-based functions. Though in all honesty I don't know how a platform with CHAR_BITS=16 handles `char*` / `char[]`.