我想知道为什么这可以编译:
#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;
}
Run Code Online (Sandbox Code Playgroud)
虽然这不能:
#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
Run Code Online (Sandbox Code Playgroud)
简单地说,你只能取一个变量的地址; 字面意思'a'不是变量.
ISO/IEC 9899:2011§6.5.3.2地址和间接操作符
约束
1一元运算
&符的操作数应该是函数指示符,[]一元或一元运算*符的结果 ,或者是一个左值,它指定一个不是位字段且未使用register存储类说明符声明的对象.
标准的引用意味着您可以使用:
&array[i]&*ptr&function或变量,或结构或联合类型的成员:
&var&ptr->member&obj.member等等.
有几个回复说你只能获取命名变量的地址,但这并不完全正确:如果你使用的是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;
Run Code Online (Sandbox Code Playgroud)
并且在包含块的持续时间内,*c将等于'a'.
然而,使用复合文字获取文字地址的更简单和更常见的方法只是声明一个只有一个元素的数组文字,它将像往常一样在赋值时衰减为指针:
char *c = (char[]){'a'};
Run Code Online (Sandbox Code Playgroud)
这是相当典型的工作语法.但事实证明,该语言允许我们做一些更直接和稍微不直观的事情:我们可以声明一个标量类型的复合文字.这减少了上面的一切,更明显:
char *c = &(char){'a'};
Run Code Online (Sandbox Code Playgroud)
在你的情况下,
#include <stdio.h>
int main(int argc, char const* argv[])
{
char *str[3];
str[1] = &(char){'a'};
return 0;
}
Run Code Online (Sandbox Code Playgroud)
它比'&'更冗长,实际上只比指定临时变量少了几个键,但确实如此.
问题是运算符的地址仅适用于名称.
char character = 'a';
str[1] = &character;
Run Code Online (Sandbox Code Playgroud)
应该工作得很好.
之所以&'a'不起作用的原因是因为无法保证值甚至具有地址.它可以直接从代码页加载到寄存器中,在这种情况下,它不在可引用的内存中,或者至少不在您应该解除引用的内存中.