【问题标题】:How to compare Signed Char to a literal constant?如何将 Signed Char 与文字常量进行比较?
【发布时间】:2015-10-09 19:21:39
【问题描述】:

API 提供了一个函数signed char getDirection();,返回 1 表示“前进”,0 表示“静止”,-1 表示“后退”。

当然,正如these questions 中所解释的,一个简单的比较:

    if(getDirection() == -1) { ... }

失败。好的,我明白为什么它失败了。但我就是找不到如何让它工作!我尝试将左侧投射到(int),将右侧投射到(signed char),仍然没有问题......

编辑:

 signed char a = getDirection();
 printf("%d\n",(int) a);
 printf("%d\n",(int) getDirection());

结果:

 -1
 255

edit2:每个请求:

const signed char getDirection(uchar d)
{
    if(d >= config.directional_inputs.channelCount) return -2;

    return shm->input_state.directional_inputs[d].direction;
}

【问题讨论】:

  • @AlexD:我希望。好吧,实际上测试语句的格式是printf("val: %d, comparison: %d", getDirection(), (getDirection() == DIRECTION_BACK) );,其中常量是#define DIRECTION_BACK -1
  • 您的代码是正确的。检查getDirection() 是否实际返回-1。显示您的printf 的输出。也显示你的实际代码,也许只有一个流浪的';'某处。
  • @MichaelWalz:输出:“val:-1,比较:0”。一位同事怀疑编译器错误。
  • @SF 你用的是什么编译器?确实很奇怪。
  • 嗯,你不是忘了在你的编译单元中包含一个 .h 或明确声明 const signed char getDirection(uchar d); 吗?

标签: c type-conversion


【解决方案1】:

这很奇怪。

首先,使用不同的编译器可能会有所不同。他们可能有不同的规则应该如何返回签名的字符。假设用于编译该函数的编译器假定有符号字符在 32 位寄存器中作为 8 位返回,其他位为零或未定义 - -1 返回为 00000000 00000000 00000000 11111111。调用的编译器假定有符号字符在 32 位寄存器中以 8 位返回,符号扩展,因此可以假定所有 32 位都包含正确的值。所以编译器认为结果是255。

其次,我看到了原型和函数不匹配的问题。如果某处的函数原型显示“char”而不是signed char,那将解释一切。由于问题很奇怪,我会向编译器询问预处理器输出并检查是否发生了任何奇怪的事情。

【讨论】:

  • 对于最近的或不错的编译器,标准很明确 6.3.1.1 §2-3 : 如果一个 int 可以表示原始类型的所有值(受宽度限制,有点-field),将值转换为int;否则,将其转换为无符号整数。这些被称为整数提升整数提升保留值,包括符号。如前所述,“普通”字符是否被视为有符号是实现定义的。但是符合 TCC 标准吗?什么版本的标准?
【解决方案2】:

似乎在GetDirection 中执行了return shm->input_state.directional_inputs[d].direction; 部分。 direction 元素的类型是什么?我不确定这里的促销活动,但如果是unsigned char,它可能只是被复制到返回寄存器ax 并返回。即不进行符号扩展,ax 为0x000000ffff 被分配给signed char a,这是正确的,当a 用于printf 调用时,它会得到正确的符号扩展。所以符号扩展必须在GetDirection的return语句中完成,显然没有完成。

尝试将其更改为return (signed char)shm->input_state.directional_inputs[d].direction;

【讨论】:

  • directionsigned char 都是一样的,它是分配链中的第一个,一旦输入端口组合成“向后”配置,就会得到文字 -1
  • 看起来GetDirection 仍然没有做符号扩展。用调试器检查一下。
【解决方案3】:

如果您确定 getDirection() 确实返回有符号字符,它应该可以工作,因为 0xff 的有符号字符应该正确提升为 -1 整数。

如果不确定,你可以尝试写

int dir = getDirection();
// optionnally for extensive tests : fprintf(stderr, "getDirection : %d\n", dir);
if ((dir == -1) || (dir == 255)) { ... }

255 会发现任何转换问题,例如 getDirection() 返回一个签名字符...您上次编辑的建议...

【讨论】:

  • @MichaelWalz:是的。但是我曾经不得不对返回 char 的库使用类似的东西,我不得不在 2 个平台上使用它,其中一个平台上 char 签名,另一个平台上未签名。我已经看到(写得很糟糕的)代码,其中 doc 说 signed char 并且代码只包含 char 因为程序员认为他在他的系统上拥有的东西(char = signed char)是标准,而标准说它是实现依赖。
  • @SergeBallesta:我个人的看法是,单独的“char”总是意味着一个 ASCII 字母。如果是数字,则必须表示为“有符号”或“无符号”。
  • @sf a char 不是 ASCII 字母,它是一个 8 位值。 char 单独是 unsigned char 或(大部分时间)signed char 取决于您的编译器。
  • @MichaelWalz:这取决于上下文。文字 'A' 是有符号还是无符号?我通过选择类型前缀来表示变量的内容 - 如果它是普通的 char,那么 printf() 的正确格式不是 %hhd 或 %hhu 而是 %c。
  • @SF。 : 对于最近的或体面的编译器,标准很明确 6.2.5 §15 : char、signed char 和 unsigned char 这三种类型统称为字符类型。实现应将 char 定义为与有符号字符或无符号字符具有相同的范围、表示和行为
猜你喜欢
  • 2020-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多