Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can't assign a pointer to primitive in C?

Tags:

c

pointers

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
like image 710
qed Avatar asked Aug 09 '13 21:08

qed


People also ask

Is a pointer a primitive type?

Pointer can also be referred to as a primitive data type that can be used to store the address of another variable. Pointers can store the address of other primitive and non-primitive data types as well. Pointer is supported by languages like C and C++.

Can you assign a pointer to an int?

This is the best way to attach a pointer to an existing variable: int * ptr; // a pointer int num; // an integer ptr = &num; // assign the address of num into the pointer // now ptr points to "num"!

Can you assign a pointer to a reference?

You can assign pointers to "point to" addresses in memory. You can assign references to "refer to" variables or constants. You can copy the values of pointers to other pointers.

How do you declare a pointer in C?

The * symbol indicates that the variable is a pointer. To declare a variable as a pointer, you must prefix it with *. In the example above, we have done a pointer declaration and named ptr1 with the data type integer.


2 Answers

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.

like image 89
Jonathan Leffler Avatar answered Sep 22 '22 05:09

Jonathan Leffler


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 e.g. 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.

like image 27
tab Avatar answered Sep 22 '22 05:09

tab