Are these two methods for setting pointers equal to each other the same?

I am curious if I have two pointers

int *x = (int *)malloc(sizeof(int)); int *y; 

and I want y to specify the address x, is

 y = x; 

same as

 y = &*x; 

?

+4
source share
7 answers

Your question has two parts, and it is worth noting that they are not true:

First you ask:

is an
y = x; Same as
y = & * x;

Since dereference operators ( * ) and address-of ( & ) have the same precedence , they will bind the rights to the left, therefore

 y = &*x; 

matches with:

 y = &(*x); 

And yes, it will give the same effect as y=x; Now, if you have a C-compatible compiler that follows the letter of the law, it will not only be just as efficient, it will be the same, it should be to section C.3 specification 6.5.3.2 P3:

Unary and operator gives the address of its operand. If the operand is of type type '', the result is of type '' pointer to type.

If the operand is the result of a unary * operator, neither that operator nor the operator is evaluated, and the result looks as if both were omitted

So, the compiler will see * and & together and completely omit them.


In the second half of your question, you stated:

I want y to point to the address of x

Presumably you know that this is not what you are doing, but you are setting y instead of pointing to the same address as x . x , of course, has its own address and can be set, but you need another variable int **y = &x; assuming x is a valid value to be dereferenced.

+8
source

They are functionally equivalent. This is actually a “shallow copy”.

So, the following appointments achieve the same end result:

 y=x; y=&(*x); 

However, it will take longer to complete the second operation, because instead of directly assigning it, you perform an indirect and then an address operation. The compiler can simply optimize this to y=x anyway, depending on your system.

Edit:


As a note below, if your compiler supports standard C, including 6.5.3.2 P3 of standard C, this will definitely be optimized, probably at the pre-processor level, before the code is even compiled.

+4
source

They either exactly match by definition, or almost the same, depending on the version of C version you're dealing with.

In ISO C99 and C11 we have the following wording (quoting N1570 draft C11) in 6.5.3.2:

The unary operator & gives the address of its operand. If the operand is of type type, the result is of type pointer to type. If the operand is the result of the unary operator * , neither that of the operator or operator & , and the result will be as if both were omitted, except that the restrictions on the operators are still applied, and the result is not a value of l.

So, given:

 int *x = /* whatever */; int *y; 

these two are exactly equivalent, even if x is a null pointer:

 y = x; y = &*x; 

Without the rule of a special case, the behavior will be undefined, since the behavior of the * operator is determined only if its operand is a valid non-empty pointer. But since * never evaluated, he has no behavior here, definite or otherwise. (The fact that, unlike x , &*x not an lvalue, does not matter here.)

And in C89 / C90 this special case rule has not yet been added, therefore the behavior of &*x is undefined if x is a null pointer (or otherwise invalid). Most pre-C99 compilers will probably optimize the * and & ; remember that the nature of undefined behavior is that something can behave as you might expect it to behave.

On the other hand, there is a very real difference in the behavior of anyone reading the code. If I see y = x; , my behavior should be thinking "Oh, this is the usual pointer assignment." If I see y = &*x; , my behavior is to think "Why did you write like that?" And change it to y = x; if I am able to do this.

+3
source

Yes, although the second looks like an entry for an obfuscation contest.

+2
source

Yes, they are the same, but very confusing.

You can verify this by following these steps:

 y = &(*x); printf("%p\n", (void*)x); printf("%p\n", (void*)y); 
+2
source

As far as I know, they are exactly equivalent. I will be surprised if some compiler treats them differently.

Due to the presence of & , *x will not be evaluated at all. Therefore, even if x is null, this will not lead to a failure / failure. (You can better check using the assembly.)

When we talk about assembly, it is not possible to compute * x (value) and then & (* x) (pointer). Therefore, the compiler will simply calculate the address * x without calculating the value * x.

We can also check more complex cases, for example &(a[10]) It just translates to a+10*sizeof(a[0]) in the assembly.

Another proof would be the offsetof macro, usually defined as:

 #define offsetof(st, m) ((size_t)(&((st *)0)->m)) 

Here it computes &(null_pointer->m) , which does not cause a crash.

+1
source

Here is a small handy feature that might help. Not sure if you need everything "included".

 #include <stdio.h> #include <stdlib.h> #include <iostream> #include <string> #include <typeinfo> using namespace std; int main() { int *x = (int *)malloc(sizeof(int)); int *y = x; int *z = &*x; //y = x; //z = &*x; cout << "x has type: " << typeid(x).name() << '\n' << "y has type: " << typeid(y).name() << '\n' << "z has type: " << typeid(z).name() << '\n' << "values are " << x <<" "<< y << " " << z << '\n'; } 

The result obtained from this:

 x has type: Pi y has type: Pi z has type: Pi values are 0x1a3a010 0x1a3a010 0x1a3a010 

Then the answer: Yes, the methods are exactly the same as Ubuntu 14.10, g ++

-1
source

Source: https://habr.com/ru/post/1484233/


All Articles