简体   繁体   中英

address operator and array in assembly level

Q1: The address operator takes the address of that variable. for example:

int var1;
int *p;
p = &var1;

Program takes the address of var1 to variable p at line 3.

Does it mean that CPU creates a space for putting address of var1(due to address operator), and then gives it to p?

Q2: the code below:

int A[3]= {2, 4, 6};

int *p = A;

printf("%d\n", p);
printf("%d\n", *p);

prints value of p and dereferencing value of p(value of A[1]), and is equivalent to:

int A[3]= {2, 4, 6};

printf("%d\n", A);
printf("%d\n", *A);

The first example in Q2 is very clear to see that CPU creates another variable p to store address of A.

Does the second example do the same thing in CPU except creating one more variable p?

Thanks

The CPU doesn't "create variables". You could say the compiler creates space on the stack for variables through the choice of instructions it uses, or in static storage with assembler directives to reserve space in the .data , .rodata , or .bss sections.

You'll see more or less what you expect if you put that code on http://godbolt.org/ with optimization disabled ( -O0 ), ie the actual asm for x86, ARM, or whatever, will reserve space for every variable that exists in the C abstract machine, and actually store the values there.

But in real code compiled normally ( -O2 or -O3 ) the compiler takes advantage of the "as if" rule, which lets it emit whatever asm instructions it decides will produce the same observable behaviour as the C source, including optimizing away int *p entirely and doing the equivalent of printf("%d\\n", 2); . Passing the address A to an external function like printf will probably cause the compiler to actually create that array on the stack, though. But you never take the address of p itself, so there's no reason for p to exist in memory.

I'm afraid you are mistaking two things here:

  • the use of address operator & .
  • the use of arrays in C.

The address of & operator allows you to construct a pointer to value from a variable of same type as value. That means that, when you write:

p = &var1;

C gets the address of variable var1 and stores that value into pointer variable p .

When you refer to an array by name, the value you get is the address of the first element, so

int *p = A;

is the same as take the address of the first element of A and assign that value to the pointer to int variable p .

When you do:

int *p = &A;

you are doing an assignment from a pointer to array of int into a variable of type array of int , which is a different type. Historically, the compiler automatically converted the type and didn't give any indication, but as it is incorrect, it can confuse more than one. It gives a warning on my compiler, although:

$ make pru2.o
cc -O -pipe -c pru2.c -o pru2.o
pru2.c:5:6: warning: incompatible pointer types initializing 'int *' with an expression of type 'int (*)[20]'
      [-Wincompatible-pointer-types]
int *q = &A;
     ^   ~~
1 warning generated.

This is manifested in the code you post later:

printf("%d\n", A); /* this is the same ass &A[0] */
printf("%d\n", *A); /* dereference that, as *(&A[0]) == A[0] */

Here, it is important (when using arrays) to differentiate clearly that

&A

and

A

Are different expressions, that give (normally, as thinking otherwise is Undefined Behaviour) the same address value, but as a pointer to different type.

&A  

is the address of array A , and as such is defined as type

int (*)[sizeof A / sizeof A[0]]

while

A

represents the address of the first element of A , and as such it is defined as type

int *

(pointer to int ) This can be shown, by simply printing the sizes of the pointed to dereferences, as in:

int A[20];

...

printf("sizeof *(&A) == %z\n", sizeof *(&A));

and

printf("sizeof *A == %z\n", sizeof *A);

(the first will give you the size of the complete array, demonstrating that the address of an array A is a pointer to an array of 20 int s, while the second will give you the size of the first element of A , demonstrating that it points to a single int element)

In general, arrays are used in a very limited way in C, as they are assimilated to pointers in many situations, they cannot be passed by value ---using the array name as a parameter to a function passes a pointer to the first element, using the address of the array makes the compiler to pass the same value, but as a pointer to array of n elements--- this will be treated as a simple pointer value by the called function, as the unspecified array suffix [] will be converted into a pointer definition by the compiler.

Q1: No, the address operator is not the reason why var1 has space on the stack. Whenever you declare any variable "locally", the "computer" allocates memory on the stack for that variable.

Q2: Yes. Note that in certain conditions, you can interchange an array and a pointer. That is, for int [] my_array and int * ptr , *my_array and *ptr will both give you the first element of the array

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