Pointer values?


#1

Hi. I’m confused by pointers :smiley: Nothing new there, I guess, but I have one specific misunderstanding which is getting in my way and stopping me from really understanding pointers.

I believe that a pointer is a number, and the value of that number is an address in memory, and at that address there can be a value of any type or even a whole set of values and other stuff located in contiguous memory locations starting at that address. But when I set out to test this belief, I get confusing results.

Here is some code:

int i = 17;
int *j = &i;

printf("i is %d\n",i); // outputs 17
printf("j is %p\n",j); // outputs 0x7fff5fbff2cc
printf("address of i is %p\n", &i);// outputs 0x7fff5fbff2cc as expected

OK. so far. So I tried to set the address programmatically:

long k = 0x7fff5fbff2cc;
int valueAtAddressk = *k;// This throws an error Invalid type arg of "unary *"

even though k gets through the printf call happily (apart from the warning):

printf("k is %p\n",k);// warning about format type "void *" vs type long, but still outputs 0x7fff5fbff2cc

Then this:

printf("value stored at address k is %d\n",*k);// This throws the same error as above

So my belief that k stores the address of the value of i must be wrong. But if I assign k to a pointer which gives exactly the same value, it works:

int *l = k;// warning about making pointer from int without cast
printf("l is %p\n",l);// outputs 0x7fff5fbff2cc
printf("value stored at address l is %d\n",*l);// outputs 17

So why does *l work when *k does not?


#2

You need to follow the grammar of the language…

long k: k is not a variable of type long * (although it can happily store an address.)

