简体   繁体   English

无法在C中分配指向基元的指针?

[英]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. 'a'这样的文字不是变量。

ISO/IEC 9899:2011 §6.5.3.2 Address and indirection operators ISO / IEC 9899:2011§6.5.3.2地址和间接操作符

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. ¶1一元&运算符的操作数应该是函数指示符, []或一元*运算符的结果,或者是一个左值,它指定一个不是位字段的对象,并且没有用register存储器声明 -类说明符。

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. 有几个回复说你只能获取命名变量的地址,但这并不完全正确:如果你使用的是C99或更高版本,你也可以获取复合文字的地址或复合文字的字段。 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 }); 示例: 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'. 并且在包含块的持续时间内,* c将等于'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. &'a'不起作用的原因是因为无法保证值甚至有地址。 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. 'a'不是变量。 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'). 在封面下,'a'实际上只是一个短整数(ASCII值为'a')。 So, it's the same as why you can't do this: 所以,它与为什么你不能这样做是一样的:

str[1] = &9;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM