这个(char*)&x cast的行为是否定义明确?

Joh*_*ith 6 c string casting character

在编写一些C代码时,我遇到了一个小问题,我必须将字符转换为"字符串"(一些内存块,其开头由char*指针给出).

我的想法是,如果sourcestr设置了某个指针(不是NULL),那么我应该将它用作我的"最终字符串",否则我应该将给定charcode转换为另一个数组的第一个字符,然后使用它.

出于这个问题的目的,我们假设变量的类型不能事先改变.换句话说,我不能只将我存储charcode为一个const char*而不是一个int.

因为我倾向于懒惰,所以我想:"嘿,我不能只使用角色的地址并将该指针视为字符串吗?".这是我写的一小段(不要把我的头撞到墙上!):

int charcode    = FOO;   /* Assume this is always valid ASCII. */

char* sourcestr = "BAR"; /* Case #1 */
char* sourcestr = NULL;  /* Case #2 */

char* finalstr  = sourcestr ? sourcestr : (char*)&charcode;
Run Code Online (Sandbox Code Playgroud)

现在我当然试过了,正如我所料,它确实有效.即使有一些警告标志,编译器仍然很高兴.但是,我有这种奇怪的感觉,这实际上是未定义的行为,我不应该这样做.

我认为这种方式的原因是因为char*数组需要以空值终止才能正确打印为字符串(我希望我的是!).然而,我不确定值&charcode + 1是否为零,因此我可能最终会出现一些缓冲区溢出的疯狂.

是否有一个实际的原因,它为什么它正常工作,或者我只是幸运在我尝试时在正确的地方得到零?

(请注意,我不是在寻找其他方式来实现转换.我可以简单地用一个char tmp[2] = {0}变量,并把我的角色在索引0我也可以使用像sprintf或者snprintf,只要我有缓冲区溢出不够细心.有无数的方法,我只是对这个特定的演员操作的行为感兴趣.)

编辑:我看到有几个人称这个hackery,我们要明确:我完全同意你的看法.在释放的代码中我实际上做这个是不够的受虐狂.这只是我好奇;)

Bat*_*eba 5

您的代码定义明确,因为您始终可以转换为char*.但有些问题:

  1. 请注意,这"BAR"是一个const char*文字 - 所以不要试图修改内容.那是不确定的.

  2. 不要尝试将其(char*)&charcode用作C标准库中任何字符串函数的参数.它不会以空值终止.所以从这个意义上说,你不能把它当成一个字符串.

  3. 指针算术(char*)&charcode 在标量之前有效且包括一个charcode.但是不要试图取消引用任何超出charcode自身的指针.的范围内n的量,表达(char*)&charcode + n是有效取决于sizeof(int).


Fra*_*e_C 0

这绝对是未定义的行为,原因如下:

  1. 可能性较小,但在严格引用标准时要考虑:您不能假设将编译代码的机器/系统上的 int 大小
  2. 如上所述,您不能假设代码集。例如,EBCDIC 机器/系统上会发生什么?
  3. 很容易说你的机器有一个小端处理器。在大端机器上,代码由于大端内存布局而失败。
  4. 因为在许多系统上char是一个有符号整数,int当您的 char 是负值时(即char>127在具有 8bits 的机器上char),如果您按照下面的代码分配值,则可能会由于符号扩展而失败

代码:

char ch = FOO;
int charcode = ch;
Run Code Online (Sandbox Code Playgroud)

PS关于第3点:在具有正值的小端机器中,您的字符串确实以NULL结尾sizeof(int)>sizeof(char)char,因为int的MSB将为0,并且这种字节顺序的内存布局是LSB-MSB(LSB在前)。