我正在使用 Linux 中的 C 语言进行一些串行通信。我正在使用文件描述符来执行此操作。之后由于某种原因char* s = "Hello world"
,我可以s
使用write方法写入串口,没问题。我正在使用串行监视器程序来检查另一端。但是,我无法发送任何其他类型的数据。我从写入函数中收到“错误地址”错误。
但是,我注意到如果我做了一些非常奇怪的事情:int* x = "5";
那我可以发送 this x
。我的问题是,这到底是什么int* x = "5"
意思?
我正在使用 Linux 中的 C 语言进行一些串行通信。我正在使用文件描述符来执行此操作。之后由于某种原因char* s = "Hello world"
,我可以s
使用write方法写入串口,没问题。我正在使用串行监视器程序来检查另一端。但是,我无法发送任何其他类型的数据。我从写入函数中收到“错误地址”错误。
但是,我注意到如果我做了一些非常奇怪的事情:int* x = "5";
那我可以发送 this x
。我的问题是,这到底是什么int* x = "5"
意思?
int* x = "5";
这不是有效的 C 代码。您必须将数组的值转换为 anint *
但指针的取消引用仍然会破坏对齐规则并且是未定义的行为。
int *x = (int *) "5";
最后一段代码存储了一个类型为 的未命名数组对象char [2]
。的值"5"
是指向其第一个元素的指针,指针是 a char *
。强制转换将 转换char *
为 an int *
并将其存储在x
.
int* x = "5";
是违反约束的。这意味着任何符合标准的编译器都必须为其发出诊断。不必将其视为致命错误;允许编译器发出警告,然后成功翻译程序。但是语言没有定义这个声明的行为。
没有从char*
("5"
衰减后的类型)到的隐式转换int*
。
这就像 C 说某事是非法的一样接近。
实际上,接受此声明的编译器可能会将其视为等同于:
int *x = (int*)"5";
即,他们将插入转换。(这不是唯一可能的解释,但大多数编译器要么以这种方式解释它,要么拒绝它。)它采用char*
数组表达式衰减产生的值"5"
(即,'5'
字符开头的地址字符串),并转换为int*
.
结果int*
指针指向一个int
可能有效也可能无效的对象。该字符串"5"
有两个字节长 ( { '5', '\0' }
)。如果int
是两个字节,*x
则可以评估将这两个字节解释为一个int
值的结果——这将取决于系统的字节序。或者,如果字符串文字未正确对齐int
对象,则评估*x
可能会终止您的程序。如果int
大于两个字节(通常是这样),*x
是指超过字符串文字末尾的内存。在任何情况下,尝试修改*x
都有另一种未定义的行为,因为尝试修改字符串文字是明确未定义的。
当您编译该声明时,您至少应该得到一个警告。如果是这样,你绝对不应该忽略它。如果您没有收到警告,您应该了解如何哄骗您的编译器产生更多警告。
TL;DR:不要那样做。
int* x = "5"
"5"
将(a )隐式转换const char*
为 anint*
并将其存储在x
. 因此,x
将指向sizeof(int)
最低为 0x35(字符 '5')的字节,下一个为 0,其余的都是不确定的,并且在读取时会导致未定义的行为。