6 ms·
It's been way too long since I've learned C for me to put myself in the shoes of somebody attempting to learn it for the first time but it's a bit steep for a "
by simias 9y ago
It's been way too long since I've learned C for me to put myself in the shoes of somebody attempting to learn it for the first time but it's a bit steep for a "primer", isn't it? I mean just looking at the examples it goes from introducing structs to a complex examples dealing with malloc, free, enums, pointers, NULL, arrays and for loops.
I also think the section about "the machine" is interesting but it's a bad idea in a C tutorial. When you code C you code for the C abstract machine, not your CPU. It's very important to understand that difference, especially if you want to write portable code. For instance integer overflow is most likely very well defined on your machine, but it's not in the C virtual machine. C is not a macroassembler. Furthermore I really don't think the details in this sections are relevant in the early stages of learning C.
There also are a few technical inaccuracies:
>So bytes (chars) can go from -128 to 127, shorts from -32768 to 32767, and so on. By default all of the types are signed (except pointers) UNLESS you put an “unsigned” in front of them.
That's true on most systems but "char" can be either signed or unsigned (IIRC on ARM they default to unsigned) and the C standard only gives minimum ranges, so 32bit chars and 64bit shorts are theoretically possible (and can occur on systems where the smallest addressable value is larger than 8 bit such as some DSPs). It's pure nitpick of course but why even bother mentioning that in a C intro? Introduce stdint.h instead, that's actually very useful for any C coder.
>You can have a pointer to pointers, so de-reference a pointer to pointers to get the place in memory where the actual data is then de-reference that again to get the data itself
>So keep this in mind as a general rule - your data must be aligned.
>Note that in addition to memory, CPUs will have “temporary local registers” that are directly inside the CPU.
Are we seriously talking about nested pointers, alignment and CPU registers before we've even introduced printf? If a newbie manages to get past that and continue through the examples I congratulate them.
I don't want to sound too harsh, it's definitely very commendable to try and share your knowledge with other people and writing tutorials is very time consuming and not always very rewarding. That being said I definitely wouldn't advise anybody to start learning C using that document, especially since there's already a wealth of resources for learning C, both online and off.
- abainbridge 9y ago> 32bit chars and 64bit shorts are theoretically possible Indeed. I worked at Cambridge Silicon Radio. Their Bluetooth chips often had two processors: a XAP for the BT stack and a Kalimba DSP for audio processing. They had 16-bit and 24-bit chars respectively. About 1 billion such chips have been sold, so it's not just some wacky architecture invented by a mad bloke in a shed.
- btashton 9y agoWriting code for the XAP2 processor from CSR gave me headaches. Did not help that the compiler is some old forked off version of GCC.
- abainbridge 9y agoI still occasionally see the people responsible for that. I'll pass on your regards :-)
- mrpippy 9y agoIt's been a few years but it was GCC 3.3 as I remember, always being called in C89 mode. Worst part was that there was a debugger, but it couldn't actually be used. All you get is printf()
- monocasa 9y agoThank god it's not GCC 2.95. I still have nightmares about embedded systems stuck on that compiler.
- tom_mellior 9y ago> Are we seriously talking about nested pointers, alignment and CPU registers before we've even introduced printf? No, printf is introduced in the very first hello world example. But the concept of format strings is not explained, nor are variadic functions, and no documentation for printf is linked. Also, the example #define MY_TITLE "Hello world" printf("This is: %n", MY_TITLE); is really quite broken. %n needs and int* argument and writes the number of characters written so far to it. A string constant is not only of the wrong type, even more importantly it is not writable (though not const). Of course a modern compiler with -Wall would catch this, but the tutorial never mentions any flags you might want to pass to your compiler...
- gameswithgo 9y ago>When you code C you code for the C virtual machine, not your CPU I code for my cpu, when I code C.
- simias 9y agoYou might think you do but I can assure you that your C compiler is not aware of that. Here's a quick example to demonstrate why I mean, consider the following code that increments a variable and returns it. If the incrementation overflows it returns 0 instead: int increment_or_0(int a) { int res = a + 1; if (res < a) { /* Overflow */ return 0; } return res; } If you code "for your CPU" and your CPU is, say, x86-64 then you might think that this code ought to work. You add one to a and if the result is smaller than the original value of a then an overflow occurred. With 2's complement arithmetic that makes perfect sense. Yet built with gcc 7.3.0 using -O3 the compiler generates the following assembly: lea 0x1(%rdi),%eax retq In other words you have the incrementation but the overflow check is nowhere to be found. That's a perfectly valid optimization for a C compiler to make, because your code relies on an undefined behavior. In this case if you really want to write your test that way you can use the "-fwrapv" to tell GCC to assume fully defined integer overflow but then you're coding in a nonstandard dialect of C.
- icedchai 9y agoI believe K&R refers to it as an "abstract machine", not a "virtual machine." On (most) platforms, there's nothing virtual about it.
- simias 9y agoAh yeah, when I wrote it it felt wrong, although I think in context it's not ambiguous. I'm going to correct it, thanks.
- loeg 9y agoYou are correct about every published version of the C standard. C-next plans to standardized on 2's complement for signed integers, for what it's worth.[0] (For developers: additionally, as a non-standard feature, most popular open source compilers (i.e., gcc and clang) support an option called "-fwrapv", which does not treat 2's complement overflow as Undefined Behavior. This is useful for getting a large legacy codebase working on newer compilers, if it makes assumptions about 2's complement. Until the new C standard is published it's probably best to avoid relying on 2's complement overflow in new code.) [0]: https://twitter.com/jfbastien/status/989242576598327296 https://twitter.com/jfbastien/status/989242576598327296
- vidarh 9y agoThe article makes clear it's a "practical" tutorial for the purposes of EFL on common architectures. EFL is a set of mostly low level libraries underlying Enlightenment. Things relating to things that are theoretically possible (like 64 bit shorts), is irrelevant if it doesn't occur on the platforms they plan on supporting, while a lot of basic stuff won't be relevant because it's not likely to be something you'd use as part of those libraries. I think most of the things you point would be valid for a generic C tutorial intending to teach C, but less so for a tutorial intending to teach the bits of C the author thinks is most important to be able to understand and/or contribute to EFL.
- pjmlp 9y agoEFL is famously known as not being a good example of good and safe C quality. https://what.thedailywtf.com/topic/15001/enlightened https://what.thedailywtf.com/topic/15001/enlightened
- simias 9y agoI'm not really sure I see who could benefit from something like that. If the coder already knows the basics of C and you want to bring them up to speed on the details they'll have to know to work on your library then I don't think you'll need to explain that "A function is a basic unit of execution" or that "Memory to a machine is just a big “spreadsheet” of numbers" for instance. This is clearly meant for complete novices, but at the same time it introduces too many concepts at once to work as a tutorial to learn C from scratch. Instead focus on how your libraries are architectured, how the pieces fit together, the rationale for why things are this way etc... See for instance "linux device drivers"[1] as an example of what I'm talking about. I know C and this "primer" doesn't give me anything valuable if I actually wanted to hack on their libraries. On the other hand if the coder really doesn't know what a function or a struct is then it's probably a better idea to tell them to follow some actual C tutorial and come back when they're done because this particular text will probably overwhelm and confuse them, not actually give them the skills necessary to actually contribute decent C code anyway. [1] https://lwn.net/Kernel/LDD3/ https://lwn.net/Kernel/LDD3/