使用/ MD编译器选项,isprint('\ t')的计算结果为true(64)

时间:2018-07-20 04:47:58

标签: c visual-c++

对于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

2 个答案:

答案 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的自变量应该是0UCHAR_MAX范围内的整数。因此,您应该编写isprint(i)而不是isprint((char)i)。由于您将i限制为正确范围的一部分,因此这对您的程序来说是无济于事的。但是,如果让i超过127,那将是不正确的。