char 和 char[1] 之间的区别
在 C++ 中,使用 char 和 char[1] 之间有什么区别(如果有)。
示例:
struct SomeStruct
{
char x;
char y[1];
};
对于 unsigned char 是否也有同样的原因?
In C++ what is the difference (if any) between using char and char[1].
examples:
struct SomeStruct
{
char x;
char y[1];
};
Do the same reasons follow for unsigned char?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
主要区别在于您用来访问单个字符的语法。
我所说的“访问”是指使用语言中的各种运算符对其进行操作,与
char
数组相比,大多数或全部运算符在应用于char
时会执行不同的操作。这听起来好像x
和y
几乎完全不同。事实上,它们都“由”一个字符组成,但该字符以一种非常不同的方式表示。该实现可能会导致其他差异,例如,它可能会根据您使用的结构以不同的方式对齐和填充结构。但我怀疑它会。
运算符差异的一个示例是 char 是可分配的,而数组则不可分配:
但是
y
不可分配的事实并不能阻止SomeStruct
可分配:所有这些都与类型、
char
与否无关。某种类型的对象和该类型的大小为 1 的数组在内存中的内容几乎相同。顺便说一句,在上下文中,您“使用”
char
和char[1]
会产生很大的差异,有时这会让人感到困惑认为数组实际上是指针。不是您的示例,而是作为函数参数:在
bar
和baz
声明中提供的数字被 C++ 语言完全忽略。显然,有人在某个时候认为它作为一种文档形式对程序员很有用,表明函数 baz 期望其指针参数指向 12 个字符数组的第一个元素。在 bar 和 baz 中,
c
从来没有数组类型 - 它看起来像数组类型,但事实并非如此,它只是一种奇特的特殊情况语法,其含义与char *c 相同
。这就是为什么我在“use”上加上引号 - 你根本没有真正使用char[1]
,它只是看起来像它。The main difference is just the syntax you use to access your one char.
By "access" I mean, act upon it using the various operators in the language, most or all of which do different things when applied to a
char
compared with achar
array. This makes it sound as ifx
andy
are almost entirely different. If fact they both "consist of" one char, but that char has been represented in a very different way.The implementation could cause there to be other differences, for example it could align and pad the structure differently according to which one you use. But I doubt it will.
An example of the operator differences is that a char is assignable, and an array isn't:
But the fact that
y
isn't assignable doesn't stopSomeStruct
being assignable:All this is regardless of the type,
char
or not. An object of a type, and an array of that type with size 1, are pretty much the same in terms of what's in memory.As an aside, there is a context in which it makes a big difference which you "use" out of
char
andchar[1]
, and which sometimes helps confuse people into thinking that arrays are really pointers. Not your example, but as a function parameter:The numbers provided in the declarations of
bar
andbaz
are completely ignored by the C++ language. Apparently someone at some point felt that it would be useful to programmers as a form of documentation, indicating that the functionbaz
is expecting its pointer argument to point to the first element of an array of 12 char.In bar and baz,
c
never has array type - it looks like an array type, but it isn't, it's just a fancy special-case syntax with the same meaning aschar *c
. Which is why I put the quotation marks on "use" - you aren't really usingchar[1]
at all, it just looks like it.如果您确实在生产代码中将构造
char y[1]
视为结构体的最后一个成员,那么您很可能遇到过 结构黑客。这个短数组是真实但可变长度数组的替代品(回想一下,在 c99 之前,c 标准中没有这样的东西)。程序员总是会在堆上分配此类结构,并注意确保分配的大小足以满足他想要使用的数组的实际大小。
If you've actually seen the construct
char y[1]
as the last member of a struct in production code, then it is fairly likely that you've encountered an instance of the struct hack.That short array is a stand-in for a real, but variable length array (recall that before c99 there was no such thing in the c standard). The programmer would always allocate such structs on the heap, taking care to insure that the allocation was big enough for the actual size of array that he wanted to use.
除了 Steve 强调的用法上的符号差异之外,char[1] 还可以传递给例如
template。 void f(char(&a)[N])
,其中 char x = '\0'; f(&x); 不匹配。可靠地捕获数组参数的大小非常方便且令人放心。它也可能意味着不同的东西:要么实际长度可能更长(如 dmckee 所解释的),要么内容在逻辑上是一个 ASCIIZ 字符串(在这种情况下恰好为空),或者一个字符数组(这发生在有一个元素)。如果该结构是几个相关结构之一(例如,数组大小是模板参数的数学向量,或者某些 I/O 操作所需的内存布局的编码),那么完全有可能与其他字段存在某些相似性如果数组可能更大,则建议优先选择单字符数组,从而允许支持代码更简单和/或更普遍适用。
As well as the notational differences in usage emphasised by Steve, char[1] can be passed to e.g.
template <int N> void f(char(&a)[N])
, wherechar x = '\0'; f(&x);
wouldn't match. Reliably capturing the size of array arguments is very convenient and reassuring.It may also imply something different: either that the real length may be longer (as explained by dmckee), or that the content is logically an ASCIIZ string (that happens to be empty in this case), or an array of characters (that happens to have one element). If the structure was one of several related structures (e.g. a mathematical vector where the array size was a template argument, or an encoding of the layout of memory needed for some I/O operation), then it's entirely possible that some similarity with other fields where the arrays may be larger would suggest a preference for a single-character array, allowing support code to be simpler and/or more universally applicable.