简体   繁体   中英

What's the difference between * and & in C?

I'm learning C and I'm still not sure if I understood the difference between & and * yet.

Allow me to try to explain it:

int a; // Declares a variable
int *b; // Declares a pointer
int &c; // Not possible

a = 10;
b = &a; // b gets the address of a
*b = 20; // a now has the value 20

I got these, but then it becomes confusing.

void funct(int a) // A declaration of a function, a is declared
void funct(int *a) // a is declared as a pointer
void funct(int &a) // a now receives only pointers (address)

funct(a) // Creates a copy of a
funct(*a) // Uses a pointer, can create a pointer of a pointer in some cases
funct(&a) // Sends an address of a pointer

So, both funct(*a) and funct(&a) are correct, right? What's the difference?

* and & as type modifiers

  • int i declares an int.
  • int* p declares a pointer to an int.
  • int& r = i declares a reference to an int, and initializes it to refer to i .
    C++ only. Note that references must be assigned at initialization, therefore int& r; is not possible.

Similarly:

  • void foo(int i) declares a function taking an int (by value, ie as a copy).
  • void foo(int* p) declares a function taking a pointer to an int.
  • void foo(int& r) declares a function taking an int by reference. (C++ only)

* and & as operators

  • foo(i) calls foo(int) . The parameter is passed as a copy.
  • foo(*p) dereferences the int pointer p and calls foo(int) with the int pointed to by p .
  • foo(&i) takes the address of the int i and calls foo(int*) with that address.

( tl;dr ) So in conclusion, depending on the context:

funct(int a) 

Creates a copy of a

funct(int* a) 

Takes a pointer to an int as input. But makes a copy of the pointer.

funct(int& a)

Takes an int, but by reference. a is now the exact same int that was given. Not a copy. Not a pointer.

Originally in C there were pointers and no references. Very often though we just want to access a value without copying it and the fact that we're passing around an address and not the actual value is an unimportant detail.

C++ introduced references to abstract away the plumbing of pointers. If you want to "show" a value to a function in C++ then references are preferable. The function is guaranteed that a reference is not null and can access it as if it were the value itself. Pointers are still necessary for other purposes, for example, you can "re-aim" a pointer or delete with a pointer but you can't do so with a reference.

Their functionality does overlap and without a bit of history it should confuse you that we have both.

So the answer to your direct question is that very often there is no difference. That said, f(int*) can be useful if you want the function to be able to check if the pointer is null. If you're using C then pointers are the only option.

The meaning of * is dependent on context. When in a data or function argument declaration, it is a datatype qualifier, not an operator int* is a datatype in itself. For this reason it is useful perhaps to write:

int* x ;

rather than:

int *x ;

They are identical, but the first form emphasises that it the * is part of the type name, and visually distinguishes it from usage as dereference operator.

When applied to an instantiated pointer variable, it is the dereference operator, and yields the the value pointed to.

& in C is only an operator, it yields the address (or pointer to ) of an object. It cannot be used in a declaration. In C++ it is a type qualifier for a reference which is similar to a pointer but has more restrictive behaviour and is therefore often safer.

Your suggestion in the comment here:

funct(&a) // Sends an address of a pointer

is not correct. The address of a is passed; that would only be " address of a pointer " is a itself is a pointer. A pointer is an address. The type of an address of a pointer to int would be int** (a pointer to a pointer).

Perhaps it is necessary to explain the fundamentals of pointer and value variables? A pointer describes the location in memory of a variable, while a value describes the content of a memory location.

  • <typename> * is a pointer-to- <typename> data type.
  • & * <value-variable> yields the address or location of <variable> (ie a pointer to <variable> ),
  • * * <pointer-variable> dereferences a pointer to yield the the value at the address represented by the pointer.

So given for example:

int a = 10 ;
int* pa = &a ; 

then

*pa == 10

void funct(int &a) declares a function that takes a reference . A reference is conceptually a pointer in that the function can modify the variable that's passed in, but is syntactically used like a value (so you don't have to de-reference it all the time to use it).

When you do func(&a) that's called a "call by reference" that means your parameter "a" can actually be modified within the function and any changes made will be visible to the calling program. This is a useful way if you want to return multiple values from a function for example:

int twoValues(int &x)
{
  int y = x * 2; 
  x = x + 10; 
  return y; 
}

now if you call this function from your main program like this:

 int A, B; 
 B = 5; 
 A = twoValues(B); 

This will result in:

 A holding the value 10 (which is 5 * 2) 
 and B will hold the value 15 (which is 5 + 10).

If you didn't have the & sign in the function signature, any changes you make to the parameter passed to the function "twoValues" would only be visible inside that function but as far as the calling program (eg main) is concerned, they will be the same.

Now calling a function with a pointer parameter is most useful when you want to pass an array of values or a list. Example:

float average ( int *list, int size_of_list) 
{
  float sum = 0; 
  for(int i = 0; i < size_of_list; i++)
   {
    sum += list[i];
    }
   return (sum/size_of_list);
}

note that the size_of_list parameter is simply the number of elements in the array you are passing (not size in bytes).

I hope this helps.

C++ is different from c in many aspects and references is a part of it.

In terms of c++ context:

void funct(int *a) // a is declared as a pointer This corelates to the use of pointers in c..so, you can compare this feature to that of c.

void funct(int &a) // a now receives only pointers (address) This would lead to the reference usage in c++... you cannot corelate this to that of c..

Here is a good q&a clarifying differences between these two. What are the differences between a pointer variable and a reference variable in C++?

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