Velocity Reviews > Pointers

# Pointers

Eric Sosman
Guest
Posts: n/a

 03-13-2013
On 3/12/2013 10:40 PM, http://www.velocityreviews.com/forums/(E-Mail Removed) wrote:
> I read the entire FAQ for pointers, and I'm still stuck . What I (think) I understand is that when you declare pointer such as:
>
> int *ptr;
>
> Then that points the address of a variable and not the value inside the address. What I'm not understanding is, what do these do:

Here, ptr is a variable. Its value (once you give it one) will
not be an int, but a value that locates an int somewhere else. By
way of analogy, ptr is a telephone number and the thing it points at
is the telephone.

> 1. &ptr

Like most operators, the unary & operator produces a value. The
value it produces is a pointer to its operand, so &ptr is a value
that points at the variable ptr.

... which is itself a pointer, so maybe we're getting a little
deep for beginners. Let's go back to shallower water for a while:

int foo = 42;
int bar = 56;
int *ptr;

Here we have two int variables, each with its own integer value.
We've also got a pointer variable capable of pointing at ints, but
it hasn't been given a value yet (just as in `int x;' the x has
not yet been given a value). So, let's assign a value:

ptr = &foo;

The &foo part produces a pointer value aiming at the variable
foo, and then we store that value in ptr, making ptr point at foo.
Later on, we might change our mind:

ptr = &bar;

Again &bar produces a pointer value, this one aimed at bar, and we
store that value in ptr. Now ptr points at bar instead of at foo.

Why is this useful? Because we can do things like

.... without caring whether ptr is aimed at foo or at bar or perhaps
at some other int altogether. The prefix * operator looks at its
operand -- a pointer -- finds out what it points at, and delivers
the value of the pointed-at thing. By using ptr, we can make this
single printf() call able to print the value of any int variable in
the program: We just aim ptr at it, and execute the call.

We can also use this on the left-hand side of an assignment:

*ptr = -17;

This stores minus seventeen in ... well, in whatever ptr is
aimed at when the statement is executed. We don't have to write
different assignments for foo and for bar, the same assignment
works for either of them -- or for anything else we've aimed ptr at.

> 2. null pointers

It's useful to have a special pointer value that means "I'm
not pointing at anything whatsoever." That's what a null pointer
is for; the FAQ goes into some detail on how they're used.

> 3.ptr++ vs ++ptr vs (*ptr)++ etc...

When the pointer's target variable is not isolated but is one
element of an array, it makes sense to do arithmetic on the pointer
values: "Whatever you're pointing at, find the next-door neighbor."
You can move forward and back in single steps with ++ and --, or
in larger steps by adding/subtracting bigger integers.

> 4. void *ptr

This is a special case: A pointer to something whose nature
is not stated. It might be pointing at an int, or at a char, or
at a float, or at anything at all. That flexibility makes it
useful for writing "generic" code that can operate on many different
kinds of data, rather than writing separate routines for int, char,
float, and so on.

The flexibility comes at a price: Since the type of the target
is unknown, you can't use *ptr to fetch a value from it, nor to store
a value in it. Nor can you do arithmetic on the pointer, since you
don't know how big a step takes you from one unknown-type variable to
its neighbors. You can pass arbitrary pointer values around in your
program by using void*, but you can't actually do much with them
until you say "Aha: I happen to know that the target is a double,
so I'll convert my void* to a double* and proceed."

... which brings up another part of the price: Loss of type
safety. Since you can convert any kind of data pointer to void*
easily, and then convert a void* to a data pointer again equally
easily, it's absurdly easy to get the types wrong. You start with
&foo (an int* from an earlier example), convert it to void*, then
arrive at the "Aha" moment and convert the void* to a double*. You
are now In Trouble, because you're trying to do double-ish things
on an int. It's like packing all the picnic lunches in identical
paper bags, then giving the ham and Swiss on whole wheat to the
vegetarian Jewish celiac sufferer because all the bags looked alike.
Be watchful always, and be extra watchful when converting pointers
from one type to another.

