我想知道为什么这可以编译:
#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;
}
虽然不能:
#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
答案 0 :(得分:9)
稍微简单一点,你只能取一个变量的地址;像'a'
这样的文字不是变量。
ISO / IEC 9899:2011§6.5.3.2地址和间接运营商
约束
¶1一元
&
运算符的操作数应该是函数指示符,结果是[]
或一元*
运算符,或指定不是位字段的对象的左值 未使用register
存储类说明符声明。
标准的引用意味着您可以使用:
&array[i]
&*ptr
&function
或变量,或结构或联合类型的成员:
&var
&ptr->member
&obj.member
等
答案 1 :(得分:7)
有几个回复说您只能获取命名变量的地址,但这并不完全正确:如果您使用的是C99或更高版本,您还可以获取复合文字的地址或复合文字的字段。通常这对于例如调用一个函数,该函数接受指向某个结构的指针,您只需要在调用期间创建该结构。示例:draw(&(struct point){ 5, 10 });
可以通过一些途径获取标量的地址[编辑解释]:
// 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;
在包含块的持续时间内,* c将等于'a'。
然而,使用复合文字获取文字地址的更简单和更常见的方法只是声明一个只有一个元素的数组文字,它会像往常一样在赋值时衰减为指针:
char *c = (char[]){'a'};
这是相当典型的工作语法。但事实证明,该语言允许我们做一些更直接和稍微不直观的事情:我们可以声明一个标量类型的复合文字。这减少了上面的一切,更明显:
char *c = &(char){'a'};
在你的情况下,
#include <stdio.h>
int main(int argc, char const* argv[])
{
char *str[3];
str[1] = &(char){'a'};
return 0;
}
它比'&amp;'更加冗长实际上只有少数几个键比分配一个临时变量少,但它就是。
答案 2 :(得分:5)
问题是运营商的地址仅适用于名称。
char character = 'a';
str[1] = &character;
应该可以正常工作。
&'a'
不起作用的原因是因为无法保证值甚至具有地址。它可以直接从代码页加载到寄存器中,在这种情况下它不在可引用的内存中,或者至少不在你 应该解除引用的内存中。
答案 3 :(得分:1)
第一个片段工作正常,因为您正在获取变量的地址。
在第二个代码段中: -
str[1] = &'a';
这不是正确的方法。 'a'不是变量。和运营商的地址运营商在名称上工作。 如果你想要这个,那就改变它: -
char c = 'a';
str[1] = &c;
答案 4 :(得分:1)
正如乔纳森所说,你只能取一个变量的地址。在封面下,'a'实际上只是一个短整数(ASCII值为'a')。所以,这与你不能这样做的原因相同:
str[1] = &9;