gpt4 book ai didi

c++ - 使用 char 参数从 调用函数是否安全?

转载 作者:塔克拉玛干 更新时间:2023-11-03 02:19:41 26 4
gpt4 key购买 nike

C 编程语言表示来自 <ctype.h> 的函数遵循一个共同的要求:

ISO C99, 7.4p1:

In all cases the argument is an int, the value of which shall be representable as an unsigned char or shall equal the value of the macro EOF. If the argument has any other value, the behavior is undefined.

这意味着下面的代码是不安全的:

int upper(const char *s, size_t index) {
return toupper(s[index]);
}

如果此代码在 char 的实现上执行与 signed char 具有相同的值空间并且字符串中有一个负值字符,此代码调用未定义的行为。正确的版本是:

int upper(const char *s, size_t index) {
return toupper((unsigned char) s[index]);
}

尽管如此,我看到许多 C++ 示例并不关心这种未定义行为的可能性。那么C++标准中有没有什么东西可以保证上面的代码不会导致未定义的行为,或者所有的例子都是错误的?

[其他关键字:ctype cctype isalnum isalpha isblank iscntrl isdigit isgraph islowwer isprint ispunct isspace isupper isxdigit tolower]

最佳答案

就其值(value)而言,Solaris Studio 编译器(使用 STLport4)就是这样一种编译器套件,在这里会产生意想不到的结果。编译并运行:

#include <stdio.h>
#include <cctype>

int main() {
char ch = '\xa1'; // '¡' in latin-1 locales + UTF-8
printf("is whitespace: %i\n", std::isspace(ch));
return 0;
}

给我:

kevin@solaris:~/scratch
$ CC -library=stlport4 whitespace.cpp && ./a.out
is whitespace: 8

供引用:

$ CC -V
CC: Studio 12.5 Sun C++ 5.14 SunOS_i386 2016/05/31

当然,这种行为已记录在 C++ 标准中,但这绝对令人惊讶。


编辑:由于有人指出,由于整数溢出,上述版本在尝试分配 char ch = '\xa1' 时包含未定义的行为,因此这里有一个版本可以避免这种情况并仍然保留相同的输出:

#include <stdio.h>
#include <cctype>

int main() {
char ch = -95;
printf("is whitespace: %i\n", std::isspace(ch));
return 0;
}

而且在我的 Solaris VM 上仍然打印 8:

kevin@solaris:~/scratch
$ CC -library=stlport4 whitespace.cpp && ./a.out
is whitespace: 8

编辑 2:这是一个程序,在其他方面可能看起来很正常,但由于 UB 在使用 std::isspace() 时给出了意想不到的结果:

#include <cstdio>
#include <cstring>
#include <cctype>

static int count_whitespace(const char* str, int n) {
int count = 0;
for (int i = 0; i < n; i++)
if (std::isspace(str[i])) // oops!
count += 1;
return count;
}

int main() {
const char* batman = "I am batman\xa1";
int n = std::strlen(batman);
std::printf("%i\n", count_whitespace(batman, n));
return 0;
}

并且,在我的 Solaris 机器上:

kevin@solaris:~/scratch
$ CC whitespace.cpp && ./a.out
3

请注意,根据您排列此程序的方式,您可能会得到两个空白字符的预期结果;也就是说,几乎可以肯定会出现一些编译器优化,利用此 UB 更快地为您提供错误结果。

例如,如果您尝试通过在字符串中搜索(非多字节)空白字符来对 UTF-8 字符串进行标记化,您可能会想像这会咬您的脸。这样的程序在将 str[i] 转换为 unsigned char 时会正确运行。

关于c++ - 使用 char 参数从 <cctype> 调用函数是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7131026/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com