Therefore, you can not derefrence k to get the object at that address; namely the expression [color=#FF0000]*k[/color] is invalid because k is not of pointer type.

Learn the grammar (syntax and semantics) of the language and follow it religiously.


#3

You said “long k: k is not a variable of type long * (although it can happily store an address.)” but that is exactly at the root of my question: if it stores an address,why can’t I get the contents of the cell at that address from it? Is an address not just a number?

By the way, how do I quote posts in this boards?


#4

To get the value of the object whose address is stored in k (of type long), you need to convert the expression k into an expression of type int * and then rerefrence the resulting expression:

int main (int argc, const char * argv[])
{
    int i = 17;
    int *j = &i;

    assert (sizeof (long) >= sizeof (int *));
    long k = (long)&i; // type casting to long quieten the compiler

    assert (i == 17);
    assert (*j == i);
    assert (*(int *)k == i); // convert: (int *)k and derefrence: *(int *)k

    return 0;
}

#5

Thanks, but I guessed that something that would work :smiley: because k had to be a pointer, but that also implies that a pointer is much more than just a number representing an address. There must be more to it than that, otherwise any old variable holding a legal cell address would be good as a source of the contents of that address. My problem is that I don’t know what that difference is!

And I found the “quote” button…


#6

The difference lies in the syntax and semantics of declarations and of expressions involving pointers.
You need to learn more about the C Programming Language.
See: viewtopic.php?f=133&t=5826


#7

Surely not! The semantics are there in order that the assembler will properly assemble the code. It’s the memory contents that is getting at me.

For example, I believe that memory holds data, and that each memory cell has an address. I know that some data is simple, like an an ASCII character, and takes up exactly one byte in memory, and that one byte has its own unique address, used by the system to access that value. I know that other data types take up more space than one byte, and the address of that space is referenced by the first address in contiguous memory which holds that extended data. (I don’t know if I’m using the correct language here)

Thus a pointer points to that one byte. But somewhere, somehow, something knows that the data extends over, say, 30 bytes. The assembler knows that, and somehow the pointer reference knows that, but when folks say that a pointer is just the address of a memory cell, that must surely be wrong. I hate it when that happens, and I hate it that I don’t understand what is going on, because then I just don’t get it when you say that k, containing the same value as l, can’t be a memory address whereas l can. I do know about pointers and how to use syntax to declare them, but I hope you see that syntax is just a tool, and not the reason for this difficulty Im having.


#8

You have a curious mind, and that’s good. However, curiosity will give you grief if you ignore the rules of the language: syntax and semantics.

Your understanding of pointers is correct, but the way you are using them is distorting your understanding.

Good:

// good
int i = 17;

// good
int *j = &i;  // assign address of an int to a pointer to an int

Ugly and bad:

int i = 7;

// ugly but okay
long k = &i; // assign address of an int to a long

// bad and don't do it
int v = *k;  // attempt to get the value residing at an address stored in a long

If you must get the value residing at an address stored in a non-pointer type:

int i = 7;

// ugly but okay
long k = &i;

// If you must get the value residing at an address stored in a long
int v = *((int *)k);   // both syntax and semantics at work here

Yes, pointers have additional information associated with them, which enables the compiler to compute what the next memory address will be when they are incremented.

For example:

//  main.m

struct Triplet
{
   double x, y, z;
};
typedef struct Triplet Triplet;

int main (int argc, const char * argv[])
{  
    typedef Triplet cell_type;  // Triplet can be replaced with any type
    
    cell_type cells [16];
    cell_type *x = cells;
    const long start = (const long)cells;
    const long cell_size = sizeof (*x);
    
    for (long j = 0; j < 32; ++j)
    {
        // ugly - treating x like a long
        long l = (long)x + j;
        assert (l == start + j);
        
        // address of the next cell j cell away from the start
        cell_type *w = x + j;
        assert (w == (cell_type *)(start + j * cell_size));
    }
    
    // Let's make some good and bad assignments
    cell_type P1 = {0, 0, 0};
    
    // Good
    cells [0] = P1;
    
    // Bad: Violating semantics - good compiler will issue warnings
    cells [1024] = P1; // 1024 > (16 - 1)
    
    // Good
    x [0] = P1;
    
    // Bad: Violating semantics - compiler can't issue warnings!
    x [1024] = P1;  // 1024 > (16 - 1)

    return 0;
}

#9

ibex10: you are obviously very knowledgeable. You know a whole s***load more about this area than I do, and probably more than most on this board. But there is just one teeny problem with your posts (and I take a deep breath here before I continue): you don’t seem to want to take into account the stage-of-learning of those whose posts you reply to. I’ve followed many threads here trying to get a handle on this-and-that, and your posts are ubiquitous, but actually really not always helpful. Sorry. I appreciate your trying, but…

This whole forum is about getting readers of the book to understand the contents of the book. Please correct me if I’m wrong. So you have to realise that these readers, like me, don’t know a whole bunch of stuff about all the other things in the study domain. Otherwise why would we be reading this book? We’re really only at a particular chapter in a particular book, faced with a particular problem, and that book and its contents form the whole essence of our study (apart from surfing websites and forums like this one, which presents its own problems). So if you present stuff, intended to help folks with their particular stage of development, you actually ought to consider what you are asking the poster to do.

So, to take this specific thread as an example, you said that I seem to understand pointers to some extent, but then you started giving examples of “good” “bad” and “ugly” code regarding pointers. That would maybe have been useful if I understood it. But I don’t. Not because I’m stupid, but because I don’t get something as explained in the book, and I just don’t know why you say these things about these code snippets. I don’t know enough to be able to tell why.

Do you really think that I, as a newb, can tell why good is good, bad is bad and ugly is ugly? I note that you did not give any indication at all of why you labelled these code slippets in that way. I don’t think that that is in any way helpful.

Actually I’m CONVINCED that in my case it was not helpful.

to conclude, I quote: [quote]Yes, pointers have additional information associated with them[/quote] which is not mentioned in the book, so I was led astray by that, believing that a pointer was just a number referencing a memory address. If I believe you, it isn’t. That was all I needed. If I believe you.


#10

I am sorry to be blunt, but you have the wrong attitude for learning; you should be asking short specific questions rather than writing long critiques.

If you are Learning the Objective-C Programming Language in order to write shiny applications to run on shiny devices, make sure that you learn the the fundamentals first.

That means picking up a copy of the K & R C Programming Language Book or some other similar book and start reading. Once you have done that, you can tackle the Objective-C.


#11

Alistair, not sure if I do understand your question as deeply as other responders, but I am in about the same learning process as you are, so be assured that I can’t get too technical about it :wink:
Could it be this: in programming language (like ObjC), as I understand it now, you can ask the (numbers of) adresses in memory, you can also ask the computer to make a reservation for some adresses, but you can’t SET the precise adress; that is done in/on/by a different level of computer language, which you can’t reach from the programming language.
??


#12

I was thinking exactly like you thought! :slight_smile: (I was trying to set long k with a memory address I got from the log message. e.g. 0x7fff5fbff2cc) But, then I realized that pointer is not some kind of variable (like int or long). How I realized it? Because in:

int *j = &i;

The variable j is an integer, however it’s also a pointer. And more over:

printf("j is %p\n",j);

Variable j here is an integer, by right, it cannot hold a hexadecimal as its value, because integer can only hold value up to approximately -32000 until 32000 (I forgot the exact value). Integer’s value cannot be set with a hexadecimal value (which contains alphabet).

So, maybe we should not treat pointer’s value as an address in our computer’s memory. Pointer is only pointing to a memory address of some other variable. Pointer itself has variable (for example: int *j, the variable is integer… float *k, the variable is float… and they are all pointers)

Note: This is my understanding, feel free to discuss. :slight_smile:


#13

[quote]int *j = &i;

The variable j is an integer, however it’s also a pointer. And more over:

printf(“j is %p\n”,j);

Variable j here is an integer, by right, it cannot hold a hexadecimal as its value, because integer can only hold value up to approximately -32000 until 32000 (I forgot the exact value). Integer’s value cannot be set with a hexadecimal value (which contains alphabet).

So, maybe we should not treat pointer’s value as an address in our computer’s memory. Pointer is only pointing to a memory address of some other variable. Pointer itself has variable (for example: int *j, the variable is integer… float *k, the variable is float… and they are all pointers)[/quote]
Here it is in a nutshell.

You can assign numbers written in hex notation to integers:

int someNumber = 0xABCDEF;  // (0xABCDEF == 11259375)

Pointers.

int i;
// variable i is for storing an integer value

int *pi
// variable pi is for storing the address of an integer

pi = &i;
// Now pi contains the address of i

double area;
// variable area is for storing a double value

double r = 17;
// variable r is for storing a double value

double *pd;
// variable pd is for storing the address of a double

pd = &area;
// Now pd contains the address of area

area = 4.0 * atan (1.0) * r * r;
*pd == area;

We can generalise the pointers. Below is either a primitive type or a user-defined type (struct type or a typedef type), not an Objective-C class type.

typedef T <SomeType> ;

T v;
// variable v is for storing an object of type T

T *pv = &v;
// variable pv is for storing the address of an object of type T
// variable pv is a pointer to an object of type T
// variable pv is for storing the address of a variable of type T
// variable pv is a pointer to a variable of type T

T **ppv = &pv;
// variable ppv is for storing the address of a pointer variable which stores the address of an object of T.
// variable ppv is a pointer to a pointer to an object of type T.

// We can simplify T**
typedef T * pointer_type;

pointer_type *ppt = &pv;
// Same as T **ppv above.

pointer_type *ppt2 = ppt;
pointer_type pt2 = *ppt2;
T v2 = *pt2;
// v2 == v

#14

Hi Ibex,

Thank you for the explanation. In my understanding, a pointer’s value is always the address which is owned by other variable. And the way we assign it is using:

int i;
i = 10;
int *pi;
pi = &i;   // <<<<< using '&' to assign an address to a pointer

With this… I was trying to play around by:

First getting the memory address using printf…

printf("The address of i is %p\n", &i);

Then using the result from the Debug Area, I tried to assign it to the other pointer…

int *j;
j = 0x7fff5fbff854; // This address is what appears in my debug area when I print the &i
printf("The address of j is %p\n", j);
printf("The content of j is %d\n", *j);

Although with a warning "Incompatible integer to pointer conversion assigning to ‘int *’ from ‘long’… to my surprise, it is working :slight_smile:

The result is:

The address of i is 0x7fff5fbff854
The address of j is 0x7fff5fbff854
The content of j is 10


#15

Your understanding is correct.

Add some good tinkering there :slight_smile:

But be aware that this may not always work: the address of the same variable may change each time you run a program or each time you compile it.

To get rid of the warning, tell the compiler that you know what you are doing:

j = (int *)0x7fff5fbff854; // compiler, cast this value to a pointer to an int

#16

[quote=“ibex10”]Your understanding is correct.

Add some good tinkering there :slight_smile:

But be aware that this may not always work: the address of the same variable may change each time you run a program or each time you compile it.

To get rid of the warning, tell the compiler that you know what you are doing:

j = (int *)0x7fff5fbff854; // compiler, cast this value to a pointer to an int [/quote]

Thank you Ibex. :slight_smile: