如何将有符号字符与文字常量进行比较?

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

当然,正如这些问题所解释的那样,简单的比较操作:

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

失败了。好的,我明白为什么会失败。但是我就是找不到如何使它工作的方法!我尝试将左侧转换为(int),将右侧转换为(signed char),但还是没有效果...

编辑:

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

结果:

 -1
 255

编辑2:按照要求:

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 - SF.
3
你的代码是正确的。检查一下 getDirection() 是否真的返回了 -1。展示一下你的 printf 输出结果。同时也展示一下你的实际代码,可能只是漏掉了一个分号。 - Jabberwocky
1
@SF 你在用什么编译器?确实很奇怪。 - Jabberwocky
1
嗯,你是不是忘了在编译单元中包含.h文件或明确声明const signed char getDirection(uchar d); - Serge Ballesta
一些编译器假定任何返回int参数的未声明函数与1970年代的K&R C兼容。但是如果您已经检查了任何内容,我会怀疑不符合规范的编译器(我不了解TCC,除了ooold Turbo C编译器)。 - Serge Ballesta
显示剩余7条评论
3个回答

0

GetDirection函数中,执行了return shm->input_state.directional_inputs[d].direction;这一部分。那个direction元素的类型是什么?我不确定这里是否有提升,但如果它是unsigned char,它可能会被复制到返回寄存器ax中并返回。也就是说,没有进行符号扩展,ax为0x000000ff。将ff赋值给signed char a是正确的,当aprintf调用中使用时,它会得到适当的符号扩展。因此,在GetDirection函数的返回语句中必须执行符号扩展,而显然没有执行。

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


“direction” 是 “signed char”,并且它是赋值链中的第一个,一旦输入端口组合成“向后”配置,它就会得到文字“-1”。 - SF.
看起来 GetDirection 函数仍然没有进行符号扩展。请使用调试器进行检查。 - Paul Ogilvie

0

这很奇怪。

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

其次,我曾经看到过原型和函数不匹配的问题。如果某个地方有一个函数的原型,它说“char”而不是signed char,那就可以解释一切了。由于问题很奇怪,我建议请求预处理器输出并检查是否发生了任何奇怪的事情。


对于最近或较新的编译器,标准是很清楚的6.3.1.1§2-3: 如果int可以表示原始类型的所有值(由位域限制宽度),则该值将转换为int;否则,它将转换为unsigned int。这些被称为整数提升整数提升保留值,包括符号。如前所述,“普通”字符是否作为有符号处理是实现定义的。但是TCC是否符合规范?以及哪个版本的标准? - Serge Ballesta

0
如果你确定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的库使用类似的东西,而我必须在两个平台上使用它,其中一个平台上的char是有符号的,另一个平台上的char是无符号的。我已经看到(糟糕编写的)代码,其中文档说“signed char”,但代码只包含“char”,因为程序员认为他在自己的系统上拥有的内容(char = signed char)是标准,而标准则表示这是实现相关的。 - Serge Ballesta
@sf char 不是 ASCII 字母,它是一个8位值。char 单独使用时是 unsigned char 或(大多数情况下)取决于编译器的 signed char - Jabberwocky
@SF. : 对于最近或较新的编译器,标准很明确6.2.5 §15: 字符类型可以分为三种:char、signed char和unsigned char。实现必须定义char的范围、表示和行为与signed char或unsigned char相同 - Serge Ballesta
假设 CHAR_BIT==8,不存在“signed char of 0xff”。signed char 的范围是从 -128+127(假设使用 2 的补码)。0xff 只是另一种写作方式,表示 255。一个 signed charrepresentation 与值为 0xffunsigned char 相同,则其值为 -1(再次假设 CHAR_BIT==8 和使用 2 的补码)。 - Keith Thompson
@KeithThompson:我认为操作signed char c = 0xFF;是显式的实现定义,并且即使对于CHAR_BIT==8也可能引发信号:6.3.1.3 §3 [when]新类型为带符号类型,且该值无法在其中表示时;要么结果是实现定义的,要么会引发实现定义的信号 - 但常见的2补码实现给出-1 - Serge Ballesta
显示剩余3条评论

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