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についても同じ理由が続きますか?
主な違いは、1つの文字にアクセスするために使用する構文だけです。
「アクセス」とは、言語のさまざまな演算子を使用してそれに基づいて動作することを意味します。これらの演算子のほとんどまたはすべては、配列char
と比較して適用すると異なる動作をします。char
これにより、まるでほぼ完全に異なるようx
に聞こえます。y
実際には、両方とも1つの文字で「構成」されていますが、その文字は非常に異なる方法で表されています。
実装により、他の違いが生じる可能性があります。たとえば、使用する構造に応じて構造を異なる方法で整列およびパディングすることができます。しかし、私はそうなるとは思えません。
演算子の違いの例は、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
、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
bar
およびの宣言で提供される番号はbaz
、C++言語では完全に無視されます。どうやら、ある時点で誰かがドキュメントの形式としてプログラマーに役立つだろうと感じていたようです。これは、関数baz
が12文字の配列の最初の要素を指すポインター引数を期待していることを示しています。
barとbazでは、c
配列型はありません-配列型のように見えますが、そうではありません。これは、と同じ意味を持つ単なる特別な場合の構文char *c
です。だから私は「使用」に引用符を付けました-あなたは実際にはまったく使用char[1]
していません、それはちょうどそれのように見えます。
コンストラクトを本番コードの構造体の最後のメンバーとして実際に見た場合は、構造体ハックchar y[1]
のインスタンスに遭遇した可能性がかなりあります。
その短い配列は、実際の可変長配列の代用です(c99以前はc標準にはそのようなものがなかったことを思い出してください)。プログラマーは常にそのような構造体をヒープに割り当て、割り当てが使用したい配列の実際のサイズに対して十分な大きさになるように注意します。
Steve によって強調された使用法における表記上の違いと同様に、char[1] は、たとえばtemplate <int N> void f(char(&a)[N])
whereに渡される可能性がありchar x = '\0'; f(&x);
ます。配列引数のサイズを確実に取得できることは、非常に便利で安心です。
それはまた、何か違うことを暗示しているかもしれません: 実際の長さはもっと長いかもしれません (dmckee で説明されているように)、またはコンテンツが論理的に ASCIIZ 文字列 (この場合はたまたま空です)、または文字の配列 (それが起こります) であることのいずれかです。要素を 1 つ持つ)。構造体がいくつかの関連する構造体の 1 つであった場合 (たとえば、配列サイズがテンプレート引数であった数学的ベクトル、または I/O 操作に必要なメモリ レイアウトのエンコーディング)、他のフィールドとの類似性が完全に可能です。配列が大きくなる可能性がある場合は、単一文字の配列を優先することをお勧めします。これにより、サポート コードがよりシンプルになり、より普遍的に適用できるようになります。