--
Eric Sosman
(E-Mail Removed)d

Joe Pfeiffer
Guest
Posts: n/a

 03-13-2013
(E-Mail Removed) writes:

> I read the entire FAQ for pointers, and I'm still stuck . What I (think) I understand is that when you declare pointer such as:
>
> int *ptr;
>
> Then that points the address of a variable and not the value inside
> the address. What I'm not understanding is, what do these do:

One small point: it *is* the address of the object it "points" to. To
digress, doing some assembly language programming did more to help me
understand pointers than anything else ever did.

> 1. &ptr

That's the address of the pointer itself. Let's suppose you've got

int a;
int *ptr;
int **ptrptr;

Now you can say:
ptr = &a; // ptr is now contains the address of a --
// it's a pointer to a
ptrptr = &ptr; // ptrptr now contains the address of ptr --
// it's a pointer to ptr, or a pointer to a pointer
// to a

and we can make some assertions:
*ptr == a
*ptrptr = ptr
**ptrptr = a

> 2. null pointers

A pointer need not "point to" (contain the adddress of) any actual
object. We can set the pointer to NULL to give it a specific value we
can test against, to see if it's valid. It's really common that
functions that return a pointer (like malloc()) will return NULL to let
you know they've failed.

Unfortunately, there are myriad ways a pointer can just contain what
amounts to a random number; then it won't point to an object we'd like
it to, probably won't point to any object at all, and almost certainly
won't be NULL. Making sure an invalid pointer contains NULL is the
programmer's responsibility.

> 3.ptr++ vs ++ptr vs (*ptr)++ etc...

