I guess uint8_t et co. appeared out of the plight of many systems programmer who needed to do things like "hand these precisely 8 bits to this peripheral". On this machine, getting only these specific 8 bits out of a char requires bit twiddling trickery (it doesn't support unaligned memory access), but if the peripheral you're talking to (e.g. a temperature sensor) calls 8 bits a byte, you're going to have to send it 8 bits, not teach it that a byte doesn't always mean 8 bits.
Prior to stdint.h (and on any platform without a C99-enable compiler, which are neither few nor unused), we used to work around this crap with a bunch of custom macros defined in hardware-specific header files. It was a mess and you needed to learn a lot more about every specific platform's compiler than you ever cared about. And it was particularly beautiful on bi-endian platforms, oh yes, those were so beautiful.
C99 came and said you know what, this is so platform-and-compiler-specific that the compiler should worry about it and that accounted for a massive relief of about 20% of my daily stress dose.
You should use it when you know that you need something to be exactly 8 bits long. Which may or may not be a byte (that's why it frickin' says int8_t and uint8_t, not byte and ubyte).
Edit: I'm going to piggyback on my comment and gently ask anyone to consider not blindly following the advice to inline the declaration of b in code like this:
void test(uint8_t input) {
uint32_t b;
if (input > 3) {
return;
}
b = input;
}
In many (most?) cases, that's good advice, but declaring it (and any other local variables) in the beginning has the major advantage of allowing me to read the first line of the functions and tell how much space is being allocated on the stack when the function is called.This is not only nice to know for performance reasons, it's also useful information for platforms that have limited stack size or -- my favourite! -- platforms that lack a MMU, so when your stack runs into useful data, your system doesn't crash, it just starts acting funny.
>The TMS320C28x byte is 16 Bits. By ANSI/ISO C definition, the sizeof operator yields the number of bytes required to store an object. ANSI/ISO further stipulates that when sizeof is applied to char, the result is 1. Since the TMS320C28x char is 16 bits (to make it separately addressable), a byte is also 16 bits.
http://processors.wiki.ti.com/index.php/Byte_Accesses_with_t...
C is the closest thing to universally portable assembler.
Conversely, JavaScript's failures are not because of the wide variety of architectures that it supports (a tiny fraction of C's), but instead on the monolithic and bad design of the language. If you read "The C Programming Language", you'll realize that in the ~240 pages of text, you know basically every feature of the language. It's small, and it's elegant, and it's portable. JavaScript is none of those.
> If you read "The C Programming Language", you'll realize that in the ~240 pages of text, you know basically every feature of the language.
Except for those little compiler specific little issues, it seems:
http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
http://blog.regehr.org/archives/213
http://blog.regehr.org/archives/226
http://blog.regehr.org/archives/232
> It's small, and it's elegant, and it's portable
Have you had the pleasure to port C code across multiple C compilers and OS in the mid-90's?
"The C Programming Language" isn't that great of a book, either. I had FAR better luck making sense of C (after having been in school for almost 4 years, and working part time on another language for almost 2 years) with the book "C, An Advanced Introduction" (1st version, not "ANSI Edition"), by Narain Gehani. For somebody transitioning from real high level languages, the array/pointer/string swamp was a real source of anti-productivity fun and games until explained by somebody other than its creators.
On a related note, I believe "The C Programming Language" is not a good book for the realities of 2016.
I read it cover to cover fairly recently; I don't think there was really anything I disagreed with, but there also wasn't anything I didn't already know and wasn't already practicing. While I've been programming C a while now, that surprised me. I've decided that the book isn't bad but is probably more "help get you from beginner to intermediate" than "help get you from intermediate to expert", much less something of use to an expert (sadly, in my position).
An alternative interpretation would have it that there is just not enough to say about C that an expert-level book is likely to say things a C expert would not already know. That would argue against your point about the complexity of C. As I say, though, this has not been my conclusion.
[1] Except that Eliza was named after the character from Pygmalion - I'd somehow never put that together!
You can hype your favorite systems language all you want, but if there is no compiler, it wont compile.
>OS and hardware vendors decided to only support C compilers.
If you want your favorite language X to work everywhere C does. Just make X-to-C compiler.
Not an ideal situation, for sure, but a real one.
Btw. There is nothing "pet" in X to C translators. You pay good money for a good Ada to C compiler.
A job I had in the early 90s, maintaining and extending such...
I remember the days when using C meant getting an account to the university (or work) UNIX system.
The fact that all modern systems use eight bit bytes is no reason to assume that a byte is eight bits. The fact is that a byte is not eight bits large.
People may wish to run code on "historical" systems, and someone may wish to create a 9-bit byte system for fun.
To write C code with an assumption that things are one way, when the standard does not define this assumption, screams of unportable code. You might as well use GCC extensions - after all, for a long time, what would it matter? Everyone used GCC, right?
You need to make a decision about which simplifying assumptions you make - C has decided not to assume there are 8 bits to the byte. I think it's arguable that in 2016 this is not the best decision, and they could get rid of some cognitive overhead by making the simplifying assumption.
C is one of the very, very few languages that you can reasonably expect to run on your weird embedded microprocessor, microcontroller, DSP, or whatever.
Bit, however, means "binary digit". That's the literal definition of the word. Historical usage of the word "byte" has varied.
I'm not an expert on DSP processing in any way, but I'd argue that if the environment is so peculiar that it doesn't have 8-bit bytes, you won't be able to use so many of the (formally optional) parts of C that you might as well call your code "weirdC" and do without char. It's not like you're going to use normal C libraries, and you are most probably relying on a specific compiler implementation and a lot of platform specific weirdnesses.
As for why this is the case, Generally DSPs are designed to do a few tasks very well (multiply-accumulate being the most obvious example, simultaneous reads from X and y memory, etc.) and are generally optimized for a specific word size. If you really need to access an octet on E.g. A 16-bit TI DSP you can, you just need to shift and mask. That's obviously not very efficient, because that's not really what it's optimized for. If that's what you really need, you picked the wrong part. You're gonna be filter-/FFT-/DCT-/whatever-ing way more 12 or 16-bit ADC samples per second, per dollar, and per milliWatt on that 16-bit DSP than you would be on your octet-addressable MSP430.
Regarding "Normal" c libraries, If they're valid C they should work just fine for the most part, With some obvious exceptions: you're not going to have a fun time with your "floats" on a processor without FP HW. That's why there's a standard, if you're not relying on undefined or implementation-defined behavior, you'll be fine(ish)
I don't think that's fair at all. It's well written and perfectly portable, under that assumption. If that assumption happens to hold for all the systems that could is meant to run on, why shouldn't you make it? Why assuming that unsigned integers overflow to 0 is fair, and assuming 8 bit bytes is not? They are both pragmatic choices. I think arguing that the C standard didn't make the best choice is at the least a reasonable position. Saying that people who disagree with you on this are writing bad code is not the right way to approach the subject, IMO.
> If they're valid C they should work just fine for the most part
I've yet to find a library that is valid C, in the strictest sense of the term - i.e., no floats or doubles, no 8-bit char, no uint8_t, etc. I'm sure there are, among libraries meant to run on DSPs. Does it make sense for them and libraries meant to run on bigger processors to adhere to the same exact standard? I'm not sure.
Because what's going to happen two years down the road when you need to get that code working on a different platform.
(In the old days, they called that thinking "all the world's a VAX", which became "all the world's linux" in the not-quite-as-old days)
And what happens when the different platform handles overflow differently? Or has non-IEEE floats? Or breaks whatever assumption the C standard already makes?
Here's the thing: C is already built on assumptions, which might or might not hold for a specific platform.
Choosing which assumptions we hold true is a pragmatic choice that must be done. C does it, and does it consciously - but it doesn't mean that it nails every choice.
The fact that a char is stored on silicon in the lowest 8 bits of the smallest addressable memory space really makes no difference. char arrays act just like they do on any other platform.
There aren't a lot of libraries floating around that you'd be using on a DSP, aside from vendor-supplied ones. Generally you're using a DSP because you have specific signal processing needs and power and cost requirements, which are pretty orthogonal to the requirements of most desktop development. As such, there probably isn't a huge amount of overlap between the libraries you'd be using.
Another reason for that being that quite a bit of the time you're not running an OS. There is no transparent abstraction layer that magically maps an ADC IC connected via SPI to an arbitrary group of remappable peripheral pins to /dev/adc0. I think that's kind of the big disconnect between desktop and embedded, so much of the code is specific to the processor/DSP and the arbitrary external hardware connected to it. You can't take code written for a DsPIC that uses the internal ADC and run it on an MSP430 with an internal ADC for the same reason. There isn't necessarily a POSIX layer, so it's a very different beast than writing code that works on UNIX, Linux, and OSX. Look at the Linux source and see how many architecture-specific files there are in each architecture's folder. That's what you need to get a consistant interface across different processors. Without all that non-portable abstraction code running below yours, posix- and standard-compliant code still wouldn't be portable.
As far as using the same standard, I think it's a good thing that there is agreement on what the effect of a given construct is. I think the issue comes when you expect that code written for one platform to just work(TM) on another.
>Why assuming that unsigned integers overflow to 0 is fair
because the standard says so
In your other posts I noticed some more misunderstanding of the C standard, so I suggest not to talk about things you are not aware about.
Sure, but the standard says hardly anything about their behaviour, making it practically impossible to write code that actually does anything with floats and doubles that will behave correctly on any standards-compliant C implementation.
I suggest you refrain from personal attacks, especially based on your own misreadings of the comment you're replying to.
No, not really. This reminds me the common "you can't write anything serious in C without undefined behaviour" bs.
However, if you DO have a real need of IEEE-compatible floats for whatever reason, then there is nothing wrong with checking __STDC_IEC_559__ and reporting an error if it is not defined. In fact, if you are using a system that doesn't have an IEEE float implementation, using another language won't save you.
>I suggest you refrain from personal attacks, especially based on your own misreadings of the comment you're replying to.
Feel free to show me what I misread. I would also suggest that you try to read the nonsensical bullshit he has been spreading in this thread.
Sure - but in that case why not do the same thing for insisting that char be 8 bits?
If it does limit you somehow and you really need char be 8 bits, then sure.
Same with bytes not being 8 bits. Nobody will ever make a system where that's not the case anymore. You'd break de facto compatibility with almost all C code for no reason. Market realities trump making systems "for fun".
The authors of that code should have written portable code if they didn't want it to break.
Outside world, there are tons of C compilers to chose from.
I bet there will be then bigger problems with porting the code than assuming byte is 8 bit long if someone is creating a 9-bit system "for fun".
Not in DSPs. Today.
On it: A 'byte' is 16 bits. A word is 16 bits (so sizeof(int) == 1) A function ptr is 24 bits (so sizeof(Fx) == 2)
CSR have sold well over a billions chips. There is a strong argument that this is the 3rd most popular architecture family after ARM and X86/64.
Things that x86 programmers do that won't work because they make assumptions the C standard doesn't specify: Cast a uint16_t* to uint8_t* to extract the upper and lower octets of the uint16 (a uint8_t array is actually in memory a uint16_t array using only the lower 8 bits) Store a function pointer in a void* (throws away upper 8 bits of the 24 bit func pointer).
Seems like you would learn the rules, even though they are a bit odd, easily enough while writing something from scratch, or maintaining an existing (somewhat) small driver program.
Agreed, though, be aware (or just beware?) that this chip is quite different, and new skills MUST be learned.
(EDIT: fixed PDP-11 -> PDP-8, thanks kabdib!)
I don't remember what the popular sizes for the PDP-10 were. A 36-bit machine, none of the choices were really great. (I know that CLU on the PDP-10 used 36 bits).
That said, uint8_t is more explicit (and less to write).
"I wasn't even told that there once were systems where this wasn't true until fairly recently."
Wait, so someone filled in a piece of your ignorance and your response is still "Bytes and octets are the same"?
The real crime here isn't lack of knowledge; it's thinking that one's own narrow experience is all-encompassing and that what's true in one part of the programming world is true everywhere.
One example:
> If you want bytes, use unsigned char. If you want octets, use uint8_t
Bytes and octets are the same today. I never came across a system where this wasn't true. I was never told about a system where this wasn't true. I wasn't even told that there once were systems where this wasn't true until fairly recently.