2018/02/25

[c/c++]仮引数を書かない場合と戻り型未指定を実際にやってみる

昔のC言語に仕様としてあり、今となってはほぼ使われていない書き方や、推奨されていない書き方がある。
いくつかあるのかもしれんが、私が気付くのはこの2つだ。

  • 戻り値の型を書かないとint
  • 仮引数を省略すると...


知識として持っていて、実際にやったことが無かったので、やってみた。

01: #include <stdio.h>
02: #include <stdarg.h>
03: 
04: func()
05: {
06:     va_list argptr;
07:     va_start(argptr, 3);
08: 
09:     const char *str = va_arg(argptr, const char*);
10:     printf("%s\n", str);
11:     int a = va_arg(argptr, int);
12:     int b = va_arg(argptr, int);
13:     return a + b;
14: }
15: 
16: int main(void)
17: {
18:     int res = func("hello", 3, 8);
19:     printf("result=%d\n", res);
20: }


書くのは書けたが、ビルドが通らない。。。

$ gcc -std=c89 -o tst noarg.c
In file included from noarg.c:2:0:
noarg.c: In function ‘func’:
noarg.c:7:5: error: ‘va_start’ used in function with fixed args
      va_start(argptr, 3);
      ^

funcを、

func(int num, ...)

として、呼び出しの第1引数に何か整数を入れておくと、warningが出る(second parameter of ‘va_start’ not last named argument)ものの通るし、実行できる。
va_start()の第2引数をnumにすれば、warningも消える。


https://linuxjm.osdn.jp/html/LDP_man-pages/man3/stdarg.3.html

va_start()の第2引数は、引数リストのうちで最後にならんでいる引数名、となっている。
うーん、では、「引数名を省略したら...扱い」かどうか確認できないではないか。。。


上記リンクの「注意」「バグ」に説明が載っていた。
stdargでは許されていない、ということで、<varargs.h>を使えば動かせそうだ。

#error "GCC no longer implements <varargs.h>."

あー、gccでは徹底的に使えなくなってるのですな。
残念だが、ここであきらめよう。


01: #include <stdio.h>
02: #include <stdarg.h>
03: 
04: func(int num, ...)
05: {
06:     va_list argptr;
07:     va_start(argptr, num);
08: 
09:     const char *str = va_arg(argptr, const char*);
10:     printf("%s\n", str);
11:     int a = va_arg(argptr, int);
12:     int b = va_arg(argptr, int);
13:     return a + b;
14: }
15: 
16: int main()
17: {
18:     int res = func(3, "hello", 3, 8);
19:     printf("result=%d\n", res);
20: }


こそっと、main関数はreturnなくてもOK、というやつも使っている。
自分でmainを呼び出す処理を書くときは、サブルーチンコールではなくてジャンプで飛ばしてスタックの消費を減らしたりしてしまいがちだ。
C11だと「noreturnマクロなんてものがあるから、今後はそれを書いた方が親切かもしれん。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。