开发者

Difference between char and char[1]

开发者 https://www.devze.com 2023-01-24 10:35 出处:网络
In C++ what is the difference (if any) between using char and char[1]. examples: struct SomeStruct { 开发者_如何转开发char x;

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?


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 a char array. This makes it sound as if x and y 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:

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

But the fact that y isn't assignable doesn't stop SomeStruct being assignable:

b = a; // OK

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 and char[1], and which sometimes helps confuse people into thinking that arrays are really pointers. Not your example, but as a function parameter:

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

The numbers provided in the declarations of bar and baz 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 function baz 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 as char *c. Which is why I put the quotation marks on "use" - you aren't really using char[1] at all, it just looks like it.


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.


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]), where char 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.

0

精彩评论

暂无评论...
验证码 换一张
取 消