warning: function call has aggregate value
warning: function returns an aggregate
警告:構造体を引数にした
警告:構造体を返却した
[-Waggregate-return]
■1.構造体を引数にすると遅くなる
大きなサイズの構造体を引数や戻り値にすると構造体を自動変数領域(大抵はスタック)にコピーするのでその分遅くなります。
■2.構造体引数とポインタ引数の比較実験
#include <stdio.h>
#include <assert.h>
#include <time.h>
#define MAX 100000
struct tag {//大きな構造体
int buf[MAX];
};
struct tag 構造体引数版(struct tag v,int idx) {
v.buf[idx] = idx ;
return v ;
}
void ポインタ引数版(struct tag *ptr,int idx) {
ptr->buf[idx] = idx ;
}
static struct tag x = {0};
static void 構造体引数版計測(void){
clock_t start = clock();
for (int i = 0; i < MAX; i++) {
x = 構造体引数版(x,i);
}
clock_t end = clock();
printf("%.2f秒\n", (double)((end - start) / CLOCKS_PER_SEC));
}
static struct tag y = {0};
static void ポインタ引数版計測(){
clock_t start = clock();
for (int i = 0; i < MAX; i++) {
ポインタ引数版(&y,i);
}
clock_t end = clock();
printf("%.2f秒\n", (double)((end - start) / CLOCKS_PER_SEC));
}
static void 結果比較(void){
for (int i = 0; i < MAX; i++) {
if(x.buf[i] != y.buf[i]){
assert(0);
}
}
}
int main(void) {
構造体引数版計測();
ポインタ引数版計測();
結果比較();
}
構造体を関数引数や戻り値に使用すると
構造体を丸ごと自動変数領域にコピーするので
構造体が大きくなればなるほど
処理時間を浪費します。
※自動変数領域とは多くの実装でスタックの事です。
このプログラムの例では
構造体引数返却版は数秒かかるのに対して、
ポインタ版計測はほぼ0秒です(=早すぎて計測できない)
■3.比較実験に使ったgccのオプション
この警告は
-Wall -Wextraオプションに含まれず、
-Waggregate-return オプションで表示されます。
併せて
-Wframe-larger-than=0 オプションを使用すると
スタックを浪費しているのが観測できます。
参考:
C-FAQ 2.9: どんな仕組みで構造体を引数で渡したり、関数の戻り値に使うことが できるのか。
http://www.kouno.jp/home/c_faq/c2.html#9