在 C++ 中,使用 char 和 char[1] 有什么区别(如果有的话)。
例子:
struct SomeStruct
{
char x;
char y[1];
};
unsigned char 是否遵循相同的原因?
在 C++ 中,使用 char 和 char[1] 有什么区别(如果有的话)。
例子:
struct SomeStruct
{
char x;
char y[1];
};
unsigned char 是否遵循相同的原因?
主要区别只是您用来访问一个字符的语法。
我所说的“访问”是指使用语言中的各种运算符对其进行操作,其中大多数或所有运算符在应用于 achar
与char
数组时会做不同的事情。这使它听起来好像x
并且y
几乎完全不同。如果事实上它们都“由”一个字符组成,但是该字符以非常不同的方式表示。
该实现可能会导致存在其他差异,例如它可以根据您使用的结构以不同的方式对齐和填充结构。但我怀疑它会。
运算符差异的一个示例是 char 是可分配的,而数组不是:
SomeStruct a;
a.x = 'a';
a.y[0] = 'a';
SomeStruct b;
b.x = a.x; // OK
b.y = a.y; // not OK
b.y[0] = a.y[0]; // OK
但是不可分配的事实y
并没有停止SomeStruct
可分配:
b = a; // OK
这一切都与类型无关char
。一个类型的对象和一个大小为 1 的类型的数组,就内存中的内容而言几乎相同。
顺便说一句,有一个上下文会产生很大的不同,你“使用”出char
and char[1]
,这有时会让人们误以为数组是真正的指针。不是您的示例,而是作为函数参数:
void foo(char c); // a function which takes a char as a parameter
void bar(char c[1]); // a function which takes a char* as a parameter
void baz(char c[12]); // also a function which takes a char* as a parameter
C++ 语言完全忽略bar
和的声明中提供的数字。baz
显然有人在某些时候觉得它作为一种文档形式对程序员很有用,表明该函数baz
期望它的指针参数指向一个 12 字符数组的第一个元素。
在 bar 和 baz 中,c
从来没有数组类型——它看起来像一个数组类型,但实际上不是,它只是一个花哨的特殊情况语法,与char *c
. 这就是为什么我把引号放在“使用”上——你根本没有真正使用char[1]
,它只是看起来像它。
如果您实际上已将构造char y[1]
视为生产代码中结构的最后一个成员,那么您很可能遇到了struct hack的实例。
那个短数组是一个真实但可变长度的数组的替代品(回想一下,在 c99 之前,c 标准中没有这样的东西)。程序员总是在堆上分配这样的结构,注意确保分配足够大,以适应他想要使用的数组的实际大小。
除了史蒂夫强调的用法上的符号差异外,char[1] 还可以传递给 eg template <int N> void f(char(&a)[N])
,而 wherechar x = '\0'; f(&x);
将不匹配。可靠地捕获数组参数的大小非常方便且令人放心。
它也可能暗示一些不同的东西:要么实际长度可能更长(如 dmckee 所解释),要么内容在逻辑上是 ASCIIZ 字符串(在这种情况下恰好为空),或者字符数组(发生有一个元素)。如果结构是几个相关结构之一(例如,数组大小是模板参数的数学向量,或某些 I/O 操作所需的内存布局的编码),那么与其他字段有一些相似性是完全可能的如果数组可能更大,则建议首选单字符数组,从而使支持代码更简单和/或更普遍适用。