我假设您想检查编译器在将源代码中的字符串文字和字符文字转换为机器码时是否使用ASCII编码。
std 中是否有像 is_ascii 这样的函数?
我不知道有没有这样的函数。
我可以自己实现类似于 if(65 == 'A' && ...) 的 is_ascii 函数,枚举整个 ASCII 字符集。
那就这么做吧。检查可以作为 c-char 的字符,所以是从基本源字符集中获取的所有字符:
a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '
和转义序列:
\a \b \f \n \r \t \v
无法检查“整个”ASCII字符集,因为编译器不会将程序转录到整个ASCII字符集中。它只将基本字符集字符和转义序列映射到其机器表示形式,而不是整个字符集(可能有编译器扩展)。
但这很烦人。
但这是唯一的方法。要验证您的实现使用了某些字符集,您必须检查它使用的所有字符。所以检查它们。它最终会成为consteval
。
如何检查像SOH(标题起始)等不可打印字符。
不用。SOH字符不能在字符字面量中,您不必检查它们,因为在C语言中无法表示它。没有\SOH
转义序列,0x01
字节不在基本字符集中。您的编译器永远不会将一系列字符转换为SOH
字符。一个有效的程序只由基本源字符集中的字符组成。 SOH
字符的解释取决于将要接收它的东西,如果我写'\001'
,它将是等于1
的字节,与编码无关。
呃,让我们写吧!以下是程序:
#include <type_traits>
#include <algorithm>
constexpr bool compiler_uses_ascii() {
return
'\a'==0x07 && '\b'==0x08 && '\t'==0x09 && '\n'==0x0a && '\v'==0x0b && '\f'==0x0c &&
'\r'==0x0d && '!'==0x21 && '#'==0x23 && '%'==0x25 && '&'==0x26 && '\''==0x27 &&
'('==0x28 && ')'==0x29 && '*'==0x2a && '+'==0x2b && ','==0x2c && '-'==0x2d &&
'.'==0x2e && '/'==0x2f && '0'==0x30 && '1'==0x31 && '2'==0x32 && '3'==0x33 &&
'4'==0x34 && '5'==0x35 && '6'==0x36 && '7'==0x37 && '8'==0x38 && '9'==0x39 &&
':'==0x3a && ';'==0x3b && '<'==0x3c && '='==0x3d && '>'==0x3e && '?'==0x3f &&
'A'==0x41 && 'B'==0x42 && 'C'==0x43 && 'D'==0x44 && 'E'==0x45 && 'F'==0x46 &&
'G'==0x47 && 'H'==0x48 && 'I'==0x49 && 'J'==0x4a && 'K'==0x4b && 'L'==0x4c &&
'M'==0x4d && 'N'==0x4e && 'O'==0x4f && 'P'==0x50 && 'Q'==0x51 && 'R'==0x52 &&
'S'==0x53 && 'T'==0x54 && 'U'==0x55 && 'V'==0x56 && 'W'==0x57 && 'X'==0x58 &&
'Y'==0x59 && 'Z'==0x5a && '['==0x5b && '\\'==0x5c && ']'==0x5d && '^'==0x5e &&
'_'==0x5f && 'a'==0x61 && 'b'==0x62 && 'c'==0x63 && 'd'==0x64 && 'e'==0x65 &&
'f'==0x66 && 'g'==0x67 && 'h'==0x68 && 'i'==0x69 && 'j'==0x6a && 'k'==0x6b &&
'l'==0x6c && 'm'==0x6d && 'n'==0x6e && 'o'==0x6f && 'p'==0x70 && 'q'==0x71 &&
'r'==0x72 && 's'==0x73 && 't'==0x74 && 'u'==0x75 && 'v'==0x76 && 'w'==0x77 &&
'x'==0x78 && 'y'==0x79 && 'z'==0x7a && '{'==0x7b && '|'==0x7c && '}'==0x7d &&
'~'==0x7e;
}
constexpr int char_index(char c)
{
if constexpr (compiler_uses_ascii()) {
return c - 'A';
} else {
// Is that right? Maybe it is.
const char a[] = "ABCDEFGHIJKLMNOPRSTUVXYZ";
return std::find(a, a + sizeof(a), c) - a;
#if 0
return
c == 'A' ? 0 : c == 'B' ? 1 : c == 'C' ? 2 : c == 'D' ? 3 :
c == 'E' ? 4 : c == 'F' ? 5 : c == 'G' ? 6 : c == 'H' ? 7 :
c == 'I' ? 8 : c == 'J' ? 9 : c == 'K' ? 10 : c == 'L' ? 11 :
c == 'M' ? 12 : c == 'N' ? 13 : c == 'O' ? 14 : c == 'P' ? 15 :
c == 'Q' ? 16 : c == 'R' ? 17 : c == 'S' ? 18 : c == 'T' ? 19 :
c == 'U' ? 20 : c == 'V' ? 21 : c == 'W' ? 22 : c == 'X' ? 23 :
c == 'Y' ? 24 : c == 'Z' ? 25 : -1;
#endif
}
}
#include <iostream>
int main() {
std::cout << compiler_uses_ascii() << " " << char_index('B') << "\n";
}
执行时输出:
$ g++ 1.cpp -std=c++20 && ./a.out
1 1
$ g++ 1.cpp -fexec-charset=IBM-1047 -std=c++20 && ./a.out
0@1%
return c == 'A' ? 0 : c == 'B' ? 1 :
等等的代码,那么你就不需要is_ascii
,因为它在任何情况下都可以工作。 - n. m.