Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dereferencing in C

Tags:

c

pointers

c99

c89

I've just started to learn C so please be kind. From what I've read so far regarding pointers:

int * test1; //this is a pointer which is basically an address to the process 
             //memory and usually has the size of 2 bytes (not necessarily, I know)
float test2; //this is an actual value and usually has the size of 4 bytes,
             //being of float type
test2 = 3.0; //this assigns 3 to `test2`

Now, what I don't completely understand:

*test1 = 3; //does this assign 3 at the address 
            //specified by `pointerValue`?
test1 = 3;  //this says that the pointer is basically pointing 
            //at the 3rd byte in process memory, 
            //which is somehow useless, since anything could be there
&test1; //this I really don't get, 
        //is it the pointer to the pointer? 
        //Meaning, the address at which the pointer address is kept?
        //Is it of any use?

Similarly:

*test2; //does this has any sense?
&test2; //is this the address at which the 'test2' value is found? 
        //If so, it's a pointer, which means that you can have pointers pointing 
        //both to the heap address space and stack address space. 
        //I ask because I've always been confused by people who speak about 
        //pointers only in the heap context.
like image 843
Meda Avatar asked Dec 12 '12 22:12

Meda


People also ask

What is dereferencing explain with example?

Dereferencing a variable means accessing the variable stored at a memory address: int i = 5; int * p; p = &i; *p = 7; //*p returns the variable stored at the memory address stored in p, which is i. //i is now 7.

Why is it called dereferencing?

Dereferencing means taking away the reference and giving you what it was actually referring to. A pointer to something really means that your pointer variable holds a memory address of something . But the pointer can also be thought of as a reference to something instead.

Which is used for dereferencing?

2. Which is used to do the dereferencing? Explanation: Dereferencing is using a pointer with asterix.

What does dereference a pointer mean?

Dereferencing a pointer means getting the value that is stored in the memory location pointed by the pointer. The operator * is used to do this, and is called the dereferencing operator.


2 Answers

Great question.

Your first block is correct. A pointer is a variable that holds the address of some data. The type of that pointer tells the code how to interpret the contents of the address being held by that pointer.

The construct:

*test1 = 3

Is called the deferencing of a pointer. That means, you can access the address that the pointer points to and read and write to it like a normal variable. Note:

int *test;
/*
 *    test is a pointer to an int - (int *)
 *   *test behaves like an int - (int)
 *
 * So you can thing of (*test) as a pesudo-variable which has the type 'int' 
 */

The above is just a mnemonic device that I use.

It is rare that you ever assign a numeric value to a pointer... maybe if you're developing for a specific environment which has some 'well-known' memory addresses, but at your level, I wouldn't worry to much about that.

Using

*test2

would ultimately result in an error. You'd be trying to deference something that is not a pointer, so you're likely to get some kind of system error as who knows where it is pointing.

&test1 and &test2 are, indeed, pointers to test1 and test2.

Pointers to pointers are very useful and a search of pointer to a pointer will lead you to some resources that are way better than I am.

like image 152
Dancrumb Avatar answered Oct 14 '22 13:10

Dancrumb


It looks like you've got the first part right.

An incidental thought: there are various conventions about where to put that * sign. I prefer mine nestled with the variable name, as in int *test1 while others prefer int* test1. I'm not sure how common it is to have it floating in the middle.

Another incidental thought: test2 = 3.0 assigns a floating-point 3 to test2. The same end could be achieved with test2=3, in which case the 3 is implicitly converted from an integer to a floating point number. The convention you have chosen is probably safer in terms of clarity, but is not strictly necessary.

Non-incidentals

*test1=3 does assign 3 to the address specified by test.

test1=3 is a line that has meaning, but which I consider meaningless. We do not know what is at memory location 3, if it is safe to touch it, or even if we are allowed to touch it.

That's why it's handy to use something like

int var=3;
int *pointy=&var;
*pointy=4;
//Now var==4.

The command &var returns the memory location of var and stores it in pointy so that we can later access it with *pointy.

But I could also do something like this:

int var[]={1,2,3};
int *pointy=&var;
int *offset=2;
*(pointy+offset)=4;
//Now var[2]==4.

And this is where you might legitimately see something like test1=3: pointers can be added and subtracted just like numbers, so you can store offsets like this.

&test1 is a pointer to a pointer, but that sounds kind of confusing to me. It's really the address in memory where the value of test1 is stored. And test1 just happens to store as its value the address of another variable. Once you start thinking of pointers in this way (address in memory, value stored there), they become easier to work with... or at least I think so.

I don't know if *test2 has "meaning", per se. In principle, it could have a use in that we might imagine that the * command will take the value of test2 to be some location in memory, and it will return the value it finds there. But since you define test2 as a float, it is difficult to predict where in memory we would end up, setting test2=3 will not move us to the third spot of anything (look up the IEEE754 specification to see why). But I would be surprised if a compiler would allow such thing.

Let's look at another quick example:

int var=3;
int pointy1=&var;
int pointy2=&pointy1;
*pointy1=4;  //Now var==4
**pointy2=5; //Now var==5

So you see that you can chain pointers together like this, as many in a row as you'd like. This might show up if you had an array of pointers which was filled with the addresses of many structures you'd created from dynamic memory, and those structures contained pointers to dynamically allocated things themselves. When the time comes to use a pointer to a pointer, you'll probably know it. For now, don't worry too much about them.

like image 36
Richard Avatar answered Oct 14 '22 14:10

Richard