简体   繁体   中英

How do I use pointers? in C

Im fairly new to C programming and I am confused as to how pointers work. How do you use ONLY pointers to copy values for example ... use only pointers to copy the value in x into y.

#include <stdio.h>

int main (void)
{
    int x,y;
    int *ptr1;

    ptr1 = &x;    

    printf("Input a number: \n");
    scanf("%d",&x);

    y = ptr1;

    printf("Y : %d \n",y);

    return 0;
}

It is quite simple. & returns the address of a variable. So when you do:

ptr1 = &x;

ptr1 is pointing to x , or holding variable x 's address.

Now lets say you want to copy the value from the variable ptr1 is pointing to. You need to use * . When you write

y = ptr1;

the value of ptr1 is in y , not the value ptr1 was pointing to. To put the value of the variable, ptr1 is pointing to, use * :

y = *ptr1;

This will put the value of the variable ptr1 was pointing to in y , or in simple terms, put the value of x in y . This is because ptr1 is pointing to x .


To solve simple issues like this next time, enable all warnings and errors of your compiler, during compilation.

If you're using gcc , use -Wall and -Wextra . -Wall will enable all warnings and -Wextra will turn all warnings into errors, confirming that you do not ignore the warnings.

What's a pointer??

A pointer is a special primitive-type in C. As well as the int type stored decimals, a pointer stored memory address.

How to create pointers

For all types and user-types (ie structures, unions) you must do:

Type * pointer_name;
int * pointer_to_int;
MyStruct * pointer_to_myStruct;

How to assing pointers

As I said, i pointer stored memory address, so the & operator returns the memory address of a variable.

int a = 26;
int *pointer1 = &a, *pointer2, *pointer3; // pointer1 points to a
pointer2 = &a; // pointer2 points to a
pointer3 = pointer2; // pointer3 points to the memory address that pointer2 too points, so pointer3 points to a :)

How to use a pointer value

If you want to access to the value of a pointer you must to use the * operator:

int y = *pointer1; // Ok, y = a. So y = 25 ;)
int y = pointer1; // Error, y can't store memory address.

Editing value of a variable points by a pointer

To change the value of a variable through a pointer, first, you must to access to the value and then change it.

*pointer1++; // Ok, a = 27;
*pointer1 = 12; // Ok, a = 12;
pointer1 = 12; // Noo, pointer1 points to the memory address 12. It's a problem and maybe it does crush your program.
pointer1++; // Only when you use pointer and arrays ;).

Long Winded Explanation of Pointers

When explaining what pointers are to people who already know how to program, I find that it's really easy to introduce them using array terminology.

Below all abstraction, your computer's memory is really just a big array, which we will call mem . mem[0] is the first byte in memory, mem[1] is the second, and so forth.

When your program is running, almost all variables are stored in memory somewhere. The way variables are seen in code is pretty simple. Your CPU knows a number which is an index in mem (which I'll call base ) where your program's data is, and the actual code just refers to variables using base and an offset.

For a hypothetical bit of code, let's look at this:

byte foo(byte a, byte b){
    byte c = a + b;
    return c;
}

A naive but good example of what this actually ends up looking like after compiling is something along the lines of:

  • Move base to make room for three new bytes
  • Set mem[base+0] (variable a) to the value of a
  • Set mem[base+1] (variable b) to the value of b
  • Set mem[base+2] (variable c) to the sum mem[base+0] + mem[base+1]
  • Set the return value to mem[base+2]
  • Move base back to where it was before calling the function

The exact details of what happens is platform and convention specific, but will generally look like that without any optimizations.

As the example illustrates, the notion of a b and c being special entities kind of goes out the window. The compiler calculates what offset to give the variables when generating relevant code, but the end result just deals with base and hard-coded offsets.

What is a pointer?

A pointer is just a fancy way to refer to an index within the mem array. In fact, a pointer is really just a number. That's all it is; C just gives you some syntax to make it a little more obvious that it's supposed to be an index in the mem array rather than some arbitrary number.

What a does referencing and dereferencing mean?

When you reference a variable (like &var ) the compiler retrieves the offset it calculated for the variable, and then emits some code that roughly means "Return the sum of base and the variable's offset"

Here's another bit of code:

void foo(byte a){
    byte bar = a;
    byte *ptr = &bar;
}

(Yes, it doesn't do anything, but it's for illustration of basic concepts)

This roughly translates to:

  • Move base to make room for two bytes and a pointer
  • Set mem[base+0] (variable a) to the value of a
  • Set mem[base+1] (variable bar) to the value of mem[base+0]
  • Set mem[base+2] (variable ptr) to the value of base+1 (since 1 was the offset used for bar)
  • Move base back to where it had been earlier

In this example you can see that when you reference a variable, the compiler just uses the memory index as the value, rather than the value found in mem at that index.

Now, when you dereference a pointer (like *ptr ) the compiler uses the value stored in the pointer as the index in mem . Example:

void foo(byte* a){
    byte value = *a;
}

Explanation:

  • Move base to make room for a pointer and a byte
  • Set mem[base+0] (variable a) to the value of a
  • Set mem[base+1] (variable value) to mem[mem[base+0]]
  • Move base back to where it started

In this example, the compiler uses the value in memory where the index of that value is specified by another value in memory. This can go as deep as you want, but usually only ever goes one or two levels deep.

A few notes

Since referenced variables are really just numbers, you can't reference a reference or assign a value to a reference, since base+offset is the value we get from the first reference, which is not stored in memory, and thus we cannot get the location where that is stored in memory. ( &var = value; and &&var are illegal statements). However, you can dereference a reference, but that just puts you back where you started ( *&var is legal).

On the flipside, since a dereferenced variable is a value in memory, you can reference a dereferenced value, dereference a dereferenced value, and assign data to a dereferenced variable. ( *var = value; , &*var , and **var are all legal statements.)

Also, not all types are one byte large, but I simplified the examples to make it a bit more easy to grasp. In reality, a pointer would occupy several bytes in memory on most machines, but I kept it at one byte to avoid confusing the issue. The general principle is the same.

Summed up

  • Memory is just a big array I'm calling mem .
  • Each variable is stored in memory at a location I'm calling varlocation which is specified by the compiler for every variable.
  • When the computer refers to a variable normally, it ends up looking like mem[varlocation] in the end code.
  • When you reference the variable, you just get the numerical value of varlocation in the end code.
  • When you dereference the variable, you get the value of mem[mem[varlocation]] in the code.

tl;dr - To actually answer the question...

//Your variables x and y and ptr
int x, y;
int *ptr;
//Store the location of x (x_location) in the ptr variable
ptr = &x; //Roughly: mem[ptr_location] = x_location;
//Initialize your x value with scanf
//Notice scanf takes the location of (a.k.a. pointer to) x to know where 
//to put the value in memory
scanf("%d", &x); 
y = *ptr; //Roughly: mem[y_location] = mem[mem[ptr_location]]
//Since 'mem[ptr_location]' was set to the value 'x_location',
//then that line turns into 'mem[y_location] = mem[x_location]'
//which is the same thing as 'y = x;'

Overall, you just missed the star to dereference the variable, as others have already pointed out.

Simply change y = ptr1; to y = *ptr1; .

This is because ptr1 is a pointer to x , and to get the value of x , you have to dereference ptr1 by adding a leading * .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM