对于Visual Studio 2017下的isprint
函数,我有意外的结果。给定以下程序
#include <ctype.h>
#include <stdio.h>
int main() {
for (int i = 0; i < 128; i += 1) {
printf("isprint(0x%x aka '%c') = %s (%d)\n", i, (char)i,
isprint((char)i) ? "yes" : "no", isprint((char)i));
}
return 0;
}
使用
编译并执行cl /MD isprint.c /Feisprint.exe && isprint.exe
返回
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26433 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
isprint.c
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:isprint.exe
isprint.obj
isprint(0x0 aka ' ') = no (0)
isprint(0x1 aka '') = no (0)
isprint(0x2 aka '') = no (0)
isprint(0x3 aka '') = no (0)
isprint(0x4 aka '') = no (0)
isprint(0x5 aka '') = no (0)
isprint(0x6 aka '') = no (0)
isprint(0x7 aka '') = no (0)
isprint(0x8 aka ') = no (0)
isprint(0x9 aka ' ') = yes (64)
isprint(0xa aka '
') = no (0)
isprint(0xb aka '') = no (0)
isprint(0xc aka '') = no (0)
') = no (0) aka '
isprint(0xe aka '') = no (0)
isprint(0xf aka '') = no (0)
isprint(0x10 aka '') = no (0)
isprint(0x11 aka '') = no (0)
isprint(0x12 aka '') = no (0)
isprint(0x13 aka '') = no (0)
isprint(0x14 aka '') = no (0)
isprint(0x15 aka '') = no (0)
isprint(0x16 aka '') = no (0)
isprint(0x17 aka '') = no (0)
isprint(0x18 aka '') = no (0)
isprint(0x19 aka '') = no (0)
isprint(0x1a aka '') = no (0)
isprint(0x1b aka '') = no (0)
isprint(0x1c aka '') = no (0)
isprint(0x1d aka '') = no (0)
isprint(0x1e aka '') = no (0)
isprint(0x1f aka '') = no (0)
isprint(0x20 aka ' ') = yes (64)
isprint(0x21 aka '!') = yes (16)
isprint(0x22 aka '"') = yes (16)
isprint(0x23 aka '#') = yes (16)
isprint(0x24 aka '$') = yes (16)
isprint(0x25 aka '%') = yes (16)
isprint(0x26 aka '&') = yes (16)
isprint(0x27 aka ''') = yes (16)
isprint(0x28 aka '(') = yes (16)
isprint(0x29 aka ')') = yes (16)
isprint(0x2a aka '*') = yes (16)
isprint(0x2b aka '+') = yes (16)
isprint(0x2c aka ',') = yes (16)
isprint(0x2d aka '-') = yes (16)
isprint(0x2e aka '.') = yes (16)
isprint(0x2f aka '/') = yes (16)
isprint(0x30 aka '0') = yes (4)
isprint(0x31 aka '1') = yes (4)
isprint(0x32 aka '2') = yes (4)
isprint(0x33 aka '3') = yes (4)
isprint(0x34 aka '4') = yes (4)
isprint(0x35 aka '5') = yes (4)
isprint(0x36 aka '6') = yes (4)
isprint(0x37 aka '7') = yes (4)
isprint(0x38 aka '8') = yes (4)
isprint(0x39 aka '9') = yes (4)
isprint(0x3a aka ':') = yes (16)
isprint(0x3b aka ';') = yes (16)
isprint(0x3c aka '<') = yes (16)
isprint(0x3d aka '=') = yes (16)
isprint(0x3e aka '>') = yes (16)
isprint(0x3f aka '?') = yes (16)
isprint(0x40 aka '@') = yes (16)
isprint(0x41 aka 'A') = yes (1)
isprint(0x42 aka 'B') = yes (1)
isprint(0x43 aka 'C') = yes (1)
isprint(0x44 aka 'D') = yes (1)
isprint(0x45 aka 'E') = yes (1)
isprint(0x46 aka 'F') = yes (1)
isprint(0x47 aka 'G') = yes (1)
isprint(0x48 aka 'H') = yes (1)
isprint(0x49 aka 'I') = yes (1)
isprint(0x4a aka 'J') = yes (1)
isprint(0x4b aka 'K') = yes (1)
isprint(0x4c aka 'L') = yes (1)
isprint(0x4d aka 'M') = yes (1)
isprint(0x4e aka 'N') = yes (1)
isprint(0x4f aka 'O') = yes (1)
isprint(0x50 aka 'P') = yes (1)
isprint(0x51 aka 'Q') = yes (1)
isprint(0x52 aka 'R') = yes (1)
isprint(0x53 aka 'S') = yes (1)
isprint(0x54 aka 'T') = yes (1)
isprint(0x55 aka 'U') = yes (1)
isprint(0x56 aka 'V') = yes (1)
isprint(0x57 aka 'W') = yes (1)
isprint(0x58 aka 'X') = yes (1)
isprint(0x59 aka 'Y') = yes (1)
isprint(0x5a aka 'Z') = yes (1)
isprint(0x5b aka '[') = yes (16)
isprint(0x5c aka '\') = yes (16)
isprint(0x5d aka ']') = yes (16)
isprint(0x5e aka '^') = yes (16)
isprint(0x5f aka '_') = yes (16)
isprint(0x60 aka '`') = yes (16)
isprint(0x61 aka 'a') = yes (2)
isprint(0x62 aka 'b') = yes (2)
isprint(0x63 aka 'c') = yes (2)
isprint(0x64 aka 'd') = yes (2)
isprint(0x65 aka 'e') = yes (2)
isprint(0x66 aka 'f') = yes (2)
isprint(0x67 aka 'g') = yes (2)
isprint(0x68 aka 'h') = yes (2)
isprint(0x69 aka 'i') = yes (2)
isprint(0x6a aka 'j') = yes (2)
isprint(0x6b aka 'k') = yes (2)
isprint(0x6c aka 'l') = yes (2)
isprint(0x6d aka 'm') = yes (2)
isprint(0x6e aka 'n') = yes (2)
isprint(0x6f aka 'o') = yes (2)
isprint(0x70 aka 'p') = yes (2)
isprint(0x71 aka 'q') = yes (2)
isprint(0x72 aka 'r') = yes (2)
isprint(0x73 aka 's') = yes (2)
isprint(0x74 aka 't') = yes (2)
isprint(0x75 aka 'u') = yes (2)
isprint(0x76 aka 'v') = yes (2)
isprint(0x77 aka 'w') = yes (2)
isprint(0x78 aka 'x') = yes (2)
isprint(0x79 aka 'y') = yes (2)
isprint(0x7a aka 'z') = yes (2)
isprint(0x7b aka '{') = yes (16)
isprint(0x7c aka '|') = yes (16)
isprint(0x7d aka '}') = yes (16)
isprint(0x7e aka '~') = yes (16)
isprint(0x7f aka '') = no (0)
问题在于它对于制表符('\t'
)返回true(64)。但是,如果在没有/MD
编译器选项或其他一些运行时库版本(例如
cl /MDd isprint.c /Feisprint.exe && isprint.exe
结果是
Microsoft (R) C/C++ Optimizing Compiler Version 19.14.26433 for x64
Copyright (C) Microsoft Corporation. All rights reserved.
isprint.c
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:isprint.exe
isprint.obj
isprint(0x0 aka ' ') = no (0)
isprint(0x1 aka '') = no (0)
isprint(0x2 aka '') = no (0)
isprint(0x3 aka '') = no (0)
isprint(0x4 aka '') = no (0)
isprint(0x5 aka '') = no (0)
isprint(0x6 aka '') = no (0)
isprint(0x7 aka '') = no (0)
isprint(0x8 aka ') = no (0)
isprint(0x9 aka ' ') = no (0)
isprint(0xa aka '
') = no (0)
isprint(0xb aka '') = no (0)
isprint(0xc aka '') = no (0)
') = no (0) aka '
isprint(0xe aka '') = no (0)
isprint(0xf aka '') = no (0)
isprint(0x10 aka '') = no (0)
isprint(0x11 aka '') = no (0)
isprint(0x12 aka '') = no (0)
isprint(0x13 aka '') = no (0)
isprint(0x14 aka '') = no (0)
isprint(0x15 aka '') = no (0)
isprint(0x16 aka '') = no (0)
isprint(0x17 aka '') = no (0)
isprint(0x18 aka '') = no (0)
isprint(0x19 aka '') = no (0)
isprint(0x1a aka '') = no (0)
isprint(0x1b aka '') = no (0)
isprint(0x1c aka '') = no (0)
isprint(0x1d aka '') = no (0)
isprint(0x1e aka '') = no (0)
isprint(0x1f aka '') = no (0)
isprint(0x20 aka ' ') = yes (64)
isprint(0x21 aka '!') = yes (16)
isprint(0x22 aka '"') = yes (16)
isprint(0x23 aka '#') = yes (16)
isprint(0x24 aka '$') = yes (16)
isprint(0x25 aka '%') = yes (16)
isprint(0x26 aka '&') = yes (16)
isprint(0x27 aka ''') = yes (16)
isprint(0x28 aka '(') = yes (16)
isprint(0x29 aka ')') = yes (16)
isprint(0x2a aka '*') = yes (16)
isprint(0x2b aka '+') = yes (16)
isprint(0x2c aka ',') = yes (16)
isprint(0x2d aka '-') = yes (16)
isprint(0x2e aka '.') = yes (16)
isprint(0x2f aka '/') = yes (16)
isprint(0x30 aka '0') = yes (4)
isprint(0x31 aka '1') = yes (4)
isprint(0x32 aka '2') = yes (4)
isprint(0x33 aka '3') = yes (4)
isprint(0x34 aka '4') = yes (4)
isprint(0x35 aka '5') = yes (4)
isprint(0x36 aka '6') = yes (4)
isprint(0x37 aka '7') = yes (4)
isprint(0x38 aka '8') = yes (4)
isprint(0x39 aka '9') = yes (4)
isprint(0x3a aka ':') = yes (16)
isprint(0x3b aka ';') = yes (16)
isprint(0x3c aka '<') = yes (16)
isprint(0x3d aka '=') = yes (16)
isprint(0x3e aka '>') = yes (16)
isprint(0x3f aka '?') = yes (16)
isprint(0x40 aka '@') = yes (16)
isprint(0x41 aka 'A') = yes (1)
isprint(0x42 aka 'B') = yes (1)
isprint(0x43 aka 'C') = yes (1)
isprint(0x44 aka 'D') = yes (1)
isprint(0x45 aka 'E') = yes (1)
isprint(0x46 aka 'F') = yes (1)
isprint(0x47 aka 'G') = yes (1)
isprint(0x48 aka 'H') = yes (1)
isprint(0x49 aka 'I') = yes (1)
isprint(0x4a aka 'J') = yes (1)
isprint(0x4b aka 'K') = yes (1)
isprint(0x4c aka 'L') = yes (1)
isprint(0x4d aka 'M') = yes (1)
isprint(0x4e aka 'N') = yes (1)
isprint(0x4f aka 'O') = yes (1)
isprint(0x50 aka 'P') = yes (1)
isprint(0x51 aka 'Q') = yes (1)
isprint(0x52 aka 'R') = yes (1)
isprint(0x53 aka 'S') = yes (1)
isprint(0x54 aka 'T') = yes (1)
isprint(0x55 aka 'U') = yes (1)
isprint(0x56 aka 'V') = yes (1)
isprint(0x57 aka 'W') = yes (1)
isprint(0x58 aka 'X') = yes (1)
isprint(0x59 aka 'Y') = yes (1)
isprint(0x5a aka 'Z') = yes (1)
isprint(0x5b aka '[') = yes (16)
isprint(0x5c aka '\') = yes (16)
isprint(0x5d aka ']') = yes (16)
isprint(0x5e aka '^') = yes (16)
isprint(0x5f aka '_') = yes (16)
isprint(0x60 aka '`') = yes (16)
isprint(0x61 aka 'a') = yes (2)
isprint(0x62 aka 'b') = yes (2)
isprint(0x63 aka 'c') = yes (2)
isprint(0x64 aka 'd') = yes (2)
isprint(0x65 aka 'e') = yes (2)
isprint(0x66 aka 'f') = yes (2)
isprint(0x67 aka 'g') = yes (2)
isprint(0x68 aka 'h') = yes (2)
isprint(0x69 aka 'i') = yes (2)
isprint(0x6a aka 'j') = yes (2)
isprint(0x6b aka 'k') = yes (2)
isprint(0x6c aka 'l') = yes (2)
isprint(0x6d aka 'm') = yes (2)
isprint(0x6e aka 'n') = yes (2)
isprint(0x6f aka 'o') = yes (2)
isprint(0x70 aka 'p') = yes (2)
isprint(0x71 aka 'q') = yes (2)
isprint(0x72 aka 'r') = yes (2)
isprint(0x73 aka 's') = yes (2)
isprint(0x74 aka 't') = yes (2)
isprint(0x75 aka 'u') = yes (2)
isprint(0x76 aka 'v') = yes (2)
isprint(0x77 aka 'w') = yes (2)
isprint(0x78 aka 'x') = yes (2)
isprint(0x79 aka 'y') = yes (2)
isprint(0x7a aka 'z') = yes (2)
isprint(0x7b aka '{') = yes (16)
isprint(0x7c aka '|') = yes (16)
isprint(0x7d aka '}') = yes (16)
isprint(0x7e aka '~') = yes (16)
isprint(0x7f aka '') = no (0)
这是怎么回事?在大约两周前,我注意到我的申请有变更。这可能是由某些Windows或Visual Studio更新引起的吗?我检查了两种情况下的线程区域设置是否相同。
Windows 10内部版本17134.165
答案 0 :(得分:5)
@Meinersbur感谢您举报。我只是想在我们的构建机器上而不是在我的工作站上看到它,所以我一直在努力试图理解差异。
为了其他人来到这里,微软的回应(请参阅https://developercommunity.visualstudio.com/content/problem/297085/changing-result-of-isspacet.html)是:
被isprint()报告为打印字符的Tab是Universal C运行时中的回归,该更新从更新KB4338819开始出现。它将在以后的服务更新中修复,并将在Windows的下一个主要版本中修复。
该问题与/ MD或/ MDd设置无关。使用/ MD进行构建时,Universal C Runtime将由System32中的OS版本提供,该版本将随您的OS版本而变化。使用/ MDd进行构建时,您将收到Windows SDK和Visual Studio附带的调试版本,并且将使用已安装的最新版本。
如果希望具有与在所有操作系统上的调试模式下相同的行为,则可以通过使用/ MT构建来静态链接C运行时。
希望这会有所帮助!
史蒂夫·威斯诺斯基(Steve Wishnousky) 软件工程师II-Visual C ++库
答案 1 :(得分:1)
根据C11 7.4,
术语“打印字符”是指特定于语言环境的一组字符的成员,每个字符在显示设备上占据一个打印位置;
由于制表符通常占据多个打印位置,因此在我看来这\t
不应是打印字符。
5.2.2(字符显示语义)中的文本似乎支持了这一点,将\t
描述为非图形字符。
我的解释是,与第一个示例一样,isprint('\t')
的行为不符合非零。
但是,我可以看到有人在争论标准不明确,并且行为应由区域设置来定义;可能会更改编译器开关,从而选择其他语言环境(?)
您可以提交错误报告;然后编译器支持人员会承认它,或者建议他们的编译器为什么这样做。
NB。 isprint
的自变量应该是0
到UCHAR_MAX
范围内的整数。因此,您应该编写isprint(i)
而不是isprint((char)i)
。由于您将i
限制为正确范围的一部分,因此这对您的程序来说是无济于事的。但是,如果让i
超过127
,那将是不正确的。