根据ISO / IEC在不同的字符集编码(如UTF-16)中混淆sizeof(char)
假设一个程序在UTF-16编码字符集的系统上运行。 所以根据The C ++ Programming Language – 4th ,第150页:
char可以保存机器字符集的一个字符。
→我认为charvariables的大小是2个字节。
但根据ISO / IEC 14882:2014 :
sizeof(char)
,sizeof(signed char)
和sizeof(unsigned char)
是1“。
或C ++编程语言 – 第4页,第149页:
“[…],所以根据定义,字符的大小是1”
→大小固定为1。
问题:上述这些语句之间是否存在冲突,或者是sizeof(char) = 1
只是一个默认(定义)值,并且实现定义取决于每个系统?
C ++标准(和C,就此而言)有效地将byte
定义为char
types的大小, 而不是 8位数量1 。 按照C++11 1.7/1
(我的粗体):
C ++内存模型中的基本存储单元是字节。 一个字节至less足以包含基本执行字符集的任何成员和Unicode UTF-8编码forms的八位代码单元,并且由一个连续的位序列组成, 其数目是实现定义的。
因此,expression式sizeof(char)
总是 1,不pipe怎样。
如果你想看看你的底线char
variables(可能是unsigned
variables是最好的)实际上可以保存一个16位的值,你想看的项目是来自<climits>
CHAR_BIT
。 这保存了char
variables中的位数。
1许多标准,特别是与通信协议相关的标准,使用octet
更精确的octet
。
是的,在string的C ++混合中存在一些严重的冲突和问题,而且这个问题也混合了一些东西。 所以,一个简单的直接答案就好像回答“是”,“否”或“不知道”这个问题“你停止殴打你的妻子了吗?”。 唯一直接的答案是佛教“亩” ,不问这个问题。
所以,让我们先看看事实。
关于字符types的事实。
每个char
的位数是由<limits.h>
头文件中实现定义的CHAR_BIT
给出的。 这个数字保证是8或更大。 在C ++ 03及更早版本中,保证来自C89标准中的该符号的规范,C ++标准(在非规范性章节中,但仍然)将其标注为“合并”。 对于C ++ 11及更高版本,C ++标准明确地给出了≥8的保证。 在大多数平台上, CHAR_BIT
是8,但在一些可能仍然存在的德州仪器数字信号处理器中,它是16,而其他值已被使用。
无论CHAR_BIT
的值是CHAR_BIT
, sizeof(char)
的定义都是1,即没有实现的定义:
C ++ 11§5.3.3/ 1 (在[expr.sizeof]中):
“
sizeof(char)
,sizeof(signed char)
和sizeof(unsigned char)
是1。
也就是说, char
和它的变体是内存寻址的基本单位 ,这是字节的主要含义,无论是在普通语言还是在C ++中:
C ++ 11§1.7/ 1 (in [intro.memory]):
“ C ++内存模型中的基本存储单元是字节 。
这意味着在前面提到的TI DSP上,没有C ++获取单个八位字节 (8位部分)的指针的方法。 而这又意味着需要处理字节序的代码或者以其他方式需要将char
值视为八位字节序列(特别是用于networking通信)的代码需要使用在CHAR_BIT
的系统上无意义的char
值是8.这也意味着普通的C ++窄string文字,如果坚持标准的话,而且如果平台的标准软件使用8位字符编码的话,会浪费内存。
Pascal语言直接解决了这个浪费问题,它区分了压缩string (每个字节多个八位字节)和未压缩string (每个字节一个八位字节),其中前者用于被动文本存储,后者是用于高效处理。
这说明了单个C ++typeschar
中三个方面的基本结合:
-
内存寻址单元,又名字节,
-
最小的基本types(这将是一个
octet
types),和 -
字符编码值单位。
是的,这是一个冲突。
关于UTF-16编码的事实。
Unicode是一组21位的代码点 ,其中大部分是自己构成的字符,但其中一些与其他字符组合形成字符。 例如,可以通过将“e”和“'”作为重音的代码点组合来形成具有类似“é”的口音的字符。 而且由于这是一个通用机制,所以它意味着一个Unicode字符可以是任意数量的代码点,尽pipe通常只有1个。
当Unicode扩展为每个代码点21位时,UTF-16编码最初是一种基于原始Unicode的每个代码点16位代码的兼容性scheme。 基本的scheme是原始Unicode定义范围内的代码点表示为它们自己,而每个新的Unicode代码点表示为16位值的替代对 。 代理对值使用小范围的原始Unicode。
当时,基于每码点16位软件的例子包括32位Windows和Java语言。
在具有8位字节UTF-16的系统上是宽文本编码的例子,即编码单元比基本可寻址单元宽。 字节为导向的文本编码被称为窄文本 。 在这样的系统上,C ++ char
适合后者,但不适用于前者。
在C ++ 03中,适用于宽文本编码单元的唯一内置types是wchar_t
。
但是,C ++标准有效地要求wchar_t
适合于代码点 ,对于现代21位每代码点Unicode来说,它意味着它需要是32位。 因此,没有C ++ 03专用types适合UTF-16编码值的要求,每个值16位。 由于历史原因,基于UTF-16作为宽文本编码的最普遍的系统,即Microsoft Windows,将wchar_t
定义为16位,这在Unicode的扩展之后已经与标准公然矛盾,但是这样的标准是不切实际的关于这个问题。 有些平台将wchar_t
定义为32位。
C ++ 11引入了新的typeschar16_t
和char32_t
,前者被devise为适合于UTF-16编码值。
关于这个问题。
关于这个问题的陈述假设
“一个使用UTF-16编码字符集的系统
这可能意味着两件事之一:
- 一个以UTF-16作为标准窄编码的系统,或者
- 作为标准宽编码的UTF-16系统。
用UTF-16作为标准的窄编码CHAR_BIT
,和(按定义) sizeof(char)
= 1。我不知道任何系统,即它似乎是假设的。 然而,这似乎是目前其他答案默认的含义。
用UTF-16作为标准的宽编码,就像在Windows中一样,情况比较复杂,因为C ++标准不能胜任。 但是,以Windows为例,一个实际的可能性是sizeof(wchar_t)
= 2。应该注意的是,这个标准与这个问题的现有实践和实际考虑是冲突的,当理想是标准而不是标准化现有的做法,哪里有这样的。
现在我们终于可以处理这个问题了,
“上面的这些语句之间是否存在冲突,或者
sizeof(char) = 1
只是一个默认(定义)值,并且将由实现定义,取决于每个系统?
这是一个错误的二分法。 两种可能性不是相反的。 我们有
-
char
作为字符编码单元和内存寻址单元(字节)之间确实存在冲突。 如上所述,Pascal语言有关键字packed
处理冲突的一个方面,即存储与处理要求。wchar_t
的forms化要求与使用UTF-16编码的最广泛使用的系统(即Windows)中的UTF-16编码之间还有进一步的冲突。 -
sizeof(char) = 1
的定义:它不是系统相关的。 -
CHAR_BIT
是实现定义的,保证≥8。
不,没有冲突。 这两个语句引用了不同的字节定义。
UTF-16意味着该字节与八位 字节相同 – 一组8位。
在C ++语言中, 字节与char
相同。 对于C ++字节可以包含多less位没有限制。 C ++中的位数 – 字节由CHAR_BIT
macros常量定义。
如果您的C ++实现决定使用16位来表示每个字符,那么CHAR_BIT
将是16,每个C ++字节将占用两个UTF-16字节。 sizeof(char)
仍然是1,所有对象的大小将以16位字节来衡量。
char被定义为1个字节。 一个字节是最小的可寻址单元。 这是普通系统上的8位,但是在某些系统上,它是16位或32位,或者其他的(但是对于C ++来说,必须至less是8位)。
这有些令人困惑,因为在stream行的术语中, 字节用于技术上称为八位字节 (8位)的字节 。
所以,你的第二和第三个引号是正确的。 第一句话严格来说是不正确的。
正如C ++标准中的[intro.memory] / 1所定义的, char
只需要能够保存大约100个字符的基本执行字符集 (所有这些字符集都出现在ASCII的0-127范围内),而组成UTF-8编码的八位字节。 也许这就是作者所说的机器字符集。
在硬件是八位字节可寻址但字符集是Unicode的系统上, char
可能会保持8位。 但是, char16_t
和char32_t
(在C ++ 11中添加)的types被devise用于代码,而不是用于具有16位或32位字符集的系统的字符。
因此,如果系统使用char16_t
那么您将使用std::basic_string<char16_t>
而不是std::string
,依此类推。
究竟如何处理UTF-16将取决于系统select的实施细节。 Unicode是21位字符集,UTF-16是它的多字节编码; 所以系统可以使用类似Windows的路由,并使用带有UTF-16编码的std::basic_string<char16_t>
string; 或者可以使用原始Unicode代码点作为字符的std::basic_string<char32_t>
。
阿尔夫的文章详细解释了一些可能出现的问题。
不用引用标准就很容易给出答案,因为:
字节的定义不是8位 。 字节是任何大小,但最小的可寻址单元的内存。 最常见的是8位,但没有理由没有16位的字节。
C ++标准给出了更多的限制,因为它必须至less有8位。
所以不pipesizeof(char)总是1,没有问题。 有时候它会像8位,有时候是16位等等。