ISO/IEC在sizeof(char)中混淆不同的字符集编码,如UTF-16

kem*_*ded 37 c++ sizeof utf-16 language-lawyer

假设程序在具有UTF-16编码字符集的系统上运行.所以根据C++编程语言 - 第4页,第150页:

char可以保存机器字符集的字符.

→我认为char变量的大小是2字节.

但根据ISO/IEC 14882:2014:

sizeof(char),sizeof(signed char)并且sizeof(unsigned char)是1".

或者C++编程语言 - 第4页,第149页:

"[...],所以根据定义,char的大小是1"

→固定尺寸为1.

问题:上述这些语句之间是否存在冲突,或者sizeof(char) = 1只是默认(定义)值,并且实现定义取决于每个系统?

pax*_*blo 35

C++标准(和C,就此而言)有效地定义bytechar类型的大小,而不是 8位数量1.按照C++11 1.7/1(我的大胆):

C++内存模型中的基本存储单元是字节.一个字节至少足以包含基本执行字符集的任何成员和Unicode UTF-8编码形式的八位代码单元,并且由连续的位序列组成,其数量是实现定义的.

因此,表现sizeof(char)总是 1,不管是什么.

如果你想看看你的基线char变量(可能unsigned变体是最好的)实际上可以保持一个16位的值,你要查看的项目CHAR_BIT来自<climits>.这保存了char变量中的位数.


1许多标准,尤其是与通信协议相关的标准,octet对8位值使用更精确的术语.

  • @kembedded:不,如果基本字符集使用16位,那么**一个字节是16位宽.**你需要避免认为一个字节是8位宽.在C/C++中,它不一定如此.如果要引用8位值,请使用术语八位字节 - 一个字节可以是C++中的任何大小,只要它可以包含基础数据即可.如果你想要它处理所有的Unicode以及银河系中的每一个外星语言,你可以很容易地把它作为256位:-) (8认同)
  • 是的,定义了基本执行字符集.其中大约有90个符号. (2认同)
  • @kembedded,那是_exactly_对,尽管你持续使用字节来_sometimes_意味着8位:-)但是,我明白你得到了什么,我不确定_why_ ANSI/ISO没有像这么多的八位组路径其他标准.现在还为时已晚. (2认同)
  • @kembedded - 这几乎是正确的.我可能在这里看到语言问题而不是技术问题,但在"万一我使用UTF-8"应该"以防编译器使用UTF-8".这不是程序员所做的事情,而是编译器编写者决定做的事情. (2认同)

Che*_*Alf 28

是的,对于Rôles的C++混淆存在许多严重的冲突和问题char,但这个问题也混淆了一些事情.因此,一个简单的直接回答就是回答"是的","不"或"不知道"问题"你有没有停止殴打你的妻子?".唯一直接的答案是佛教徒"mu",没有问题.

因此,让我们先看看事实.


有关char类型的事实.

每比特的数量char由下式定义的执行给定的CHAR_BIT<limits.h>报头.此数字保证为8或更大.对于C++ 03及更早版本,保证来自C89标准中该符号的规范,C++标准指出(在非规范部分,但仍然)为"合并".对于C++ 11及更高版本,C++标准本身明确地给出了≥8保证.在大多数平台上CHAR_BIT是8,但在一些可能仍然存在的德州仪器数字信号处理器上它是16,并且已经使用了其他值.

