我想了解在C/C++中如何定义“isupper”宏。您能否提供相应的信息或指向可用资源。我尝试查看ctype.h,但无法理解。
我想了解在C/C++中如何定义“isupper”宏。您能否提供相应的信息或指向可用资源。我尝试查看ctype.h,但无法理解。
它的实现是有定义的,每个供应商可以并且通常会有不同的方法。
最常见的方法通常涉及"traits"表 - 一个包含每个字符一个元素的数组,该元素的值是指示有关该字符详细信息的标志集合。例如:
traits[(int) 'C'] = ALPHA | UPPER | PRINTABLE;
在什么情况下 isupper() 会变成类似这样的形式: #define isupper(c) ((traits[(int)(c)] & UPPER) == UPPER)
extern char *__isupper;
#define isupper(x) ((int)__isupper[(x)])
__isupper
指向一个由区域设置确定的0和1数组。然而,这种技术已经不再流行,因为在共享库中访问全局变量相当低效,并且会创建永久的ABI要求,而且它与POSIX线程本地区域设置不兼容。
在仅限于ASCII或UTF-8的实现上实现它的另一种明显方法是:
#define isupper(x) ((unsigned)(x)-'A'<='Z'-'A')
这是一个函数,不是宏。 isupper()
函数的定义取决于区域设置和当前字符集等因素——这就是为什么有一个专门用于此目的的函数。
对于 ASCII 码,由于字母的分配方式,测试这一点实际上相当容易。如果字符的 ASCII 码在包括 0x41
和 0x5A
在内的区间内,则它是大写字母。
实际上,这在GCC中相当复杂。但是isupper的简单实现可以(尽管它有双重评估错误)最简单地定义为:
#define isupper(c) (c >= 'A') & (c <= 'Z')
GCC会特别检查当前语言环境下字符的第0位是否为1:
(*__ctype_b_loc ())[(int) (c)] & (unsigned short int) (1 << (0))
其中,__ctype_b_loc()是一个函数,它返回指向当前语言环境下包含当前字符集中每个字符特征的字符数组的指针。
isupper(*s++)
...)。你需要强制转换为“unsigned”,并使用无符号溢出语义来测试范围,而不会评估参数超过一次。 - R.. GitHub STOP HELPING ICE
wchar_t
之间转换的函数。任何多字节字符是否存在以及其编码方式的性质都是实现和区域设置特定的。但我特别指出了一个仅支持UTF-8的实现。如果编码是UTF-8,则仅有ASCII字符0-0x7f可以单独对应于(宽)字符。值0x80-0xbf和0xc2-0xf4用作适当的多字节序列中的组件,任何剩余的值都是纯粹无效的(EILSEQ)。 - R.. GitHub STOP HELPING ICEchar
编码为UTF-8,则wchar_t
几乎肯定会表示为Unicode代码点(相当于UTF-32),并且isw*
函数将需要处理所有额外的字符,但非宽字符的is*
函数无法处理。 - R.. GitHub STOP HELPING ICE