Can't assign a pointer to a primitive in C?

I am wondering why this might compile:

#include <stdio.h> int main(int argc, char const* argv[]) { char *str[3]; char x = 'a'; char *px; px = &x; str[0] = px; return 0; } 

until it can:

 #include <stdio.h> int main(int argc, char const* argv[]) { char *str[3]; str[1] = &'a'; return 0; } decla.c: In function 'main': decla.c:9:14: error: lvalue required as unary '&' operand 
+6
source share
5 answers

Several answers say that you can only use the address of named variables, but this is not entirely correct: if you use C99 or higher, you can also take the address of a complex literal or field of a complex literal. This is usually useful for, for example, calling a function that takes a pointer to some structure that needs to be created only at the time of the call. Example: draw(&(struct point){ 5, 10 });

Some ways in which this could be used to obtain the address of the scalar [edited with explanations]:

 // create a char array containing only 'a', dereference to get 'a', and take its address char *c = &*(char[]){'a'}; // same as above, but using an array subscript char *c = & (char[]){'a'}[0]; /* create a literal for one unnamed struct containing only the char member "c", access .c, and take its address all in the same statement */ char *c = &(struct{char c;}){'a'}.c; 

And for the duration of the containing block, * c will be equal to 'a'.

However, a terminator and a more general way of getting an address into a literal using compound literals is to simply declare an array literal with only one element, which, as usual, will decay to a pointer:

 char *c = (char[]){'a'}; 

And this is pretty typical syntax for a job. But, as it turned out, the language allows us to do something even more direct and slightly unintuitive: we can declare a compound literal of a scalar type. Which reduces all of the above to the more obvious:

 char *c = &(char){'a'}; 

In your case

 #include <stdio.h> int main(int argc, char const* argv[]) { char *str[3]; str[1] = &(char){'a'}; return 0; } 

This is a little more verbose than '&' and in fact just a few keys are less than assigning a temporary variable, but there it is.

+7
source

Put a little simplistically, you can only take the address of a variable; literally like 'a' not a variable.

ISO / IEC 9899: 2011 Β§6.5.3.2 Address and indirectness operators

Limitations

ΒΆ1 The operand of the unary operator & must be either the designation of the function, or the result of [] or the unary operator * or the value l, which denotes an object that is not a bit field and is not declared using the register class specifier.

A quote from the standard means that you can use:

  • &array[i]
  • &*ptr
  • &function

or a variable or member of a structure or type of union:

  • &var
  • &ptr->member
  • &obj.member

Etc.

+9
source

The problem is that the operator address only works with names.

 char character = 'a'; str[1] = &character; 

should work fine.

The reason &'a' does not work is because there is no guarantee that even the address matters. It can be loaded directly from the code pages into the register, in which case it is not in a reference memory state, or at least it does not lie in memory that you should be dereferencing.

+5
source

The first snippet works fine as you take the address of a variable.

In the second code snippet: -

 str[1] = &'a'; 

This is not the right way. 'a' is not a variable. and the operator operator address works with the names. If you want this to work, change it like this: -

  char c = 'a'; str[1] = &c; 
+1
source

As Jonathan said, you can only accept the address of a variable. Under the covers, β€œa” is actually just a short integer (ASCII value β€œa”). So this is the same as you cannot do this:

 str[1] = &9; 
+1
source

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


All Articles