Edit: poor grammar
Edit: poor grammar
It took another couple of years until I understood what I lacked wasn't time spent reading another section on pointers but additional tooling. Using a debugger and stepping through programs was the next breakthrough.
Looking back today understanding my C (on UNIX) isn't just the language it's a whole ecosystem of tools to measure what is going on and manipulating state so that I can troubleshoot. After gdb came valgrind, strace, lsof, signal handling (kill), process control, gcov, the appropriate type of CFLAGS to use (e.g. the compiler itself) and how to stay sane using Make.
None of them have to do with pointers but they make life a lot easier. To become productive at this takes years but becoming good took me decades. C (imho) isn't just another language but a complete career path with dozens of branches into other areas.
If you stay patient with yourself and treat it as a journey instead of a milestone it can deepen your understanding of systems (nod to eBPF) in situations many others will bail out long before.
Don't give up and then not much will look scary any more.
2) Pointer arithmetic takes into account the size of the type pointed to.
3) The asterisk operator gives you access to the object.
4) The ampersand operator gives you the pointer to the object.
If you understand this, you understand pointers. (The arrow operator is syntactic sugar.)
That is, both a pointer to a single byte and a pointer to a 10GB memory chunk will be of the same size because they just hold a memory location whose value represents where that data starts. Therefore, declaring pointers to a certain type doesn't change their size at all, it just becomes handy when one needs to go back and forth in a memory area in which objects of that type are stored one after another, so that incrementing or decrementing the pointer by a number actually means that number times the size of the objects. Imagine asking for directions to someone and he replies "3rd door" or "3rd building" or "3rd block"; he gave you a pointer that is always the same size, but how much you have to walk will depend on the destination (size).
Once grasped the above, it should become a lot more easy; I had the same problems, then one day had a flash and they became totally clear (and fun).
It may be of help experimenting with a debugger, or simply printf-ing all values a pointer assumes when declared, assigned, incremented/decremented etc. Keep also track of the pointed data values, changing it instead of the pointer, or the other way around, are common mistakes.
An old small command line program like "cdecl" can help a lot to understand complex declarations, and someone has even made an interactive webpage around it (cdecl.org).
example:
cdecl> explain char ((x())[]) () declare x as function returning pointer to array of pointer to function returning char
Do you have any experience in other programming languages? How familiar are you with low-level computer architecture, at the CPU/memory level?
I guess one important part is to realize that in C, variables are basically names for memory locations, that in turn hold values. In other languages variables can be more abstract, and you have no idea how the value(s) are being associated with the variable name.
I started writing an example here, but I ran out of time and it wasn't good enough. :) Sorry.
EDIT: Now I've taken a loo at the relevant pages in the guide itself, and it seemed to explain the concepts very clearly and easily, so ... I'm not sure how to help. :)
Essentially, they don't/can't know anything about anything, at the most fundamental levels of their construction, and have to be hand-held every tiny step of the way.
A computer is essentially a highly complex arrangement of on/off switches - there's little else fundamentally in there doing anything at all other than something causing the first switch to cycle between on and off states and cascade to all the rest (this isn't entirely accurate but it's close enough to make te point).
This gives rise to situations where in order to create greater levels of complexity, lots of unintuitive, and seemingly even pointless things need to be done. For example: assigning letterbox addresses to every discrete portion of memory. Then things like "I want to read the values from this part of memory up to this part" require laboriously adding 1 to a value (a pointer) that tracks which address the computer is currently "thinking" about. It's so stupid it needs to remember where it is all the time like this, or it can't do anything.
Because C is very close to this mundane and laborious fundamental architecture, it (usefully in that case) deals with concepts like "pointers".
In languages at just a bit higher level, the language internals deal with pointers so that we as programmers don't have to.
http://pythontutor.com/c.html#mode=edit
If you click down to the bottom and choose from the examples "Pointer Levels" you'll get a good idea of the tools powers.
A regular variable is a place in RAM that contains a certain value.
A pointer is a variable whose value is the address of another variable.
X = 5
Y = location in memory of X
Now you can use Y to manipulate X
Its long and is filled with other stuff about C programming but it goes in to dept about how to think about pointers. Good Luck!
The quantities added or removed in arithmetic operations are the same as the size of the type that is being pointed to.
Edit: just remembered I wrote a rambling on this in 2014: https://ramblings.implicit.net/c/2014/04/21/pointers-are-not...
Subtracting two pointers yields ptrdiff_t which is not a pointer type in itself.
https://www.amazon.com/Programming-Language-2nd-Brian-Kernig...
Also, there's nothing magical about pointers - scripting languages use "handles", which is the same thing except they're read-only to the end-user programmer.
The real challenge with C is multi-threaded programming, so don't do that if you don't need it.
This is really an amazing feat: books on programming languages age really fast. This one - not so much. And you can really appreciate the careful thought that was put in each sentence. Peerless.
> The real challenge with C is multi-threaded programming, so don't do that if you don't need it.
Well, these days it's harder and harder to avoid it if you want to write efficient apps - we got more cores and the clocks remain more or less the same.
There was some article a few years ago that said the apps they looked at didn't actually run faster after making some routines parallel, so it depends, and you will definitely have more debugging to do.
It's a great (free as in beer) start.