ptr++ : access the pointer, then increment it.
If you say
ptr2 = ptr++;
then ptr2 points to the object ptr used to point to, and ptr points to
the next object (I'll describe what the "next" object is in a moment)

++ptr : increment the pointer, then access it.
If you say
ptr3 = ++ptr;
then ptr and ptr3 both point to the next object.

The increment in these cases may not be by 1, like you'd (well, OK, like
I'd) expect. It's by the right amount to get to get past the object
you're pointing to.

So if ptr is a pointer to char like
char *ptr;
then the increment works like you'd think: it adds 1 to ptr.

But if it's a pointer to an int like
int *ptr;
and the system has four chars to an int (which is almost, but not quite,
universally true), then it increments by 4.

And if it's a pointer to some sort of struct like
struct bogus *ptr;
and struct bogus is 42 bytes (a number picked in honor of Douglas Adams,
whose birthday was yesterday), then it increments by 42.

*(ptr++)

dereferences the pointer, and then increments it. So going back to the
earlier example where
ptr = &a;
then
b = *(ptr++);
will set b to a, and then increment ptr to point to the next object of
the same size as a.

> 4. void *ptr

This amounts to being a pointer to an undefined type. The idea is that
a function like malloc() can return a plain ol' pointer, and let your
program deal with what type of pointer it is. So you can say things
like

int *ptr;

ptr = malloc(sizeof *ptr);

and
(1) the sizeof operator will understand that the size of what ptr
points to is 4 (if there are 4 chars to an int, as above), and
tell malloc() that you need an object of size 4 (in practice, an
object 4 bytes long).
(2) malloc() will return a pointer to 4 bytes in memory
(3) ptr will be pointed at these 4 bytes.

Les Cargill
Guest
Posts: n/a

 03-13-2013
(E-Mail Removed) wrote:
> I read the entire FAQ for pointers, and I'm still stuck . What I (think) I understand is that when you declare pointer such as:
>
> int *ptr;
>
> Then that points the address of a variable and not the value inside the address. What I'm not understanding is, what do these do:
>
> 1. &ptr

That is a pointer to ( a pointer to ) an int.

int **qtr = &ptr;

> 2. null pointers

NULL pointers are a marker for "this pointer points to nothing. Yet."
In many archiectures, dereferencing a NULL pointer would generate an
exception which would stop your program.

We're Pavlovian-ly conditioned away from this ( your program crashed! )
but it's really a *safety* thing - if the program tried to soldier on,
who knows what it might have damaged?

> 3.ptr++ vs ++ptr vs (*ptr)++ etc...

Post increment (ptr++) is evaluated after other things happen.
Pre increment (++ptr) is evaluated before other things happen.

(*ptr)++ is the same as ptr[0]++ - the thing pointed to by
ptr is incremented.

> 4. void *ptr
>

"... and the world was *void* and *without form*..."

A void * is an opaque type with no meaning which can be
converted to another type of pointer, but it's tactically
convenient for that type to not be specified then - like as an argument
to the compare function in qsort().

It means "we'll assign this to a meaningful pointer later on."

typedef struct {
....
int el;
....
} twoomba;

twoomba *t = (twoomba *)ptr;
// now it has a meaning.

*ptr = 0;
// there is no type void... error

t->el = 42;
// allowed.

>
>

--
Les Cargill

Bart van Ingen Schenau
Guest
Posts: n/a

 03-13-2013
On Tue, 12 Mar 2013 19:40:19 -0700, j.wagner1024 wrote:

> I read the entire FAQ for pointers, and I'm still stuck . What I
> (think) I understand is that when you declare pointer such as:
>
> int *ptr;
>
> Then that points the address of a variable and not the value inside the

You are slightly off with your understanding.
The most important thing to remember is that variables _store_ something.
If you have
int foo;
int *ptr;
then foo stores an integer and ptr stores the address of an integer

If you like real-world examples, then variables are like pieces of paper
with things written on them. An integer variable is then a piece of paper
with a number written on it. A pointer variable is then a piece of paper
with directions on it where to find something else, like your street
address if it is a pointer to your house, or where you left that piece of
paper with the number on it.

> What I'm not understanding is, what do these do:
>
> 1. &ptr

That gives you the address of the pointer variable, so you can find out
where the pointer variable itself is located and possibly store it in
another pointer variable (one that stores pointer addresses, like `int
**bar`).
As C does not support pass-by-reference semantics for function arguments,
this can be useful if you want to pass ptr to some function that causes
it to point to some other integer. To see the change in the calling
function, you need to pass the address of ptr.
For example:

int a;
void assign(int** p)
{
*p = &a;
}
void foo()
{
int* ptr = NULL;
assign(&ptr);
// ptr now points at a
}

> 2. null pointers

A null pointer is a pointer that explicitly states that it points at
nothing.
The big advantage of null pointers over uninitialized pointers is that
you can actually test if a pointer is a null pointer.

> 3.ptr++ vs ++ptr vs (*ptr)++ etc...

Pointers can not only point to single values, but also to elements of an
array.
With ++ptr and ptr++, you go to the next element of the array (if you
remember the pointer pointing at your house, ++ptr makes it point to your
next door neighbor's house.
With (*ptr)++, you are dealing with two operators. operator* takes the
address stored in a pointer and gives you whatever is stored at that
address. In (*ptr)++, operator++ increments the result of operator*.

When multiple operators are used in an expression, you get to deal with
operator precedence (basically, which operator gets to do its job first).
That is too large a topic to cover here, so you should look it up in your
textbook.

> 4. void *ptr

A void* is special, because it stores addresses without knowing what
might be located at that location.
It could have been
anything *ptr
but for some reason they did not want to add to many keywords to the
language, so they decided to reuse the keyword void for this purpose.

Bart v Ingen Schenau

James Kuyper
Guest
Posts: n/a

 03-13-2013
On 03/12/2013 10:52 PM, Ian Collins wrote:
> (E-Mail Removed) wrote:
>> I read the entire FAQ for pointers, and I'm still stuck . What I
>> (think) I understand is that when you declare pointer such as:
>>
>> int *ptr;
>>
>> Then that points the address of a variable and not the value inside
>> the address. What I'm not understanding is, what do these do:

....
>> 2. null pointers

>
> The null pointer is a pointer with a value of 0. ...

That's true only in the sense that an integer constant expression with a
value of 0 is a null pointer constant, and therefore is converted to a
null pointer when used in an appropriate context. A null pointer need
not refer to memory address 0, and when stored in an object need not
cause all of the bits of that object to be 0, and there are real systems
where neither of those things are true.

> ... Zero is nearly always

Possibly, though that's not guaranteed, and therefore not really
relevant. What's relevant is the fact, that is guaranteed by the C
standard, that a null pointer never compares equal to a pointer to any
object or function. It is used as a special pointer value to indicate
that the pointer doesn't point at anything.
--
James Kuyper

Mark Bluemel
Guest
Posts: n/a

 03-13-2013
On 13/03/2013 03:23, (E-Mail Removed) wrote:
> Could someone recommend some material that I could study?

Any reference book on C will cover pointers - they're pretty
fundamental to the language. What have you read so far? If it's just
online material, you probably ought to look at a real book. (Try
<http://www.c-faq.com/resources/books.html> for some suggestions).

army1987
Guest
Posts: n/a

 03-13-2013
On Wed, 13 Mar 2013 06:29:30 -0400, James Kuyper wrote:

> That's true only in the sense that an integer constant expression with a
> value of 0 is a null pointer constant, and therefore is converted to a
> null pointer when used in an appropriate context.

And also in the sense that a null pointer is treated as false when used
as a condition.

--
[ T H I S S P A C E I S F O R R E N T ]
Troppo poca cultura ci rende ignoranti, troppa ci rende folli.
-- fathermckenzie di it.cultura.linguistica.italiano
<http://xkcd.com/397/>

j.wagner1024@gmail.com
Guest
Posts: n/a

 03-13-2013
On Wednesday, March 13, 2013 6:52:55 AM UTC-4, Mark Bluemel wrote:
> On 13/03/2013 03:23, (E-Mail Removed) wrote:
>

> What have you read so far?

So far I've gone through a few pdf's, such as Gray Hat C, and C Programming, and I am currnetly working on Let Us C. I think I should probably read K&R next. Thansk for the link!

James Kuyper
Guest
Posts: n/a

 03-13-2013
On 03/13/2013 07:10 AM, army1987 wrote:
> On Wed, 13 Mar 2013 06:29:30 -0400, James Kuyper wrote:
>
>> That's true only in the sense that an integer constant expression with a
>> value of 0 is a null pointer constant, and therefore is converted to a
>> null pointer when used in an appropriate context.

>
> And also in the sense that a null pointer is treated as false when used
> as a condition.

The standard merely says "unequal to 0" in all of the relevant places:
!, &&, ||, ?:, _Static_assert(), if(), while(), do while(), for(). It's
the fact that 0 is a null pointer constant, and is therefore implicitly
converts to a null pointer whenever compared for equality with a
pointer, and the fact that all null pointers must compare equal, that
causes null pointers to be treated the same way as 0 in those contexts.

Keith Thompson
Guest
Posts: n/a

 03-13-2013
Shao Miller <(E-Mail Removed)> writes:
> On 3/12/2013 22:40, (E-Mail Removed) wrote:
>> I read the entire FAQ for pointers, and I'm still stuck . What I
>> (think) I understand is that when you declare pointer such as:
>>
>> int *ptr;
>>
>> Then that points the address of a variable and not the value inside

>
> Roughly speaking:
>
> A pointer is an object. An object contains a value. So: A pointer
> object contains a pointer value.

The unqualified word "pointer" is ambiguous; it could mean either
a pointer object (an object of pointer type) or a pointer value
(a value of pointer type). In fact, the C standard uses the word
"pointer" to refer to a pointer value not stored in any object;
see the description of the value returned by malloc, for example.

If there's any chance of misunderstanding (such as in a discussion
with someone who's still stuck on pointers), I suggest using the word
"pointer" only as an adjective, not as a noun: "pointer object",
"pointer value", "pointer expression", "pointer type".

[...]

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"