ASCII 是一个 7 位字符集。在 C 中通常由 8 位字符表示。如果设置了 8 位字节中的最高位,则它不是ASCII 字符。
另请注意,您不能保证 ASCII作为基础,许多人忽略了其他情况。如果你想检查一个“原始”字节是否是一个字母字符,你可以换句话说不是,当注意所有系统时,说:
is_alpha = (c > 0x40 && c < 0x5b) || (c > 0x60 && c < 0x7b);
相反,您必须使用ctype.h
并说:
isalpha(c);
唯一的例外,AFAIK,是数字,至少在大多数表上,它们具有连续的值。
因此这是有效的;
char ninec = '9';
char eightc = '8';
int nine = ninec - '0';
int eight = eightc - '0';
printf("%d\n", nine);
printf("%d\n", eight);
但这不能保证是“a”:
alhpa_a = 0x61;
不基于 ASCII 的系统,即使用EBCDIC;C 在这样的平台上仍然可以正常运行,但在这里它们(大部分)使用 8 位而不是 7 位,即A
可以编码为十进制193
而不是65
ASCII。
但是对于 ASCII;具有十进制 128 - 255 的字节(使用 8 位)是扩展的,而不是 ASCII 集的一部分。即 ISO-8859 使用这个范围。
经常做什么;也就是将两个或多个字节组合成一个字符。因此,如果您连续打印两个字节,定义为utf8 0xc3 0x98
== Ø,那么您将得到这个字符。
这又取决于您所处的环境。在许多系统/环境中,打印 ASCII 值会在字符集、系统等之间给出相同的结果。但是打印字节 > 127 或双字节字符会根据本地配置给出不同的结果。
IE:
A先生运行程序得到
贾斯€</p>
虽然 B 先生得到
亚斯派斯
这可能与 ISO-8859 系列和 Windows-1252 的扩展字符的单字节表示等特别相关。
- UTF-8#Codepage_layout,在 UTF-8 中你有 ASCII,然后你有特殊的再见序列。
- 每个序列都以 > 127 的字节开始(这是最后一个 ASCII 字节),
- 后跟给定数量的字节,所有字节都以 bits 开头
10
。
- 换句话说,您永远不会在多字节 UTF-8 表示中找到 ASCII 字节。
那是; UTF-8 中的第一个字节,如果不是 ASCII,则表示该字符有多少字节。您也可以说 ASCII 字符表示后面没有更多字节 - 因为最高位是 0。
即,如果文件解释为 UTF-8:
fgetc(c);
if c < 128, 0x80, then ASCII
if c == 194, 0xC2, then one more byte follow, interpret to symbol
if c == 226, 0xE2, then two more byte follows, interpret to symbol
...
举个例子。如果我们看一下您提到的角色之一。如果在 UTF-8 终端中:
$ echo -n "č" | xxd
应该产生:
0000000: c48d ..
换句话说,“č”由两个字节 0xc4 和 0x8d 表示。将 -b 添加到 xxd 命令,我们得到字节的二进制表示。我们对它们进行如下剖析:
___ byte 1 ___ ___ byte 2 ___
| | | |
0xc4 : 1100 0100 0x8d : 1000 1101
| |
| +-- all "follow" bytes starts with 10, rest: 00 1101
|
+ 11 -> 2 bits set = two byte symbol, the "bits set" sequence
end with 0. (here 3 bits are used 110) : rest 0 0100
Rest bits combined: xxx0 0100 xx00 1101 => 00100001101
\____/ \_____/
| |
| +--- From last byte
+------------ From first byte
这给了我们:00100001101 2 = 269 10 = 0x10D => Uncode 代码点 U+010D == "č"。
这个数字也可以在 HTML 中用作č
== č
这个和许多其他代码系统的共同点是 8 位字节是基础。
通常这也是一个关于上下文的问题。以 GSM SMS 为例,ETSI GSM 03.38/03.40 ( 3GPP TS 23.038 , 3GPP 23038 )。在那里我们还找到了一个 7 位字符表,7 位 GSM 默认字母表,但不是将它们存储为 8 位,而是将它们存储为 7 位1。通过这种方式,您可以将更多字符打包到给定数量的字节中。即标准 SMS 160 个字符变成 1280 位或 160 字节作为 ASCII 和 1120 或 140 字节作为 SMS。
1并非无一例外,(更多的是故事)。
即以 SMS UDP 格式保存为 septets (7bit) C8329BFD06 到 ASCII 的字节的简单示例:
_________
7 bit UDP represented | +--- Alphas has same bits as ASCII
as 8 bit hex '0.......'
C8329BFDBEBEE56C32 1100100 d * Prev last 6 bits + pp 1
| | | | | | | | +- 00 110010 -> 1101100 l * Prev last 7 bits
| | | | | | | +--- 0 1101100 -> 1110010 r * Prev 7 + 0 bits
| | | | | | +----- 1110010 1 -> 1101111 o * Last 1 + prev 6
| | | | | +------- 101111 10 -> 1010111 W * Last 2 + prev 5
| | | | +--------- 10111 110 -> 1101111 o * Last 3 + prev 4
| | | +----------- 1111 1101 -> 1101100 l * Last 4 + prev 3
| | +------------- 100 11011 -> 1101100 l * Last 5 + prev 2
| +--------------- 00 110010 -> 1100101 e * Last 6 + prev 1
+----------------- 1 1001000 -> 1001000 H * Last 7 bits
'------'
|
+----- GSM Table as binary
9 个字节“解压”变成 10 个字符。