指针/地址类型转换

16

我有以下变量:

char *p;
int l=65;
为什么下面的强制类型转换会失败?
(int *)p=&l;

并且:

p=&((char) l);

你所说的“没有工作”,具体指什么? - bmargulies
5个回答

27

类型转换的结果始终是rvalue。无法将rvalue赋值,这就是为什么您的第一个表达式无法编译的原因。无法获取rvalue的地址,这就是为什么您的第二个表达式无法编译的原因。

为了执行正确的类型转换,您必须按以下方式进行操作

p = (char *) &l;

这是在第二个表达式中正确执行的方法。它将int *指针转换为char *类型。

你的第一个表达式已经无法修复了。你可以尝试:

*(int **) &p = &l;  

但它最终所做的并不是真正的转换,而是将被char *指针占用的内存重新解释为int *指针。这是一个丑陋的非法技巧,大部分时间几乎没有实际价值。


嘿,我不明白你输入的 (int **) 是什么意思。 - user319824
指向指针的指针。正如那个答案所述,这只是一个丑陋的技巧。 - M. Williams
5
@AndreyT 我不会把那称为技巧或黑客行为。虽然丑陋但在嵌入式编程中是必要的!这是唯一的方法,可以实际强制已知地址的寄存器(通常定义为 0xE000ED28,对于Cortex M3 CFSR寄存器)成为LVALUE! Atmel 对 Cortex M3 CFSR 寄存器的定义为 (* (uint32_t*) 0xE000ED28)。这是必要的(因此不是黑客行为),但绝对很丑陋。您能否在您的答案中添加一些关于这方面的信息? - nonsensickle

6

正确的做法应该是:

int I = 65;
char* p = (char*)&I;

&I会给你一个指向Iint*,然后你将其转换为char*并分配给p

请注意,通常不应该在不相关类型之间进行指针转换。但是,在这种特定情况下,char*可用于访问任何对象,因此是安全的。


具体来说,根据C99 6.3.2.3.7规定,仅当所涉及的指针具有不同的对齐方式时,将一个类型的指针转换为另一种类型的指针的行为是未定义的。它继续说,当将对象的指针转换为字符类型的指针时,结果指向对象的最低地址字节。 - dreamlax
实际上,我在考虑C99 §6.5/7,其中详细说明了别名规则。转换指针可能不会导致未定义的结果,但访问所指向的对象可能会。 - James McNellis

3

(int *)&l

该行无法运行,因为一旦将p强制转换为(int*),结果就是一个匿名临时对象,这是一个rvalue而不是lvalue;因此,结果不能接收赋值,即使语言允许,你也会将值分配给转换后的p的临时复制品,而不是原始的p

p=&((char) l);

上述代码类似地无法运行;(char) l的结果是l强制转换为char类型的临时对象。因此,由于它是临时的,您无法获取其地址。

相反,您可以使用:

p = (char*) &l

0
问题在于,当您执行强制转换时(无论您正在执行的强制转换是否是一个好主意),强制转换表达式的结果是一个 rvalue。
rvalue 不能被赋值或取地址。

-1
在普通的 C 语言中,类型转换并不那么严格,这段代码可以编译并正常工作。但在 C++ 编译器中,就需要像其他答案中提到的那样进行显式转换。

1
不,它在普通的C语言中也不起作用。强制转换运算符的结果就像+的结果一样 - 你不能做&((char)l),原因和你不能做&(a + b)一样。 - caf
嗯,我不知道为什么,但是msvs2008编译了这段代码,并且调试显示它实际上可以工作。奇怪。 - M. Williams
@CostantinoRupert:来自未来8年的问候!也许msvs2008允许将强制转换作为lvalue作为语言扩展。在“纯C”中肯定是无效的。 - Keith Thompson

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接