Cでは、関数から配列を返すことはできず、配列へのポインターを返すことを知っています。しかし、structs
の特別な点は何かを知りたいのですが、配列が含まれている場合でも、関数によって関数を返すことができるようになります。
struct
ラッピングが次のプログラムを有効にするのはなぜですか?
#include <stdio.h>
struct data {
char buf[256];
};
struct data Foo(const char *buf);
int main(void)
{
struct data obj;
obj = Foo("This is a sentence.");
printf("%s\n", obj.buf);
return 0;
}
struct data Foo(const char *buf)
{
struct data X;
strcpy(X.buf, buf);
return X;
}
同じ質問をするより良い方法は、「配列の特別な点」です。なぜなら、struct
sではなく、特別な処理が付加された配列だからです。
ポインターによる配列の受け渡しの動作は、Cの元の実装にまでさかのぼります。配列はポインターに「減衰」し、特に言語に不慣れな人々の間でかなりの混乱を引き起こします。一方、構造体は、int
s、double
sなどの組み込み型のように動作します。これには、 を除く、struct
に埋め込まれた配列が含まれます。 柔軟な配列メンバー 、コピーされません。
まず最初に、C11
、§6.8.6.4、return
ステートメント、(emphasis mine)
式を含む
return
ステートメントが実行されると、式の値が返されますが関数呼び出し式の値として呼び出し元に返されます。
構造変数valueが返されるため、構造変数を返すことは可能です(そして正しい)。これは、プリミティブデータ型を返すことに似ています(たとえば、int
を返す)。
一方、arrayを返す場合は、return <array_name>
、基本的に配列の最初の要素のアドレスを返します注意、配列が呼び出された関数に対してローカルである場合、呼び出し側で無効になります。そのため、そのように配列を返すことはできません。
したがって、TL; DR、何もありませんspecial with struct
s、専門はarraysにあります。
注意:
引用符C11
もう一度、§6.3.2.1、(私の強調)
sizeof
演算子のオペランドである場合を除き、_Alignof
演算子、または単項&
演算子、または配列の初期化に使用される文字列リテラル、型を持つ式''型の配列 ''は、型'を持つ式に変換されます「型へのポインター」配列オブジェクトの初期要素を指しますであり、左辺値ではありません。 [...]
struct
型について特別なことはありません。 array型には特別なものがあり、関数から直接返されるのを防ぎます。
struct
式は、他の非配列型の式と同様に扱われます。 struct
の-値に評価されます。だからあなたのようなことをすることができます
struct foo { ... };
struct foo func( void )
{
struct foo someFoo;
...
return someFoo;
}
式someFoo
は、struct foo
オブジェクトの値に評価されます。オブジェクトのコンテンツが関数から返されます(それらのコンテンツに配列が含まれている場合でも)。
配列式の扱いは異なります。 sizeof
演算子または単項&
演算子のオペランドではない場合、または宣言内の別の配列を初期化するために使用される文字列リテラルでない場合、式は「T
の配列」を「T
へのポインター」と入力すると、式の値は最初の要素のアドレスになります。
したがって、配列式への参照は自動的にポインター値に変換されるため、関数から配列値によるを返すことはできません。