假设程序在具有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 .
Question: 上面这些语句之间是否存在冲突,或者 sizeof(char) = 1
只是一个默认(定义)值,并且实现定义取决于每个系统?
5 回答
C标准(和C,就此而言)有效地将
byte
定义为char
类型的大小,而不是8位数量1 . 根据C++11 1.7/1
(我的大胆):因此表达式
sizeof(char)
总是1,无论如何 .如果你想看看你是否基线
char
变量(可能unsigned
变体最好)实际上可以保持一个16位值,你要查看的项目是<climits>
来自<climits>
. 这保存char
变量中的位数 .1许多标准,尤其是与通信协议相关的标准,对于8位值使用更精确的术语
octet
.是的,对于
char
的C合并存在许多严重的冲突和问题,但这个问题也混淆了一些问题 . 因此,一个简单的直接回答就是回答“是的”,“不”或“不知道”问题“你有没有停止殴打你的妻子?” . 唯一的直接答案是the buddhist “mu”,没有问题 .因此,让我们先看看事实 .
关于char类型的事实 .
每个
char
的位数由<limits.h>
标头中定义的 CHAR_BIT 实现给出 . 此数字保证为8或更大 . 对于C 03及更早版本,保证来自C89标准中该符号的规范,C标准指出(在非规范部分,但仍然)为“合并” . 对于C 11及更高版本,C标准本身明确地给出了≥8保证 . 在大多数平台上CHAR_BIT
是8,但有些可能仍然存在Texas Instruments digital signal processors它是16,并且已经使用了其他值 .无论
CHAR_BIT
的值如何sizeof(char)
定义为1,即它不是实现定义的:C++11 §5.3.3/1 (在[expr.sizeof]中):
也就是说,
char
及其变体是记忆寻址的基本单位,这是 byte 的主要含义,无论是在普通语音中还是在C语言中:C++11 §1.7/1 (在[intro.memory]中):
这意味着在前面提到的TI DSP上,没有C方式获得指向单个 octets (8位部分)的指针 . 而这反过来意味着需要处理字节序的代码,或者其他方式需要将
char
值视为八位字节序列,特别是对于网络通信,需要使用char
值来处理char
它也意味着普通的C窄字符串文字,如果它们符合标准,并且如果平台的标准软件使用8位字符编码,则会浪费内存 .废物方面是(或是)用Pascal语言直接处理,它区分 packed strings (每个字节多个八位字节)和 unpacked strings (每个字节一个八位字节),前者用于被动文本存储,后者用于高效的处理 .
这说明了单个C类型
char
中三个方面的基本混淆:内存寻址单位,即.k.a . 字节,
最小的基本类型(对于
octet
类型会很好),和字符编码值单位 .
是的,这是一场冲突 .
关于UTF-16编码的事实 .
Unicode很大一组21位 code points ,其中大部分都是自己构成的字符,但其中一些与其他字符组合形成字符 . 例如 . 可以通过组合“e”和“'” - 重音的代码点来形成具有类似“é”的重音的字符 . 由于这是一种通用机制,因此它意味着Unicode字符可以是任意数量的代码点,尽管它通常只有1 .
UTF-16编码最初是基于每个代码点的原始Unicode 16位代码的兼容性方案,当Unicode扩展到每个代码点21位时 . 基本方案是原始Unicode的定义范围中的代码点表示为自身,而每个新的Unicode代码点表示为16位值的 surrogate pair . 一小部分原始Unicode用于代理对值 .
当时,基于每个代码点16位的软件示例包括32位Windows和Java语言 .
在具有8位字节的系统上,UTF-16是 wide text 编码的示例,即具有比基本可寻址单元宽的编码单元 . 面向字节的文本编码则称为 narrow text . 在这样的系统上,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_t 和 char32_t ,其中前者(设计为)适用于UTF-16编码值 .
关于这个问题 .
关于问题的陈述假设
这可能意味着两件事之一:
使用UTF-16作为标准窄编码的系统,或
使用UTF-16作为标准宽编码的系统 .
使用UTF-16作为标准窄编码
CHAR_BIT
≥16,并且(根据定义)sizeof(char)
= 1.我不知道任何系统,即它似乎是假设的 . 然而,它似乎是当前其他答案中默认的含义 .使用UTF-16作为标准的宽编码,就像在Windows中一样,情况更复杂,因为C标准不能胜任任务 . 但是,以Windows为例,一个实际的可能性是
sizeof(wchar_t)
= 2.而且应该注意到标准与现有实践和实际考虑因素相冲突,当理想是标准反而标准化现有实践时,哪里有这样的 .现在终于我们能够处理这个问题,
这是一种错误的二分法 . 这两种可能性不是对立的 . 我们有
char
作为字符编码单元和作为内存寻址单元(字节)确实存在冲突 . 如上所述,Pascal语言具有关键字packed
来处理该冲突的一个方面,即存储与处理要求 . 在wchar_t
的形式要求与使用UTF-16编码的最广泛使用的系统(即Windows)中使用UTF-16编码之间存在进一步的冲突 .根据定义
sizeof(char) = 1
:它不依赖于系统 .CHAR_BIT
是实现定义的,保证≥8 .不,没有冲突 . 这两个语句指的是字节的不同定义 .
UTF-16意味着字节与八位字节相同 - 一组8位 .
在C语言中,字节与
char
相同 . C -byte可以包含的位数没有限制 . C -byte中的位数由CHAR_BIT
宏常量定义 .如果您的C实现决定使用16位来表示每个字符,则
CHAR_BIT
将为16,并且每个C -byte将占用两个UTF-16字节 .sizeof(char)
仍然是1和所有对象的大小将以16位字节为单位进行测量 .char被定义为1个字节 . 字节是最小的可寻址单元 . 这在普通系统上是8位,但在某些系统上它是16位,或32位,或其他任何东西(但对于C必须至少为8) .
这有点令人困惑,因为在流行的术语中,字节用于技术上称为八位字节(8位)的字节 .
所以,你的第二和第三个引用是正确的 . 严格来说,第一个引用是不正确的 .
根据C标准中[intro.memory] / 1的定义,
char
只需要能够保存大约100个字符的基本执行字符集(所有这些字符都出现在0 - 127范围的ASCII中),并且构成UTF-8编码的八位字节 . 也许这就是作者对机器字符集的意思 .在硬件是八位字节可寻址但字符集是Unicode的系统上,
char
可能仍为8位 . 但是,有类型char16_t
和char32_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编码;或者它可以用原始Unicode代码点作为字符std::basic_string<char32_t>
.Alf的帖子详细介绍了可能出现的一些问题 .
没有引用标准,很容易给出简单的答案,因为:
Definition of byte is not 8 bits . 字节是任何大小但可寻址的最小内存单位 . 最常见的是8位,但没有理由没有16位字节 .
C标准给出了更多限制,因为它必须至少为8位 .
因此,无论如何,sizeof(char)始终为1都没有问题 . 有时它会保持8位,有时是16位,依此类推 .