What's the different between args and &args? - c

Here is my code snip
#include <stdio.h>
void change(int a[]){
printf("%p\n",&a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",&b);
change(b);
return 0;
}
I run it and it get the result following
0x7fff5def1c60
0x7fff5def1c38
As we can see the actual parameter address is defferent from the formal parameter address
Then I edited my following
#include <stdio.h>
void change(int a[]){
printf("%p\n",a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",b);
change(b);
return 0;
}
Then I get the results
0x7fff56501c60
0x7fff56501c60
So it seems that the actual parameter and the formal parameter have the same address.
I am confused that what's the different between &a and a(a is a array),and why I get the different address from the first snippet?
Thanks!

In:
printf("%p\n",&b);
you are printing the address to the first array cell.
In:
change(b);
and specifically in:
void change(int a[]){
printf("%p\n",&a);
}
you are printing the address of the variable a which in itself is a decayed pointer. So it is semantically equivalent to:
void change(int* a){
printf("%p\n",&a);
}
To retrieve the array first cell you would need to write the function as:
void change(int* a){
printf("%p\n", a);
// ^^
}

You can think of a is the starting address of the memory where to store array[1, 2].
Please also think of a is a variable that stores the array address. A variable means itself is somewhere in the memory. So &a is the address of the variable a. All in all, address &a in memory stores the address of the array[1,2].
In your first case, you are passing the address of variable b to function change so that the function variable a stores the address of variable b. But &a is the address of a not the content of a. That's the reason cause the difference.

Because I don't think that the answers so far stress it enough, I'll give another answer:
There is no difference between b and &b, if b is an array. An array is almost like a pointer, but not 100%. A pointer is a variable that stores an address, as you know. So when you create a pointer p, you create a new variable and then assign some address to it. Now the pointer variable p has an address, and it's value is also an address. You can do three things with it:
- Get ps address with &p
- Get ps value with p
- Get ps dereferenced value with *p
With an array ar, it is different. It acts like a pointer, but it is not a distinct variable where an adress is stored! By creating an array, you just allocate the memory for the elements you want to store, but not for a variable that stores the address of these elements. The variable ar just 'stands for' the address of the first element, but it is not saved somewhere in an extra space; the compiler makes sure to translate ar to the memory of the first element - this is important to understand. So what you can do with it is:
- Get ars address with &ar or with ar
- Get ars value with ar[0]
This is the reason why in your change function, int a[] is the same as int *a but in your main function, int b[] is not the same as int *b. The latter allocates memory for an address, while the first just creates memory for a specified amount of elements, and just uses b as a placeholder for the first address of these elements - there is no extra memory allocated for the first element's address, as it would be with a pointer.
This is also the reason why in main, you can't do b = some_pointer, but you can do it in change - because one is a pointer that has memory allocated and thus can change it's value like every other variable, and the other one is just a placeholder for it's first element and thus cannot change it's value.
I hope now it is clear why &b is the same as b - Since b is not a distinct variable with a place in memory, you cannot ask for it's address - it will just give you the address that b stand for anyway.

In main(), b is an array which size if derived from the initialisation, and &b denotes the adress of the array.
In change(), a is an array of unknown size, which as parameter is handled as a pointer. &a is the adress of this pointer.
In the second version of your code, without the & you refer in both case to the value of the pointer.
Here the relevant extracts from the C11 standard:
6.5.3 Unary operators, pt 3: The unary & operator yields the address of its operand.
6.7.6.3 Function declarators, pt 7: A declaration of a parameter as ‘‘array of type’’ shall be adjusted to ‘‘qualified pointer to
type’’, where the type qualifiers (if any) are those specified within
the [ and ] of the array type derivation.

The "&" operator returns the address of a variable and the "%p" construct in printf returns the address of the pointer.
In your example, these calls in main() are equivalent:
printf("%p\n",b);
printf("%p\n",&b);
Both return the memory position of b, which is 0x7fff56501c60 in your example
When you define a function, you introduce a local variable a:
void change(int a[]){
This is a pointer (equivalent to int * a) and has its own memory address.
When you call this inside the function:
printf("%p\n",a);
you get the same as above: The address of b: The value of pointer b is copied to a and printf tells you where it points at.
However if you do this:
printf("%p\n",&a);
Then you get the address of the local variable a, which is distinct to b. It does not matter what is inside a and in your example the value of b is not even used by function "change", you could also run this:
#include <stdio.h>
void change(int a[]){
printf("%p\n",&a);
}
int main(){
int b[] = {1,2} ;
printf("%p\n",&b);
change((int *)0);
return 0;
}
This runs "change" with a Nullpointer and it is still equivalent to your first example: "change" just prints out the address of the local variable a, regardless of contents.

Related

How can array name and the address of the array name both prints the same value? [duplicate]

This question already has answers here:
Is an array name a pointer?
(8 answers)
How come an array's address is equal to its value in C?
(6 answers)
C: Does the address operator (&) produce a pointer (address + type) or just an address?
(3 answers)
Closed 4 years ago.
Consider the following code snippet.
int main(){
int x[2];
x[0]=100;
x[1]=200;
printf("%d\n",x);
printf("%d\n",&x);
printf("%d\n",*x);
}
The output is given as (in three lines)
6487616 6487616 100
I've read that the array name is a pointer to the first element of the array. Therefore, the value of 'x' prints a memory address. But if i try to print the address of the pointer which holds the address of the first element of the array, why does that also print the same memory address? Shouldn't it be printing another memory address, simply because in order for a variable to store a memory address it should be a pointer and that pointer variable also has a memory address in the RAM.
int main(){
int y = 10;
int *p = &y;
printf("%d\n",&y);
printf("%d\n",&p);
}
The above code gives the output as
6487628 6487616
So why doesn't this work when it comes to arrays?
Contrary to what you might have heard, arrays and pointers are not the same thing. An array is a sequence of one or more elements of a given type, while a pointer points to a memory location (which may be the first element of an array). Because of this, the address of an array is the same as the address of the first element.
Where the confusion comes in is that in most expressions, an array decays into a pointer to the first element. One of the times this decaying does not happen is when the array is the subject of the address-of operator &.
In your first piece of code, you first print x. Ignoring for the moment that you should be using %p to print a pointer instead of %d, here x decays into a pointer to the first element and that address is what is printed. In the next call to printf, you pass in &x. This has the same value as x (when converted to a pointer) but has a different type, i.e. x has type int [2] (which decays to int *) and &x has type int (*)[2].
In your second example, y is an int and p is an int *. These are separate variables, so each has a different address.
First, for printing memory addresses, one should use %p instead of %d; using %d is actually undefined behaviour, even if it often works:
int main(){
int x[2];
x[0]=100;
x[1]=200;
printf("%p\n",(void*)x);
printf("%p\n",(void*)&x);
printf("%d\n",*x);
}
Second, &x does not introduce a new object / variable but uses the address of object x. The use of x decays to a pointer to the first element of array object x, and this is equivalent to &x and &x[0]. So same object -> same address, and therefore, x, &x, and &x[0] give you the same address.
In the other example, you introduce a new object p, which is different from object x. That's why &p and &x give different addresses
What you heard is slightly incorrect.
An array is not "a constant pointer". An array is an array.
When you use an array in an expression, what you get is a pointer to the array's first element.
That pointer will have the same value (although a different type) as a pointer to the whole array.
These facts explain the results you saw.
You should use %p to print memory address
#include <stdio.h>
int main(){
int y = 10;
int *p = &y;
printf("%p\n",&y);
printf("%p\n",&p);
}
output :
0x7ffeed2dd6fc
0x7ffeed2dd6f0
by the way
int main(){
int x[2];
x[0]=100;
x[1]=200;
printf("%p\n",x); // u should use %p here
printf("%p\n",&x); // this is the address of the array same as upper
printf("%d\n",*x); // this is the value of x it's same as x[0]
}

Copy of address in C?

I know that this code:
void incVar(int i){
i++;
}
We know this will create a copy of the integer and then increase that value, but not the actual value.
By nature: Methods in C create copies of parameters in their Stack Frame and not the original variable.
But:
void incVar(int *i){
(*i)++;
}
Is supposed to increase the actual value of the integer by the pointer dereference.
But then, why doesn't C just create a copy of the pointer *i instead? If this is the normal behavior with regular integers, then why doesn't the same thing happen with pointers?
It is the same with pointers. All variables in C are passed by value, even pointers.
You copy the address stored in the pointer outside the function, into its parameter.
But you can use that address to reference a variable which can be allocated anywhere. So in the following code:
int j = 0;
incVar(&j);
incVar receives by-copy the address of j. But it can use that address to read or modify j (in)directly.
In fact the same thing as with values happens with pointers. Just make sure to understand the syntax correctly. You are not passing the integer *i by copy to incVar, but you are passing the pointer i of type int* by copy. No matter how often you copy the pointer to an address, it always points to the same address. So i in your second incVar example points to the integer the caller took the address of. So by derefencing the copy of the pointer (in (*i)++), you are acessing the integer of the caller.
Its better to see int *i; as a variable named i of type pointer-to-int, instead of a pointer named *i.
In your example:
void incVar(int *i) {
(*i)++;
}
We probably use it as such in the main function:
int a = 5;
incVar(&a); //After this line, a is now 6.
What happens in incVar(..) is this:
A variable i is created, of type pointer-to-int.
It holds a copy of the value of &a.
Although i is a copy, its value is the same as that of the value of &a, and it still points to the same integer a.
As a result, by de-referencing i, I refer to the integer a.
Increment the integer a, which obviously is at the address pointed to by i.

Difficulty in understanding the pointers output

Please have a look at code below :
#include <stdio.h>
void main()
{
int a=30;
int *var=&a;
Change(&var);
printf("%d %d",*var,a);
}
int Change(int**ptr)
{
**ptr=40;
}
#include <stdio.h>
void main()
{
int a=30;
int *var=&a;
Change(var);
printf("%d %d",*var,a);
}
int Change( int *ptr)
{
*ptr=40;
}
The output from both programs is 40 40
We are passing the copy of address of var so why it is reflected in actual main function and producing output 40 40?
Why both of these programs are producing same output?
Both programs are equivalent. In first one, you passing pointer to pointer (i.e. address of pointer variable), and then dereferencing it twice. In second one, you are are just passing pointer (i.e. address of actual variable) and dereferencing it once.
It seems to me you need the following illustration to get the answer on your q:
The output is the same because you write 40 via the same pointer to int. In the second case you pass pointer-to-int, which you successfully dereference with * operator and obtain lvalue with type int, to which you then write 40. In the first case you pass pointer-to-pointer-to-int. And then you do double dereferencing: **ptr or the same as *(*ptr). Inner * is applied first and makes the expression with type pointer-to-int inside braces, and that pointer-to-int is the same as was passed to Change() in the second case. And at the end - outer * works just like for the second case.
&var passes the address of var and Change uses double pointer because, var is pointing to address of a. So, Derefrencing single pointer on &var (address of var) will point to the value stored in var i.e., a's address, so again derefrencing it, will point to the value of a i.e., 30.
For single pointer Change, I think, you should figure that out now from the above details.

How &a is a pointer to a if it generates the address of a?

I'm new to programming, and at present I am learning about pointers in C.
I know that pointers are the variables which contain or hold address of another variable. Today when I was more learning about it with K&R I got confused in a line which says "&a is a pointer to a" in a given function swap(&a,&b) in Page No. 80. How &a is a pointer? It is not a variable, it is the address of the variable. Am I right?
I know that arguments can be passed to a function in two ways: call by value and call by reference. The caller's value of the argument is not changed in the first one, but it can be changed in the second one.
My question is I had read that if we want to change the value of the variable we have to pass the pointer to it (i.e. the location of the value we want to modify). What is meant by that? I mean, do we have to pass pointers to the function? And what is the meaning of the statement, "we have to pass the pointers to the location we want to modify".
A pointer is not a variable. A pointer is a value.
A variable, in C, designates a storage location, and a value can be stored in that location. Thus, if you have a variable a declared with int a, then a is a variable in which an integer value can be stored. If you have a variable int *x, then x is a variable in which a pointer to an integer value can be stored.
The address of a storage location can be obtained using the & operator. E.g., &a is the address of the storage location designated by a, or the address of a, and can be stored in (among other things) a variable of the corresponding type. Thus you can have:
int a = 42; /* a is a variable of type int, and has value 42 */
int* x = &a; /* x is a variable of type int*, and has value &a */
Although analogies in programming are often dangerous, you might think of things like page numbers in a book. The page number of a page is not the same thing as the page, but page numbers can still be written down on pages. E.g., the table of contents page has lots of page numbers written down on it. Thus:
actual_page p = ...; /* a page structure */
page_number n = &p; /* a page number */
A pointer is an address. A pointer variable is a variable holding an address.
It is perhaps analogous to the difference between a literal integer 1 and an integer variable int a. One might refer to both a and 1 as integers, just as you might refer to &a and int* p as pointers.
Note also that &a is not an lvalue and cannot be assigned - so it is as you say not a variable, but it is a pointer nonetheless, and can itself be assigned to a pointer variable.
If a is a variable of some type T, then &a is an expression which evaluates to the address of that variable, also known as a pointer to that variable—the terms are interchangeable. &a has the type T*, which is pronounced “pointer to T”.
int x = 4; // 4 has type int, so we can assign it to an int variable.
int *p = &x; // &x has type int*, so we can assign it to an int* variable.
The reason that you can modify function arguments passed by pointer is that a pointer introduces a sort of alias for a variable. You can alter it from multiple locations, either directly (via the variable) or indirectly (via the pointer).
// modifying x modifies *p.
++x;
printf("%d %d\n", x, *p);
// modifying *p modifies x.
++*p;
printf("%d %d\n", x, *p);
As others have observed, a pointer is a particular kind of value, not a particular kind of variable.
With regard to calling functions:
You cannot "pass a variable to a function" in C. If you put a variable name in the argument list of a function call then the value stored in that variable is passed, not the variable itself.
Although in a general sense programming languages may provide for passing function arguments either by value or by reference, C provides only pass by value. You can emulate pass by reference in C, however, by passing a pointer (value) to the location where another value is stored. That's what swap(&a, &b) does: you are passing the locations where the values of variables a and b are stored (that is, pointers to those values).
Pointer contains the address - so synonymous.
When you pass by reference, you are passing in the address - to directly modify the value.
A pointer is a type of variable that stores the address to an object.
Basically, the pointer is the address.
Think of it as a piece of paper. When it has a number printed on it, it's an integer (or other numeric type).
A pointer is a piece of paper that says "the data is on the peice of paper in location x", where "location x" is the address of the object.
How &a is a pointer to a if it generates the address of a?
The terms pointer and address in C are synonymous.
When you create a variable:
int a = 0;
It is created in memory at a specific memory location, or address, with sufficient memory to hold 1 int.
&a does not generate the address, it simply provides the address.
The & operator can be used to set the address of a pointer to a specific location, such as this:
int a = 0;//a now exists in memory at a specific location;
int *b = {0}; // b is created in memory as a pointer, and can be assigned a location
b = &a; //b is assigned the location (address) of the variable a
Stated a little differently, in the previous line, & is referred to as the address-of operator, so:
b = &x; Can be Read: Assign to b (a pointer) the address of a.

C pointers Question

For :
int *a;
a is an address where an integer can be stored.
&a is an address where a is stored.
Then, where is &a stored?
And, where is &(&a) stored?
And, where is &(&(&a)) stored?
Where does this storing of addresses stop?
If you don't explicitly write &a it will not be stored anywhere. If you do write then the address will be computed and stored either in an unnamed variable (temporary) or a named varible you write.
For example:
functionCall( &a ); // address will be in a temporary variable used for passing the parameter
int** b = &a; // address will be stored in variable b
otherFunctionCall( &&a ); // illegal, since &a is an expression operator & can't be applied to it
&a is a constant.
&(&a) is illegal.
a is not "an address where an integer can be stored". a is a variable large enough to hold the address of an integer. The only "integer" you can store directly in a is the address of an integer, viewed as an integer itself:
int *a;
int b;
a = &b;
printf("a is now %x\n", (unsigned int) a);
It is correct that a itself has an address, which is &a, but that address is not stored somewhere explicit, at runtime.
At a stretch, you might be able to store something that looks like the integer 0:
a = 0;
But this is just a shorthand syntax for "the NULL pointer", i.e. a pointer value guaranteed to not be the address of any actual object.
&a is the address of a. It is a value, result of operator & applied to a, and is not "stored", and has no address, so &(&a) is invalid. It's like 2+3.
int *a is a variable the size of a pointer, just like int b would an automatic int variable.
If this declaration is in a function, that variable is automatic and stored on the [stack](http://en.wikipedia.org/wiki/Stack_(data_structure)#Hardware_stacks) at runtime (a simple stack decrement allocates memory for it).
If the declaration is global, then 'a' is simply mapped in executable's .DATA area.
Any more & signs appended can 'create storage', because of the temporary variables you're using to hold'em ;) :
b = &a; //the address in the executable's .DATA or on the stack (if `a` auto)
c = &b; //the address of `b` on the stack, independent of `a` or `&a`
d = &c; //the address of `c` on the stack, independent of `a` or `&a`
z = &(&a); //error: invalid lvalue in unary '&'
The last line complains about the fact that & requires the operand to be a lvalue. That is, something assignable - like b and c above. (&a) as is a result of an expression which is not stored anywhere, therefore is not a lvalue.
You can keep going forever:
int value = 742;
int *a = &value;
void *b = &a;
void *c = &b;
void *d = &c;
You wouldn't put it on a single line without assigning it to anything - in that case it would be invalid.
At the crux of your problem seems to be a lack of understanding of the physical nature of memory and pointers. Not how the code works. As Im sure you know, physical memory is comprised of a large group of adjacent cells. The addresses of these cells are fixed and hard-coded by the computer itself, not by software apps or the programming language that you use. When you refer to &a, you are referring to the physical block of memory that is currently holding your value you've stored within the computers ram. "a" is simply a name that you've given the computer so that it knows exactly what block of memory to find the value that you've stored. I think that pretty much covers memory address.
Lets go over pointers now. A pointer is yet another memory address, that is referred to by the computer. It has whatever name that you give it. In this case it should be called something else besides the same name that you gave your first value. Lets call it "b". Based on how you declared it. b's memory location is only capable of holding one type of data....another memory location.... so when I say: b= &a I'm saying that the memory address of 'b'(which is designed only to hold memory addresses), is to hold the memory address of 'a'. Meanwhile on the other side of town, the memory address of 'a' has an integer stored in it.
I hope that this didnt get confusing, I tried not to get all techno-babble on you here. If youre still confused. Post again, Ill explain with code next time.
-UBcse
In C, a variable x may act as a value (on the right hand side of =, where it is called an rvalue), or it may act as a container for values (on the left hand side of =, where it is called an lvalue). You may take the address of x, because you can take the address of any lvalue—this gives you a pointer to the container. But because a pointer is an rvalue, not a container, you can never take &(&x). In fact for any lvalue l, &l is legal but &(&l) is never legal.
a is a variable of type "address of int";
&a is the address of variable a;
&(&a) would be the address of the address of variable a, which makes no sense
Not quite. a is a variable in which an address of some integer may be stored. &a is the address of a, i. e. the address of the variable a, which may contain an address of some integer.
Very Important: until and unless an address of something is assigned to a, it is an uninitialized pointer. Trying to use whatever it points to will lead to unpredictable results, and will likely crash your program.
You can have a pointer to a pointer.
Ex:
void foo(int **blah)
{
int *a = *blah;
...
}
A pointer does take up memory. It's just a small container that holds the address of something. It just can't take up "no space" because everything in the computer is represented somehow by numbers. It's just that as far as C/C++ is concenred, int *a is simply a pointer to an object and takes up no space. That is to keep you from having to manage any sort of memory... it keeps the machine seperated from the code.
int *a; is a pointer to an int called 'a'.
&a; is the derefrence of int *a. it's pointing to itself. this is what you would use to point to the variable that you wanted to pass around from function to function. derefrence is just a fancy word for "getting the address back"
&(&(&a)) is not a valid expression as previously stated. you may make a pointer to a pointer to a pointer. That may be what your thinking of. In such a case you would derefrence the last pointer in question and the computer should understand what you're talking about.
To answer the "where is 'a' stored" question; on the stack.
please, if i'm incorrect on anything, let me know.
&a is a number which is an rvalue: you can store it somewhere if you want to in a variable you will have declared or allocated, of type int*.
To wit:
int a = 42;
&a; /* this does not store the address of a because you've not assigned the value to a variable */
int **aptr = &a; /* aptr is on the stack */
int **aptr2 = (int*)malloc(sizeof(int*));
aptr2 = &a; /* aptr2 is in the heap */
&(&a) is not legal syntax.
If you want a pointer to a pointer to an int:
int b = 39;
int *bptr = &b;
int **ptr2bptr = &bptr;
You have to build up the levels of indirection.
With the above you can then do this if you want:
printf("%d\n", *aptr);
printf("%d\n", *aptr2);
printf("%d\n", *bptr);
printf("%d\n", **ptr_to_bptr);
Producing output of:
42
42
39
39
int* a;
This line simply declares a pointer to an integer. That pointer has a memory location, which you can get the address of using &a. & is an operator that returns the address of whatever it is run on. But if you do not assign this value anywhere, there is no further &-ing possible.
As to your question as to where &a is stored, most likely in a register. If you do not use the value, it will be immediately discarded. (And registers do not have memory addresses, which is why you cannot do &(&a))

Resources