无论的价值CHAR_BITsizeof(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(在[intro.memory]中):

" C++内存模型中的基本存储单元是字节.

这意味着在前面提到的TI DSP上,没有C++方法可以获得指向各个八位字节(8位部分)的指针.而这反过来意味着需要处理字节序的代码或者其他方式需要将char值视为八位字节序列,特别是对于网络通信,需要使用charCHAR_BIT8 的系统上没有意义的值来处理事物.它还意味着普通的C++窄字符串文字,如果它们符合标准,并且如果平台的标准软件使用8位字符编码,则会浪费内存.

废物方面是(或是)用Pascal语言直接解决,它区分打包字符串(每个字节多个八位字节)和解包字符串(每个字节一个八位字节),前者用于被动文本存储,后者是用于高效处理.

这说明了单个C++类型中三个方面的基本合并char:

  • 内存寻址单位,又称字节,

  • 最小的基本类型(对于类型来说会很好octet),和

  • 字符编码值单位.

是的,这是一场冲突.


有关UTF-16编码的事实.

Unicode是一组大量的21位代码点,其中大多数都是自己构成的字符,但其中一些与其他代码点组合形成字符.例如,可以通过组合"e"和"'" - 重音的代码点来形成具有类似"é"的重音的字符.由于这是一种通用机制,因此它意味着Unicode字符可以是任意数量的代码点,尽管它通常只有1.

UTF-16编码最初是基于每个代码点的原始Unicode 16位代码的兼容性方案,当Unicode扩展到每个代码点21位时.基本方案是原始Unicode的定义范围中的代码点表示为它们自己,而每个新的Unicode代码点表示为16位值的代理对.一小部分原始Unicode用于代理对值.

当时,基于每个代码点16位的软件示例包括32位Windows和Java语言.

在具有8位字节的系统上,UTF-16是宽文本编码的示例,即具有比基本可寻址单元宽的编码单元.然后,面向字节的文本编码被称为窄文本.在这样的系统上,C++ char适合后者,但不适合前者.

在C++ 03中,唯一适用于宽文本编码单元的内置类型是wchar_t.

但是,C++标准实际上需要wchar_t适用于代码点,对于现代21位/代码点Unicode来说,它意味着它需要是32位.因此,没有符合UTF-16编码值要求的C++ 03专用类型,每个值16位.由于历史原因,最流行的基于UTF-16的系统作为宽文本编码,即Microsoft Windows,定义wchar_t为16位,在Unicode扩展后与标准公然矛盾,但是,标准是不切实际的这个问题.一些平台定义wchar_t为32位.

C++ 11引入了新的种类char16_tchar32_t,其中前者是(设计成)适于UTF-16编码的值.


关于这个问题.

关于问题的陈述假设

"具有UTF-16编码字符集的系统

这可能意味着两件事之一:

  • 使用UTF-16作为标准窄编码的系统,或
  • 使用UTF-16作为标准宽编码的系统.

使用UTF-16作为标准窄编码CHAR_BIT≥16,并且(根据定义)sizeof(char)= 1.我不知道任何系统,即它似乎是假设的.然而,它似乎是当前其他答案中默认的含义.

使用UTF-16作为标准的宽编码,就像在Windows中一样,情况更复杂,因为C++标准不能胜任任务.但是,以Windows为例,一个实际的可能性是sizeof(wchar_t)= 2.而且应该注意到标准与现有的实践和实际考虑因素相冲突,当理想的是标准反而标准化现有的实践,其中有这样的.

现在终于我们能够处理这个问题,

" 上述这些语句之间是否存在冲突,或者sizeof(char) = 1只是默认(定义)值,并且实现定义取决于每个系统?

这是一种错误的二分法.这两种可能性不是对立的.我们有

  • char字符编码单元和存储器寻址单元(字节)之间确实存在冲突.如上所述,Pascal语言具有packed处理该冲突的一个方面的关键字,即存储与处理要求.wchar_t在最广泛使用的采用UTF-16编码的系统(即Windows)中,形式要求与其在UTF-16编码中的使用之间存在进一步的冲突.

  • sizeof(char) = 1 根据定义:它不依赖于系统.

  • CHAR_BIT 是实施定义,保证≥8.


AnT*_*AnT 9

不,没有冲突.这两个语句指的是字节的不同定义.

UTF-16意味着字节八位字节相同- 一组8位.

在C++语言中,字节与之相同char.C++字节可以包含的位数没有限制.C++中的位数 - 字节由CHAR_BIT宏常量定义.

如果您的C++实现决定使用16位来表示每个字符,CHAR_BIT则将为16,每个C++ - 字节将占用两个UTF-16字节.sizeof(char)仍然是1,所有对象的大小将以16位字节为单位进行测量.


M.M*_*M.M 7

char被定义为1个字节.字节是最小的可寻址单元.这在普通系统上是8位,但在某些系统上它是16位,或32位,或其他任何东西(但对于C++必须至少为8).

这有点令人困惑,因为在流行的术语中,字节用于技术上称为八位字节(8位)的字节.

所以,你的第二和第三个引用是正确的.严格来说,第一个引用是不正确的.

由C++标准中的[intro.memory] ​​/ 1定义,char只需要能够保存大约100个字符的基本执行字符集(所有字符都出现在0 - 127范围的ASCII中)和八位字节组成UTF-8编码.也许这就是作者对机器字符集的意思.


在硬件是八位字节可寻址但字符集是Unicode的系统上,它很可能char保持8位.但是有些类型char16_tchar32_t(在C++ 11中添加)设计用于代码,而不是char用于具有16位或32位字符集的系统.

因此,如果系统使用,char16_t那么您将使用std::basic_string<char16_t>而不是std::string,等等.

究竟如何处理UTF-16将取决于系统选择的实现细节.Unicode是一个21位字符集,UTF-16是它的多字节编码; 因此系统可以采用类似Windows的路由,并使用std::basic_string<char16_t>UTF-16编码进行字符串处理; 或者它可以std::basic_string<char32_t>用原始的Unicode代码点作为字符.

Alf的帖子详细介绍了可能出现的一些问题.


sen*_*fen 5

没有引用标准,很容易给出简单的答案,因为:

字节的定义不是8位.字节是任何大小但可寻址的最小内存单位.最常见的是8位,但没有理由没有16位字节.

C++标准给出了更多限制,因为它必须至少为8位.

因此,无论如何,sizeof(char)始终为1都没有问题.有时它会保持8位,有时是16位,依此类推.