繁体   English   中英

isprint('\ t')使用/ MD编译器选项求值为true(64)

[英]isprint('\t') evaluates to true (64) with /MD compiler option

我在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 build 17134.165

@Meinersbur感谢您报告此事。 我试图理解差异,因为我只是在我们的构建机器上而不是在我的工作站上看到它。

为了其他人来到这里,微软的回复(见https://developercommunity.visualstudio.com/content/problem/297085/changing-result-of-isspacet.html )是:

isprint()报告为打印字符的选项卡是Universal C Runtime中的回归,它随更新KB4338819一起显示。 它将在未来的服务更新中修复,并将在Windows的下一个主要版本中修复。

该问题与/ MD或/ MDd设置无关。 使用/ MD构建时,Universal C Runtime将由System32中的OS版本提供,该版本将随操作系统版本而变化。 使用/ MDd构建时,您将收到Windows SDK和Visual Studio附带的调试版本,您将使用已安装的最新版本。

如果您希望在所有操作系统上具有与在调试模式下看到的相同的行为,则可以通过使用/ MT构建来静态链接C运行时。

希望这可以帮助!

Steve Wishnousky软件工程师II - Visual C ++库

根据C11 7.4,

术语打印字符是指特定于语言环境的字符集的成员,每个字符占据显示设备上的一个打印位置;

由于标签通常占据了多打印位置,在我看来,这是说, \\t不应该是一个打印字符。

5.2.2(字符显示语义)中的文本似乎支持这一点,将\\t描述为非图形字符


我的解释是, isprint('\\t')的行为不符合非零,如第一个例子中所示。

但是我可以看到有人认为标准不清楚,行为应该由语言环境定义; 可能更改编译器开关选择不同的区域设置(?)

您可以提交错误报告; 然后编译器支持人们会承认它或建议他们的编译器为什么这样做。


NB。 isprint的参数应该是0UCHAR_MAX范围内的整数值。 所以你应该写isprint(i)而不是isprint((char)i) 由于您将i限制为正确范围的子集,因此这对您的程序来说是没有意义的; 但如果你让i超过127正确。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM