C函数调用产生的结果与C++函数调用不同

C function call produces different result than C++ function call

本文关键字:函数调用 C++ 结果      更新时间:2023-10-16

我有这个C代码:

#include <stdio.h>
#include <windows.h>
int main() {
    int i;
    while(1) {
        for (i = 8; i <= 190; i++) {
            if (GetAsyncKeyState(i) == -32767)  // That number doesnt actually work, only works with -32768 (which checks to see if the key is pressed down)
                printf("%cn",i); // When using -32768, it prints the key if it is held down about 20 times
        }
    } 
    return 0;
}

所以-32767在那个C代码中不起作用,但我有一个C++代码:

#include <iostream>
using namespace std;
#include <windows.h>
int main() {
    char i;
    while (1) {
        for(i = 8; i <= 190; i++) {
            if (GetAsyncKeyState(i) == -32767)  // works as intended, prints the pressed key letter (doesnt have to be held down)
            cout << i << endl;
        }
    }
    return 0;
}

与-32767配合使用。这是非常令人困惑的,因为这两个都是在同一台计算机上用相同的命令运行的:clang++ test.c

C输出-32768(按A):

A
A
A
A
A
A
A
A
A
A
A

用-32767:输出C++代码

A
B
C
D
E
F
G
H

具有-32767的C代码输出:(无)

根据GetAsyncKeyState:的文档

如果函数成功,则返回值指定自上次调用GetAsyncKeyState以来是否按下了该键,以及该键当前是向上还是向下。如果设置了最高有效位,则键向下;如果设置了最低有效位,那么键在上次调用GetAsyncKeyState之后被按下但是,您不应该依赖这最后一个行为;有关详细信息,请参阅备注。

这说明将-32768-32767区别对待是不可靠的。它也没有说明中间的所有比特,但您的代码假设它们是1比特,而没有理由。

为了可靠,您的代码应该只对返回值进行以下测试:

  • >= 0-密钥当前已打开,或信息不可用
  • < 0-按键当前关闭

您的代码依赖于实现定义的行为。看起来您的C编译器使用的是无符号的char s,而C++编译器使用的却是有符号的。这就是为什么C中的嵌套循环一直到190,而C++中的同一个循环在达到128时循环到零。

您可以通过在两个实现中将i的类型设置为unsigned char来解决此问题。您也可以将i设为int,并在GetAsyncKeyState函数的调用中为char添加强制转换。

请参阅本主题:http://www.cplusplus.com/forum/general/141404/-32767在二进制中实际上是1000 0000 0000 0001,当你比较GetAsyncKeyState(i)的返回值时,你基本上是在问是否只有左位和右位打开,但正如上面的链接中所说,位1-14可能并不总是零。一个更恰当的表达是这样的:

if (GetAsyncKeyState(i) & -32767)

或者可以使用十六进制文字:

if (GetAsyncKeyState(i) & 0x8001)

实际上,C实现不起作用的原因是因为我在mingw32终端中手动执行./a,由于某种原因,直到按下了很多键后,它才打印任何内容,所以我只是双击执行a.exe,它就起了作用,这是一种非常奇怪的体验:/