
A gentle introduction to pointers using C (2019) - juanorozcov
https://www.brainstobytes.com/a-gentle-introduction-to-pointers-in-c/
======
jasode
A meta comment on tutorials to teach pointers:

If pointers are so "simple", why are they so confusing?!? Because pointers are
one of those concepts that's easier to _use_ than to _explain_.

Some concepts like _pointers_ (and also _monads_ and also English words like
_" a"_ and _" the"_) are easier to teach by _examples_ instead of by
_definitions_.

E.g. Consider the English words "a" and "the": a 5-year old can fluidly _use_
those connecting words when talking but a 50-year old adult that's been
speaking English for _decades_ will have a tough time _defining what the words
"a" and "the" _mean__ without giving a confusing and circular explanation.
Attempted explanation: the "a" is the indefinite or general signifier while
"the" is the definite or specific signifier -- what's the problem?[1]

How did small children _learn_ how "a" and "the" work without being given a
formal definition? Because of numerous _examples_.

By working through enough examples, the lightbulb moment happens ("oh gee, is
that all pointers is?!?") and the learner is able to derive his own
definition. But the irony is that the learner now has _The Curse of Knowledge_
[2] and he/she now thinks he can write a "better" tutorial to explain pointers
but new learners reading that tutorial will still say _" I don't understand
your explanation at all."_

[1] riff on : [https://stackoverflow.com/questions/3870088/a-monad-is-
just-...](https://stackoverflow.com/questions/3870088/a-monad-is-just-a-
monoid-in-the-category-of-endofunctors-whats-the-problem)

[2]
[https://en.wikipedia.org/wiki/Curse_of_knowledge](https://en.wikipedia.org/wiki/Curse_of_knowledge)

~~~
CivBase
> pointers are one of those concepts that's easier to use than to explain.

My experience is the exact opposite.

A pointer is just an address for something. There is a "reference" operator to
get a variable's address (pointer) and a "dereference" operator to get the
data at a given address. That's it.

The hard part for me has always been using them correctly - keeping track of
what points to where in my head, especially for void pointers. I haven't done
any significant development in C since my early programming years, but that's
the part I remember struggling with.

They're sort of like GOTO in that they're easy for me to understand, but they
can quickly make my code hard to follow.

~~~
nobleach
But then you need to explain to a newcomer that you can have `int __ptr;`
(pointers to pointers)... It 's pretty odd for someone coming from say,
Python, Java, or JavaScript. (which, many go through years before realizing
that pass by reference happens in their language too)

~~~
MaxBarraclough
> you need to explain to a newcomer that you can have `int ptr;` (pointers to
> pointers)...

I think HN swallowed the asterisks there. I presume you meant:

    
    
        int **ptr;
    

> It's pretty odd for someone coming from say, Python, Java, or JavaScript.
> (which, many go through years before realizing that pass by reference
> happens in their language too)

That doesn't sound right. Java always passes by value.
[https://stackoverflow.com/a/40499/](https://stackoverflow.com/a/40499/)

~~~
jagged-chisel
> For objects, the pass by value is the value of the reference to the object.

That's exactly what "pass by reference" means. According the SO definition, C
is always pass by value: the value of the 'primitive' (int, long, char) or the
value of the pointer (an address.) It pretty much applies to any language:
ultimately you're passing a _value_ from the caller to the callee. Whether
that value is 'raw' (say, an int) or a pointer or reference is all in how you
(or your compiler, or your runtime) interpret that _value_ you received.

~~~
MaxBarraclough
> That's exactly what "pass by reference" means

No, that's wrong. Pass-by-value with references as values, is not the same as
pass-by-reference.

Plenty of people make the mistake of equating the two. They can get away with
the misconception as long as they don't encounter a language like C# that
features both reference types and optional pass-by-reference.

> According the SO definition, C is always pass by value

That's correct. C is always pass-by-value. You can get a similar effect to
pass-by-reference, by passing a pointer.

> It pretty much applies to any language: ultimately you're passing a value
> from the caller to the callee.

That's incorrect. If the language has pass-by-reference semantics, then it
does not copy the value, it passes the callee a reference to the variable.
It's not true of pass-by-name, either, but don't know much about that
strategy.

A good article on this topic is the documentation on C#'s _ref_ keyword, which
enables pass-by-reference. The article does a good job explaining the related
concepts. [0]

The acid test for whether pass-by-reference is happening, rather than pass-by-
value, is whether the asserts can fail in code along the lines of this Java
code:

    
    
        int myInt = 42;
        doStuff(myInt);
        assert(42 == myInt); // Ok
        
        String myString = null;
        doMoreStuff(myString);
        assert(null == myString); // Ok
    

In Java, the asserts will never fail. The two methods called do not have
access to either the _myInt_ local or the _myString_ local, they only have
access to copies of the values held in the two locals. This is the reason Java
would permit us to use the _final_ modifier when declaring the two locals,
without needing to know anything about either of the called methods.

On the other hand, C# permits pass-by-reference. Here we'll suppose that both
_doStuff_ and _doMoreStuff_ declared their parameters using the _ref_ keyword:

    
    
        int myInt = 42;
        doStuff(ref myInt); // If callee uses 'ref' keyword, caller must use it too
        assert(42 == myInt); // May fail
        
        string myString = null;
        doMoreStuff(ref myString);
        assert(null == myString); // May fail
    

In this case, either assert may fail, depending on the behaviour of _doStuff_
and _doMoreStuff_. The callees are given references to our locals, and so they
may mutate our locals (as well as reading their values of course).

Related to this, this is illegal in C#:

    
    
        doStuff(ref 42); // Compile error. 42 is not a variable!
    

[0] [https://docs.microsoft.com/en-us/dotnet/csharp/language-
refe...](https://docs.microsoft.com/en-us/dotnet/csharp/language-
reference/keywords/ref)

~~~
jagged-chisel
> ...it passes the callee a reference to the variable.

And that reference itself is a value-- it's a thing passed to the function and
copied from somewhere in memory to a register. It's the interpretation of this
value that makes it a reference to some other tangible item. Further, it's the
implementation details behind the syntactic sugar, compiler optimizations, and
runtime support that allow the developer to reason abstractly with references.

Your Java example with String overlooks the fact that String is immutable: the
object itself can't be modified. Use any other object type, allow
doMotreStuff() to operate on the argument's properties, and you get the same
effect as if passing by reference.

My point is that the SO explanation isn't a good one precisely because you get
this pass-by-reference behavior in Java. Yes, indeed, technically there's this
_value_ that gets passed to a function, and it's the value of the reference.
And, yes, everything that "passes by reference" has to pass _something_ and
that something is the "value of the reference" so everything is technically,
at the bottom of the abstract stack, "pass by value." But that's not helpful
when attempting to help the newb understand why his object mutated in a method
when "pass by value" is what he expected.

~~~
Twisol
"call-by-reference" already has a technical meaning, and it is widely-
misunderstood because "reference" is an overloaded term.

Variables are _cells_ that contain values. A better name for "call-by-
reference" semantics is "call-by-variable", because the variable -- the value-
containing _cell_ \-- is what is semantically received by the called function.
Moreover, it doesn't matter how this is actually implemented, so long as a
caller may effectively _rebind_ a caller's variable.

In Java, variables may contain either "reference values" or "primitive
values". It is never possible, in Java, to rebind a caller's variable.
(Consider that there is never a call site that could be rendered illegal by
making a non-final argument final.) We should not call it "pass-by-reference",
not only because it's incorrect but because, to your point, it's entirely
misleading when "reference" already has a distinct meaning in Java.

Pointers are strictly more powerful in a language than pass-by-reference. If
you have pointers and pass-by-value, you can emulate pass-by-reference by
providing a pointer _value_ that points to a variable _cell_. So if you have
pointers already, you don't strictly need call-by-reference.

C# doesn't have pointers in the managed subset, because raw pointers can't be
managed. But call-by-reference can be added relatively easily, so you can
recover a small amount of what could be done if you had pointers. That's the
purpose of the `ref` keyword.

Java doesn't have pointers, either, but it also doesn't have call-by-
reference. That makes it impossible to write the canonical example of call-by-
reference, `int a = 1; int b = 2; swap(a, b)`. Instead, you must reify the
concept of a cell in the first place, e.g. by wrapping each value in a one-
element array, and pass those cells to `swap` instead.

------
rramadass
This article and most of the comments here are just over complicating a
straightforward idea. I simply don't get why people always think "pointers"
are difficult to understand; it is manipulating them to do advanced stuff that
gets tricky. But nevertheless it gets easier with time and experience since
you start picking up on the common idioms.

For anybody beginning C, my advice is to not make an "imaginary dragon" out of
"pointers" but just study examples and write your own programs using them and
soon they will seem "obvious".

~~~
globular-toast
I agree. I really can't understand what is complicated about them. I find the
same with programmers who find the DAG in git difficult to grasp. It's just
linking stuff together. It's how the the web works. It's how linked lists
work. What's difficult about it.

I think exposure to assembly demystifies all of this stuff about C. Most of C
is just making stuff really convenient that you would do anyway in assembly. A
pointer is just a memory address, but in C it also has a type. The only thing
the type is for is so the compiler knows how many bytes to add/subtract when
you increment/decrement the pointer. That's it. In assembly you'd just have to
remember how many bytes to increment/decrement yourself.

Reading Knuth also helps with this. It's one of the reasons he uses a
synthetic assembly language rather than a high-level language. There are no
pointers. There is just memory, and you need some way to find stuff in memory,
otherwise it is just noise.

~~~
dnautics
IMO I don't think the problem in C is pointers, it's that pointers _are_
arrays, in the sense that they are syntactic sugar. This is incredibly
confusing, and probably part of the reason why most modern systems languages
wisely make arrays _more_ e.g. {pointer, length}, sometimes introduce slices,
where length is runtime, and make you do some syntactic work to pull out the
pointer from the array.

~~~
coliveira
No, pointers are not arrays. Pointers can point to arrays and, because of the
language rules, you can do pretty much anything you can do to an array through
pointers, but they are definitively not arrays.

~~~
dnautics
I think we see the problem here. I've been using C on and off (granted, never
formally educated in it) for 20 years now and I don't know the difference.

~~~
coliveira
An array is a variable that is declared to contain sequential data (using
square brackets and the desired number of elements). It is immutable. A
pointer is a mutable variable that can be made to point to anything, and it
can be used to reference an array or any of its elements. These are different
concepts, although the language allows a lot of operations in common between
them.

~~~
dnautics
I see. I mean, yes I obviously know the difference between pointers and arrays
as general CS concepts (and articulated how other languages get it correct),
but we're not talking about CS, we're talking about C. Perhaps I should have
said in my original context, "array _syntax_ " is the same as "pointer
_syntax_ ". But while the CS concepts of "array" and "pointer" are indeed
different, the C syntax _elides_ the two. C does not track the immutable
length of the array for you.

~~~
globular-toast
I think what you're getting at is that arrays are not really first-class
objects in C. Rather it just gives you a bit of syntactic sugar to do the same
thing that you could do with pointers anyway. But it's up to the programmer to
complete the abstraction.

------
enriquto
> Pointers are variables that hold a reference to something in memory.

This sentence is extremely confusing or meaningless. I would rather say: "A
pointer is an integer that indicates a position in the RAM."

Thus, if a pointer "p" indicates a position in memory, then "p+1" is a pointer
that indicates the next position in the memory. The value on that cell of
memory is often written as p[1].

~~~
scoutt
> A pointer is an integer that indicates a position in

RAM, ROM, NVRAM, flash, etc.

A pointer stores a number that represents an address, without making reference
where is located. Can be 0 (NULL).

"p+1" can be the next byte in RAM, or the next 4KB if p is of type "4KB
struct".

~~~
msla
> A pointer stores a number

I disagree with this, and I think it's important to understanding pointers.

A pointer _is_ a number. A variable stores a value.[1] A variable has an
address, a value does not; a value might be stored at an address, but it
doesn't intrinsically _have_ an address. A person might live in a building,
but the building has the address, not the person, who can move.

[1] (In C-like languages this is true. In Python, a variable stores something
you're largely not allowed to inspect, which might be a pointer to a data
structure with data and metadata. Haskell has no variables, just names for
constants.)

~~~
scoutt
If I put you in front of a wall full of numbers, and I tell you "point a
number with your finger and remember it", what is your finger? A number? Or
the thing you use to point a number?

------
easterncalculus
Seeing _why_ pointers are used is especially important. Understanding that
functions in C pass by value and what that means gives context to pointers as
a useful tool instead of a longer and more complicated way to do things.
Students become a lot more frustrated if they don't see a reason behind
learning something, especially if there's any sense of elitism going on.

Additionally, a lot of these terms like that pointers now introduce (address,
reference, etc) are being introduced without any sort of context, usually
they're brand new to students. If you've never seen (and may never see)
assembly then you miss out on a lot of what's going on at the beginning and
eventually when you get it, as well. It's an abstracted view of what's going
on.

------
augustk
I learned pointers by drawing boxes and arrows which I think is the best high-
level explanation. Basically a variable is a container which holds a value
from a predetermined set of values (also known as a type). For instance, an
integer variable x holding the value 37 can be visualized as a box with the
name x:

    
    
      x
     +--+
     |37|
     +--+
    

A pointer variable p can be visualized as a box which "contains" an arrow
pointing to another variable of a certain type, for instance

    
    
      p       x
     +--+    +--+
     | -|--->|37|
     +--+    +--+
    

which correspond to the C declarations

    
    
        int x = 37;
        int *p = &x;

~~~
bear8642
And that's the way they're shown in K&R2

------
DougBTX
Coming back to C after several years, I now think one of the hard things about
pointers in C is the C syntax for pointers, not just the idea of pointers in
general. Eg, sometimes the type declaration wraps around both sides of the
variable name:

    
    
        int a[2];
        int (*ap)[2] = &a; // pointer to array of int
    

It makes it harder to see what’s what.

~~~
kahlonel
I agree that it is confusing. Here [1] is something that can help new C
programmers to understand these kind of declarations. It gets easier after a
while.

[1].
[http://c-faq.com/decl/spiral.anderson.html](http://c-faq.com/decl/spiral.anderson.html)

------
EvanAnderson
I feel like spending some time programming in assembler, even just Z80 or
6502, would give most people an understanding of pointers in very short order.

~~~
Koshkin
True, but you do not need to know assembler to have a general idea of what
computer memory looks like; but more importantly, C's notion of a pointer is
more complex as it is tied to the data type and its 'sizeof' and is further
complicated by association with arrays.

------
prosaic-hacker
Not a simple general intro to pointers A useful gentle intro to the C type
feature of pointers to arrays.

The C language has more than one way of accessing arrays. Other languages
don't.

In the classic 80s teaching language Pascal if you started with pointers it
was because you where working with linked lists.

Most people I have taught programming to conflated the pointer access in C and
the linked list concepts to their disadvantage.

I taught linked lists first and left the point abstraction intact. Later I
crossed the the layer of abstraction to explain memory access details. I have
had more success (less learning difficulties) this way.

~~~
pjmlp
> The C language has more than one way of accessing arrays. Other languages
> don't.

Like this?

    
    
        procedure ArrayDemo;
        var
            data : array [1..20] of Integer;
            ptr : ^Integer;
            i : Integer;
    
        begin
            ptr := @data[low(data)];
            for i:=low(data) to high(data) do
            begin
                WriteLn(ptr^);
                ptr := ptr + Sizeof(Integer)
            end
        end;

------
dceddia
I remember pointers being very hard to grok when I was first learning about
them. And then once I was finally starting to understand, I saw a char __and
my head exploded. It took some time & practice for it to become second nature,
but eventually it did.

It's interesting how most languages have this concept, even if they don't call
it "pointers". In some ways that reduces complexity and learning curve, but in
other ways it leaves invisible footguns lying around.

JavaScript comes to mind as one where references and referential equality are
very important to understand, especially in modern frontend dev with its focus
on immutability, but there's no syntax like C's `*` and `&` to lend clues
about what's going on. I ended up writing a visual guide to "pointers for JS
devs" [0] to help explain the concept, because I think it's really easy to get
bitten by reference bugs when your mental model doesn't match what's
happening.

[0]: [https://daveceddia.com/javascript-
references/](https://daveceddia.com/javascript-references/)

------
mrweasel
I wish someone would do a gentle introduction of header files. I sort of
understand pointers, at least on a basic level. Headers files are apparently
much easier, so they get the briefest of introduction in most "Learn C"
tutorials and books, but I don't understand how they work or how to use them.

~~~
umanwizard
Imagine you have a function f in f.c:

    
    
        void f() {
            puts("hello, world!");
        }
    

and you want to call it in main.c:

    
    
        int main() {
            f();
        }
    

this is an error because the compiler treats each .c file separately, so when
it’s compiling main.c, it isn’t looking at f.c, so it has no way to know the
function f exists. So you need to “declare” it at the top of main.c. A
declaration is similar to a definition, except it has no code, and just tells
the compiler that the function exists:

    
    
        void f();
    

But now imagine f.c had many functions. It would be extremely cumbersome to
repeat all those declarations in every file that wants to use them. So you can
collect all the declarations in some file f.h, and include it from main.c or
anywhere else you want to use functions from f.c. When the compiler sees
#include "f.h", it operates as if the contents of f.h were copied and pasted
at that point.

You might ask “why not just include f.c from main.c instead?” Because then you
would have two _definitions_ of f in your program (one in f.c and one in
main.c), which is illegal, as opposed to two declarations, which is fine.

~~~
clarry
> this is an error because the compiler treats each .c file separately, so
> when it’s compiling main.c, it isn’t looking at f.c, so it has no way to
> know the function f exists.

But it's not an error and the compiler does not need to know the function
exists. If there's no declaration, then the function's type is implicit and
simply assumed to exist.

If the function doesn't actually exist, then it's your linker that will
complain.

~~~
umanwizard
You're right (even with `gcc --std=c99 --pedantic`, which surprised me!) I
should have said that the compiler won't be able to type-check the arguments
and return value.

------
vector_spaces
What I find most annoying about tutorials on pointers (as someone relatively
new to C picking it up for work and fun) and memory management is that every
single one of them seems to discuss the trivial case of a hard coded char or
int array.

Which like, is great for the absolute basics, but not for just about every
serious piece of software where in practice what you need is to build stuff
like e.g. dynamic accumulators of strings -- and virtually no tutorials or
books I've read talk through best practices for doing this.

So I've sort of kludged together my own probably wrong set of patterns for
this. Reading the source code of others on github helps a bit but I have yet
to find a good example of how to e.g. read strings from say a CSV file and
parse it into an array of arrays of strings

Does anyone have any pointers here? (sorry)

~~~
rhn_mk1
Perhaps that's because C pointers are usually (always?) exactly that - a hard
coded char array, which starts at memory offset 0.

Depending on the circumstances, it may be easier to think about it as int
array, or some other type, but the easiest on-ramp for pointers is still
char[] = 0x0.

------
stereoisomer
I think people get scared of pointers because the numbers are big and are in
hexadecimal. But they don't have to be. I didn't understand pointers until I
thought of them as house numbers in postal addresses. In a world where
everyone lives on the same street, you can send anyone a letter by mailing a
letter with their house number written on the envelope. You don't even need to
know their name -- thus SPAM mail is born. The same analogy holds for phone
numbers. The pointer is like a phone number or house number. The person on the
other end is the value you get when you dereference a pointer.

------
Jataman606
The point where I actually understood everything about pointers was when i
realized that they just hold memory address. After that everything like
pointer arithmetic and dereferencing pointers become clear as day.

~~~
Koshkin
It is easy to believe that you understand something while in reality things
are more complicated. What is an address? Is it like an integer value? (Is it
really? Or can it be converted to one? Even if so, how many bits wide is it?)
Or, if not, what is its structure? Back in the day, a question would be is it
a 'far' or a 'near' pointer or we are living in a flat address space? Also,
how is pointer arithmetic affected by alignment?

~~~
megous
Yeah, you may use a pointer in C, but it will compile to an instruction that
fetches some data from a location in memory relative to the currently executed
instruction.

------
zokier
I recommend anyone saying that pointers are simple, just integer memory
locations, to read this article:
[https://www.ralfj.de/blog/2018/07/24/pointers-and-
bytes.html](https://www.ralfj.de/blog/2018/07/24/pointers-and-bytes.html)

The fact that in C pointers point to specifically objects and not just simply
to a random place in memory makes all the difference and is source of oh so
many bugs

------
melvinroest
Here's my explanation.

A pointer stores a memory address.

But I hear you say: can't an int or long also do that? All you need is the
number of the memory address.

Well, the magical thing about a pointer is that it can use a special operator!

What? (I hear you say)

Yes!

Here is what it does: it allows you to obtain the value that is stored at that
memory address.

What does a pointer store again? (a memory address)

But it can also obtain a value at that memory address.

You can't do that with an int, I've tried [0].

We call this operator the dereference operator [1].

It looks like a star

*

That's the one. That's the dereference operator.

One of the confusing things is that when you declare a pointer, you also use a
*

Example

    
    
      int *a;
    
      //or
    
      int * a;
    
      //or
    
      int* a;
    

In those 3 examples, the * is not a dereference operator. It simply indicates
that it is a pointer. In this case we have an int pointer.

I always like to view it as: we have an int! And this is how many times we're
allowed to use the dereference operator: one time

How many times are you allowed to use it on this pointer?

    
    
      int *****super_pointer
    

That's right, five times!

So when you have

    
    
      int val = 10;
    
      int *a = val;
    

Then what is the value of a? It's 10. What do pointers store? Addresses. So
what address is this? Address 10!

But when it comes to memory addresses in computers, there is a tricky part to
it. In normal operating systems, low addresses are reserved for special
things, I think it's the kernel in this case. So if you dereference that
particular address, the OS/runtime environment won't allow you to. They will
give you an error called a segmentation fault.

So you need to get a valid address of the variable val, but how do you do
that? We have another operator for that, which I like to call the address-of
operator.

So when you have

int val = 10;

int *a = &val; // & is the address-of operator

Then the variable a has the valid memory address we want!

There's much more to learn, but I'll leave it at this for now.

\---

I recommend people who start learning pointers/programming to use GDB with the
TUI graphical interface. One could also print the values, but it's easier to
see what really happens. For that there are two steps you need to do:

\- Watch a GDB with TUI tutorial:
[https://www.youtube.com/watch?v=AxsSXMPD3N4](https://www.youtube.com/watch?v=AxsSXMPD3N4)

\- And then also display all the cpu registers. The reason for that: your
variable values will be visible in there (in hexadecimal).

All the GDB commands: [https://sourceware.org/gdb/onlinedocs/gdb/TUI-
Commands.html](https://sourceware.org/gdb/onlinedocs/gdb/TUI-Commands.html)
(look for the regs option)

[0] [https://stackoverflow.com/questions/35379191/cannot-cast-
var...](https://stackoverflow.com/questions/35379191/cannot-cast-variable-
type-to-its-pointer-type-e-g-int-to-int-i-guess-its-a)

[1] Side note: I used to have trouble with the word dereferencing. If you have
to, here is why it's called that way:
[https://stackoverflow.com/questions/35372786/what-does-
the-d...](https://stackoverflow.com/questions/35372786/what-does-the-de-
prefix-in-dereference-mean-is-there-a-linguistic-explanation)

~~~
andrew-nguyen
I'd rethink the this part of the explanation:

 _And this is how many times we 're allowed to use the dereference operator:
one time_

I can see what you meant, but I initially thought this was trying to say that
a pointer declared with a single asterisk could only be dereferenced once and
never dereferenced again afterwards (as if there was a "one-time-use only"
property to pointers). In the same vein, the "super_pointer" example could be
misinterpreted like "Oh, so if I want a pointer that will let me dereference
it on 5 different occasions, then I'll need to declare it with 5 asterisks?" I
think a better way would be to replace the "how many times we're allowed to
use the dereference operator" explanation and start with explaining the idea
of a double pointer

    
    
      int **doublePtr
    

in depth first. With a solid understanding of a double pointer (an address
that points to a memory location that contains an address that points to
another memory location), making the mental jump to understand

    
    
      int *****super_pointer
    

should be easier.

Also, I think low addresses aren't used for various reasons, but I believe the
kernel is stored in the top, high-address region of the address space.
Otherwise, I think this is a really solid explanation of pointers!

~~~
melvinroest
> I can see what you meant, but I initially thought this was trying to say
> that a pointer declared with a single asterisk could only be dereferenced
> once and never dereferenced again afterwards

Ah, haha, I see! You're right. This could've been me back in the day.

> Also, I think low addresses aren't used for various reasons, but I believe
> the kernel is stored in the top, high-address region of the address space.

Ah, yea, I was foggy on this.

For what reasons aren't they used then?

------
wolfi1
Ted Jensen's tutorial helped me a lot back in the day:
[https://pdos.csail.mit.edu/6.828/2014/readings/pointers.pdf](https://pdos.csail.mit.edu/6.828/2014/readings/pointers.pdf)

------
greypowerOz
as a C noob, this example is humorously confusing...

declare an array, fair enough, makes sense.

Declare a char *pointer,(a "reference to something in memory") ok if you say
so.

Assign the char pointer the ARRAY name.... erm, ok.. so ... that would make
the char pointer the 'first char in the array' then?

lol no you silly old duffer, it sets the char pointer to the memory address of
the first char in the array.. not the contents of that location, obviously ;)

~~~
scoutt
> that would make the char pointer the 'first char in the array' then?

That would make the char pointer _to point to_ the 'first char in the array'.

~~~
naiveprogrammer
And why is that? I am a certified C noob and this really confuses me. Why
`alphabet_pointer = alphabet;` points exactly to the first element in the
array? Why not the whole array? Why not the last? Can we have a pointer that
accepts a whole array?

Thanks

~~~
leetcrew
a c array is literally just a sequence of objects in memory (possibly with
padding, but you can ignore that for a while). you can think of pointing
"exactly" to the first element as being equivalent to pointing to the whole
array. you need to know where the array begins and its size to do anything
with it. but once you know where it starts, you can access the next element by
adding sizeof(char) (or whatever the element type happens to be) to the
pointer.

~~~
wmkn
> possibly with padding

What padding?

~~~
scoutt
If you declare a structure of unaligned size, the compiler might (probably
must) introduce some padding bytes at the end of the structure to fit the
alignment. In some architectures you cannot do unaligned accesses (ARM for
example).

Unless you _pack_ the structure with the alignment you want.

~~~
wmkn
Yes, so the structure itself has padding (added by the compiler). But that is
regardless of whether it is in an array or not. OP seemed to suggest that C
arrays introduce padding of some sort, which they do not.

------
Koshkin
A pointer monad, anyone?

------
billpg
Is adding "(2019)" really necessary? Are the contents no longer valid or only
meaningful when set in its historical context?

~~~
tomhoward
It's long been the convention here, and it's useful for people to know how
recently it's been published.

With an article title like this, it could easily be anything from 1 to 30 or
more years old, and showing the date makes it easier for readers to know if
they've already seen it before clicking through.

