简体   繁体   中英

Can't assign a pointer to primitive in C?

I am wondering why this can 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;
}

while this cannot:

#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

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

ISO/IEC 9899:2011 §6.5.3.2 Address and indirection operators

Constraints

¶1 The operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.

The quote from the standard means that you can use:

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

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

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

Etc.

Several replies say that you can only take the address of named variables, but that's not entirely right: if you're using C99 or greater, you can also take the address of a compound literal or a field of a compound literal. Usually this is useful for eg calling a function that takes an in pointer to some struct, which you only need to create for the duration of the call. Example: draw(&(struct point){ 5, 10 });

Some avenues by which this could be used to obtain the address of a 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 equal 'a'.

However the terser and more common way of obtaining an address to a literal using compound literals is simply to declare an array literal with only one element, which will decay to a pointer as usual on assignment:

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

And this is fairly typical syntax for the job. But as it turns 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 everything 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;
}

It's a little more verbose than '&' and in fact only a few keys less than assigning a temp variable, but there it is.

The problem is that the address of operator only works on names .

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

should work just fine.

The reason why &'a' doesn't work is because there is no guarantee that a value even has an address. It may be loaded directly from the code pages into the register, in which case it is not in reference-able memory, or at least doesn't lie in the memory that you should be dereferencing.

The first snippet is working fine as in that you are taking the address of the variable.

In the second code snippet:-

str[1] = &'a'; 

This is not the correct way. 'a' isn't a variable. and address operator of operator works on names. If you want this to work then change it like:-

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

As Jonathan said, you can only take the address of a variable. Under the covers, that 'a' is really just a short integer (ASCII value of 'a'). So, it's the same as why you can't do this:

str[1] = &9;

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