【问题标题】:cast 'char *' to 'signed char *'将 'char *' 转换为 'signed char *'
【发布时间】:2013-06-10 06:22:23
【问题描述】:

在 C 中将 char * 类型转换为 signed char * 是否有任何危险,其中 char 数组被解释为字节数组。

我在 gcc 中读到过,char 类型可以是无符号的,也可以是有符号的,具体取决于系统。在“最坏”的情况下,char * 将是 unsigned char *,但由于数组只是被解释为一系列位,因此类型从无符号变为有符号并不重要。

(顺便说一句,我检查了其他帖子,但我只看到了问题:将unsigned char 转换为signed char,我想知道普通char 是否有任何独特之处。提前致谢。 )

【问题讨论】:

  • 我认为如果您将其用作二进制数据,这不是问题,但如果您将其解释为数值,则。跨度>

标签: c type-conversion


【解决方案1】:

有一些边缘情况在赋值后进行比较,但是对于存储和交给不同的功能,没有任何危险......

在你的实现中,char 可能默认是有符号或无符号的......

比较和签名问题的示例:

在 c99 中带有 clang 的 MacOS X 上

char * dog = malloc(1);
dog[0]= 0xff;
unsigned char * mansBestFriend = dog;

if (mansBestFriend[0] > dog[0]) {
    puts("boy that is strange");
}

输出:奇怪的男孩

由于 C 中的比较规则有时令人困惑,因此比较的发生方式可能看起来很奇怪。

还有很多其他时候会发生这种情况,而我永远记不起的情况是其中一个值大于另一个值,一个有符号而另一个没有......它是如果您要比较不同的类型,最好将其强制转换为显式。

【讨论】:

  • sizeof(char)sizeof(signed char)sizeof(unsigned char) 都是1
  • 你的“奇怪”行为也与 ABI 无关——只是标准的 C 类型提升规则。
  • 是的,你可能是对的......虽然它可能会受到 ABI 的影响,因为 long 和 int 可以是相同大小或不同大小,因此遵循不同的规则。
  • 但这仍然是 C 实现的一部分,而不是 ABI。
  • 不,这取决于 C 实现。我承认经常存在一些相互关系。
【解决方案2】:

不,这样做没有危险,因为您只想将它​​用于其字节值。

【讨论】:

    【解决方案3】:

    强制转换本身应该没有任何问题,尤其是当您只是将数组解释为字节时。在这种情况下,我建议您考虑使用 C99 类型 uint8_tint8_t 来更好地传达您的意图,如果它们可供您使用的话。

    【讨论】:

    • +1 建议使用正确的类型来明确显示其背后的意图。
    • int8_t 可能不可用。 signed char 非常适合“签名字符”的意图......
    • 我确实说过“如果您可以使用它们”。显然,这取决于您的环境。当它们不可用时,另一种方法是使用预处理器定义或typedef 来阐明您想要用于原始数据字节的表示。
    • 是的,我知道有些人必须编写符合 C89 的代码,但它通常用于库,而处理此类事情的库通常有自己的类型... APR、OpenGL、和 SQLite 浮现在脑海中。
    【解决方案4】:

    没有危险,明确允许在所有三种 char 类型中重新解释 char 指针,还可以将 any 对象指针重新解释为 char 指针(因此将任何对象视为字节数组)。

    【讨论】:

    • 强制转换本身没有危险,但如果以后的代码依赖于一种或另一种符号扩展行为,则可能存在危险。
    • @CarlNorum:当然,但我认为 OP 有一个理由让她想要一个签名的字符,因此知道......
    • 是的,当然。我只是想把它放在那里。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-04-11
    • 2018-10-31
    • 2010-10-12
    • 2021-04-29
    • 2013-10-18
    • 2012-01-15
    • 2020-11-25
    相关资源
    最近更新 更多