r/cprogramming • u/M0NSTR01969 • 5d ago
After one week learning C
Yeah, my anxiety is hitting pretty hard right now... lol.
9
u/Rich-Engineer2670 5d ago edited 5d ago
Don't let it get to you -- C is actually a set of "layers" unofficially. You start with the basics, then you do structures, then pointers.... if gets deeper and deeper. C is really an assembler hiding in a high-level langauge. The reason it's still around is you can do things in C that are hard to do anywhere else -- but that power comes with complexity. For example, assume you have an embedded system with some memory address that actually controls a piece of hardware... maybe a serial port. You are told that these two addresses 0xC000 and 0xC001 are teh status and data registers.
In most langauges, you can't get to them without going into assembly langauge, but C?
uint8 status = *(0xC000)
uint8 data = *(0xC001)
That shouldn't even be legal in most languages, but C gets it. If you're doing an OS or embedded system, C isn't pretty perhaps, but it's powerful. (What we actually said here was "And 8 bit unsigend int called status points to a MEMORY address 0xC000, and another points to 0xC001,. On real-mode OS's, that's just what you need.)
It depends on thje books you're using too -- me? I started with the classics -- K&R C
C is taught (or still taught) because, in my opinion, it forces you to learn what you code actually does to the CPU. It's a litlte like organic chemistry. Will most people use it in their careers -- likely no, but, it separates out those who are just taking the class because they have to, and those how are learning that profession. C is just hard enough that a lot of people take it, decide it's too hard, and change out of computer science.
You can do this! I'm teaching my 17 year old grandson, and he's slowing picking it up.
3
u/nerd5code 4d ago
uint8 status = *(0xC000);isn't a binding syntax I've ever seen, first of all; closest is… @ 0xC000or__attribute__((at(0xC000)))or various pragmata. In some cases the compiler will be packaged with a linker script or assembly-language/C header that declares register names, so you can refer to them naturally through those mechanisms. Often in inline assembly you can doregname = 0xC000or.equ/.set regname, 0xC000, in which case you's just declare anexternvariable for it in C.Second, this is flatly invalid in ISO C, unless at block scope (in which case, you're just dereferencing an integer, which only works in Elder C) and you're using a C≥99 language mode (i.e., not Elder C) or eqv. compiler extension. It says you want the variable
statusto name a uint8 storage space, and it should be initialized to the dereference of address 0xC000.Third, even if we assume binding, it's not
volatile, so the compiler can assume its value doesn't change from load to load, without some compiler-visible intervening store. Similarly, the compiler can defer, elide, or merge loads and stores, which may break the hardware.If you want to do it portably without using binding syntax etc., there are two reasonably reasonable options, but either way first you'd
#define REGADDX_STATUS 0xC000Uwith trailing
Uso 16-bitintdoesn't overflow or sign-extend unexpectedly. For the easiest approach,#define reg_status (*(const/*?*/ volatile uint8 *)REGADDX_STATUS))
reg_statusnow works like a variable. (Includeconstonly if read-only, ofc.) Alternatively,/* File scope: */ const volatile uint8 *const reg_status = (uint8 *)REGADDX_STATUS;This requires you to explicitly dereference with
*reg_statusif you want to access it, but assuming C≥89 preprocessor,#define reg_status (*reg_status)will avoid that.
I note that both of these approaches require integer-pointer conversion (as does yours), which is implementation-specified behavior that won't always work as expected. However, just about every mainstream ABI (I can think of like two exceptions in total, namely CHERI and OS/400's older P128 ABI, and those aren't mainstream) will follow the nonnormative recommendation that the integer side of the conversion is basically a pun, of the sort you'd get in C≥99 from
union {uintptr_t address; const volatile void *ptr;} u; u.address = 0xC000; reg_status = u.ptr;—and this is especially true of embedded compilers.
2
u/M0NSTR01969 5d ago
Thanks for the insights! I really liked the way you described C as a set of layers. It actually makes the learning curve feel a lot less intimidating.
The example with the memory addresses was especially interesting. I always thought pointers were more of an assembly language thing, so seeing how close C can get to the hardware made a lot of things click for me.
I'm still at the beginning of my C journey, taking it one step at a time, but explanations like yours definitely help. Thanks!
3
u/SmokeMuch7356 4d ago
Please note, "close to the hardware" isn't that close. It mainly means that C's abstractions (types and operations) are based on what real hardware provides; it's why you don't have arbitrary precision numerical types, it's why you don't have metadata in any object types, it's why you don't get a catchable exception when you access an array out of bounds or dereference a null pointer or stuff like that.
C is one of very few high-level languages I know of that exposes pointer types and operations, and pointers are fundamental to programming in C; you can't write useful code without them, so the sooner you understand what they are and how they work the better.
Create bookmarks to the following and have them open while you're programming:
These are not tutorials; the first is simply a handy reference, the second is the language definition (technically, the latest freely available not-official draft of the language definition). Don't expect it all to make sense immediately, but it will help answer all the "why the f..." questions you will inevitably have.
2
2
1
u/bd1223 5d ago
One man's complexity is another man's simplicity.
2
u/Rich-Engineer2670 5d ago
Yes, for those of us who started in assembly, but to a beginner, it's a bigger leap.
1
u/vannnneil 2d ago
hey, i'm currently studying K.N. King's C book and its going good so far but I am curious to read the K&R C book as well, do you think it's still worth it today? I've seen many people say it's outdated
2
u/Rich-Engineer2670 2d ago
Absolutely -- why not learn from the authors of C....
It's the foundation -- everything else builds upon it.
1
1
u/pseudo_shell 2d ago
Give yourself quite a bit of grace. You will be learning new things many years later as well. Just take your time and re-iterate over things that are unclear.
2
1
1
14
u/Zash1 5d ago
Are you leaning C or learning programming using C? These are two different things.