8

I have a pointer and a variable:

int *a;
int b;

Is there any difference between assignments

a = &b;

and

*a = &b;

and what are they called (like pointer declaration or something) ?

Pavel
  • 5,374
  • 4
  • 30
  • 55
Sumit Ramteke
  • 131
  • 1
  • 4

11 Answers11

19

Types matter.

  • In case of a=&b, the assignment is valid. You're assigning the address of an integer (type: int *), to another variable of type int *, so this is legit.

  • In case of *a=&b, this is a constraint violation (for assignement operator, see chapter §6.5.16.1/p1, Constraints, for Simple assignment) and thus not a valid C syntax, thus not required to be compiled by any conforming compiler. To make it a valid C syntax, we need to enforce a typecast, something like

    *a= (int) &b;
    

    would make it a syntactically valid C statement which meets the required constraint.

    Even, after that, the result is implementation defined.#note Here, you're basically trying to assign the the address of an integer (type: int *) to another variable of type int (*a is of type int). Conversion from a pointer to integer is implementation defined behaviour.

    Quoting C11, chapter §6.3.2.3, Pointers

    Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. [....]

[....] And what are they called?

They both are assignment statements.


Note:

Considering a points to a valid memory location already. Otherewise, dererefencing an invalid pointer invokes undefined behavior on it's own.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • but isn't that UB too? – user2736738 Jan 02 '17 at 09:21
  • 1
    @coderredoc - UB is not the same as implementation defined result. One means your processor can blow up, the other just means you'll get something, but can't predict what it is. – StoryTeller - Unslander Monica Jan 02 '17 at 09:22
  • 1
    I get a [compile-time error](http://coliru.stacked-crooked.com/a/8453645df34d5f4d) with Clang -- are you sure an `int*` can be implicitly converted to an `int` ? – Quentin Jan 02 '17 at 09:24
  • @Quentin - Your warning as errors flags may have something to do with it. As quoted, the C standard doesn't require a diagnostic here. – StoryTeller - Unslander Monica Jan 02 '17 at 09:26
  • Yes, that's the default file. `-x c` takes care of explicitly using the C front-end. The flags only enable a bunch of warnings, `-Wfatal-errors` makes compilation stop at the first error (not to be confused with `-Werror`), and `-pedantic-errors` disables extensions. – Quentin Jan 02 '17 at 09:26
  • @Quentin OK, thanks for the info. One more note, the `-Wint-conversion` options is for generating _warning_, isn't it? Unless we choose to treat the warnings as errors, I don't see any reason to abort the compilation. Any idea on that? – Sourav Ghosh Jan 02 '17 at 09:32
  • @Quentin - Disabling [`-pedantic-errors`](http://coliru.stacked-crooked.com/a/1f3e0947f09557a9) leaves this as a warning. And from reading the description of this option, somebody seems to have misread the standard. Unless of course there is a diagnostic required here, which Sourav omitted from the quote. – StoryTeller - Unslander Monica Jan 02 '17 at 09:34
  • @Quentin - In actuality, `-pedantic-errors` is even stricter than the base standard. I quote from [GCC's manual](https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html) *"in some cases where there is undefined behavior at compile-time and in some other cases that do not prevent compilation of programs that are valid according to the standard."* – StoryTeller - Unslander Monica Jan 02 '17 at 09:38
  • `warning: incompatible pointer to integer conversion assigning to 'int' from 'int *'; remove & [-Wint-conversion]`, compile without error just warning. – Stargateur Jan 02 '17 at 09:40
  • So apparently this is `-pedantic-errors` being overzealous. @StoryTeller I can't see any UB in here. Should I create a new question ? – Quentin Jan 02 '17 at 09:42
  • @Quentin - Perhaps you should. I for one would be very interested to know why GCC deems it UB. If there is no valid reason, than it is a compiler bug. – StoryTeller - Unslander Monica Jan 02 '17 at 09:50
  • @SouravGhosh I'm reading through [N1570](http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf) (C11 draft) right now. From 6.3: "This subclause specifies the result required from such an implicit conversion, as well as those that result from a cast operation (an explicit conversion).". 6.5.16.1 (Simple Assignment) contains a list of which implicit conversions are allowed in an assignment, and pointer-to-int is not listed. Thus I think GCC's `-pedantic` is right: the conversion has to be explicit. – Quentin Jan 02 '17 at 10:11
  • @StoryTeller I think the processor can also blow up in the implementation-defined case, as long as the document for that crazy implementation says "assigning a pointer to an integer would blow up your processor" What a cool feature! :) – nalzok Jan 02 '17 at 11:01
  • @Quentin I did re-read the standard and you are quite right. Let me update the answer. – Sourav Ghosh Jan 02 '17 at 11:02
  • 2
    @SunQingyao - You are mistaken. If the standard defines a value change with implementation defined results, it does not give an implementation leeway to perform anything except a value change. Like I said, UB is much less strict on an implementation. – StoryTeller - Unslander Monica Jan 02 '17 at 11:04
  • Conversion between pointer and integer are always explicit. GCC warning is correct. – haccks Jan 02 '17 at 11:15
  • @haccks Sir, you mean to say we need that explicit typecast to make it _valid_, right? – Sourav Ghosh Jan 02 '17 at 11:17
  • @SouravGhosh; Yes, exactly. `int` and `int *` are different incompatible types. You can say same for different functions pointers. In case of function pointers implicit conversion is not performed. – haccks Jan 02 '17 at 11:19
8

Pay attention to types on the left and on the right of =.

&b is int *, a is also int * but *a is int.


It's a bit confusing that * has different meanings:

int *a; — here * means that a will be a pointer;

*a = ...; — here * means that we change not address stored in a but value which is located at the address.


So a = &b means "write the address of b to a",

but *a = &b means "write the address of b to *a, i.e. to the address which is stored in a".


Let's suggest that we have this situation:

   Address  Value
 a 0x0001   0x0004
 b 0x0002   70
   0x0003   80
   0x0004   90

At the moment a is 0x0004 and *a is 90.

If you do a = &b, a will be 0x0002 and *a will be 70.

But if you do *a = &b, a will not change, but *a, i.e. value at the address 0x0004, will change to 0x0002.

Pavel
  • 5,374
  • 4
  • 30
  • 55
3

One notable difference is that second assignment is ill-formed C (because of constraint violation):

*a = &b;

error: assignment makes integer from pointer without a cast [-Wint-conversion]

C11 §6.5.4/3, Cast operators:

Conversions that involve pointers, other than where permitted by the constraints of 6.5.16.1, shall be specified by means of an explicit cast.

The requirement of explicit cast was introduced in C89, in order to to disallow bad practice of implicit conversion between integer and pointer types.

The only exception to this rule is that you can assign pointer value with 0 integer constant, which represents null pointer constant:

a = 0; // more idiomatically: a = NULL;
Grzegorz Szpetkowski
  • 36,988
  • 6
  • 90
  • 137
3

Given the types, the following assignments would be valid:

 a = &b; // int * = int *
*a =  b; // int   = int

In the second case, a must point to a valid memory location or the behavior is undefined.

*a = &b;  // int = int *

is a constraint violation and the compiler will yell at you.

John Bode
  • 119,563
  • 19
  • 122
  • 198
3

Is there any difference between assignments

a = &b;

and

*a = &b;  

Yes. In first case, a and &b (address of b) both are of type int *. They are assignable.
In case of *a = &b, *a is of type int while &b is of type int *. Bothe types are incompatible and type of &b is not converted explicitly to the type of *a. This is a constraint violation. That being said: int types are not capable of holding pointer objects. The only integer types that are capable of holding pointer object are intptr_t and uintptr_t.

7.20.1.4 Integer types capable of holding object pointers

1 The following type designates a signed integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

intptr_t  

The following type designates an unsigned integer type with the property that any valid pointer to void can be converted to this type, then converted back to pointer to void, and the result will compare equal to the original pointer:

uintptr_t

These types are optional.


and what are they called (like pointer declaration or something) ?

They are assignment statements.

haccks
  • 104,019
  • 25
  • 176
  • 264
3

Like all the other answers have already pointed out, given the variables int *a and int b:

  • the assignment a = &b is valid (and assigns the address of b to the pointer a, so that *a can be used to access b), whereas
  • the assignment *a = &b is a constraint violation, since it tries to assign the address of b to the integer pointed to by a, which is not allowed without an explicit cast.

What might be confusing you, however, is that the variable declaration:

int b;
int *a = &b;

is valid, and does exactly the same thing as:

int b;
int *a;
a = &b;    // not *a = &b!

That's a very convenient shorthand, since you nearly always want to initialize a variable as soon as you declare it (if only to make sure that you don't accidentally try to use it before it's initialized). But it can be confusing when you first encounter that syntax, since it looks as if you're assigning &b to *a, when it's actually a itself that is getting initialized with the value &b. This is just something that you'll have to learn: variable initialization is not the same as normal assignment, even though it looks confusingly similar.

Community
  • 1
  • 1
Ilmari Karonen
  • 49,047
  • 9
  • 93
  • 153
  • This potential confusion is precisely why I prefer writing `int* a = &b;` to make sure that `a` is of type `int*` and gets assigned the address of `b`. – David Zwicker Jan 02 '17 at 19:23
  • 1
    @DavidZwicker: That's one way to highlight the difference, although it comes with its own pitfalls: `int* a, b` does *not* declare two variables of type `int*`! Also, it doesn't work so well for more complex things like pointers to arrays or functions (although you can always `typedef` those). – Ilmari Karonen Jan 03 '17 at 03:45
  • Agreed! I guess the cleanest solution is to typedef pointers, but that might be overkill (and actually harm readability) in simple cases. – David Zwicker Jan 03 '17 at 14:20
2

The first, int a = &b; copies the address of the variable "b" to the "a".

The second, int *a = &b; copies the address of the variable "b" to the location "a" points to.

  • For the second line, you say "copies the address of the variable "b" to the location "a" points to," but where does `a` point to? (This is my way of saying your explanation of the second line couldn't possibly be right and the behavior of the second line is actually to initialize `a` so it points to `b`; that is, afterwards you have `a==&b`.) Here is a [reference](http://www.cplusplus.com/doc/tutorial/pointers/#initialization) – Brian Moths Jan 02 '17 at 16:35
1

First one is ok but second one invokes UB. ( Unless a is pointing to some valid memory)

user2736738
  • 30,591
  • 5
  • 42
  • 56
1

Sure there are differents between them
& represent pointer(from pointer you can get value)
* represent value
a=&b (represent a equal point of b)
*a=&b(represent value a equal point of b)

Helped Tutorial

Aya Aboud
  • 371
  • 2
  • 4
  • 16
1

First let me clear you the difference between integer variable and pointer variable:

(1) Integer variable ( e.g: int b, in this case ) is used to store the value of an integer ( of length 4 bytes ). The value of 'b' gets stored in some memory location ( say 0x00000001 ).

(2) Pointer variable (e.g: int * a, in this case) is used to store the memory location of an integer variable. That is, in 'a' we can store the address of an integer variable. The value pointed by a pointer variable can be dereferenced by using ' * ' operator. So 'a' will have the address and ' *a ' will have the value pointed by the value (address) contained in a.

Now answering to your question:

Let's assume that b = 4 and address of b ( &b ) is 0x00000001 ( hexadecimal notation ).

In first type assignment a = &b, the address of variable integer b gets stored in a ( since a is a pointer variable ). Now 'a' has the value 0x00000001 and ' *a ' will have 4.

In second type assignment *a = &b, the address of variable b gets stored in the memory location pointed by a, i.e, in 0x00000001 memory location will have the value 0x00000001 itself. Now 'a' has the value 0x00000001 and ' *a ' will also have the same value 0x00000001.

LearningC
  • 11
  • 1
1
int *a;
int b;

Is there any difference between assignments `a = &b` and `*a = &b`.

Any variable var of type T has some location in memory, whose adress is either allocated by the compiler or by the static or dynamic linkers. The adress of some variables can be obtained by &var and has the type pointer to T. So, when you apply the & operator you nest the type inside another pointer. a=&b is correct.

On the other hand, *a=&b is not correct. You try to store in the variable *a (that has type int) a pointer to the base address of the variable b (that has type pointer to int). In the architectures where the pointer has 64 bits and int has 32 bits this will lead to failure. On the other hand, on the architectures where pointer and int have the same length, this is possible if you insert a cast. The compiler will not automatically insert a coercion from int* to int.

alinsoar
  • 15,386
  • 4
  • 57
  • 74