掲示板利用宣言

 次のフォームをすべてチェックしてからご利用ください。

 私は

 題名と投稿者名は具体的に書きます。
 課題の丸投げはしません。
 ソースの添付は「HTML変換ツール」で字下げします。
 返信の引用は最小限にします。
 環境(OSとコンパイラ)や症状は具体的に詳しく書きます。
 返信の付いた投稿は削除しません。
 マルチポスト(多重投稿)はしません。

掲示板2

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧

No.29195

関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/09 01:04:57)


関数定義の一部である関数宣言子で識別子並びが空の場合, 関数が仮引数をもたないことを指定する。関数定義の一部でない関数宣言子の識別子並びが空の場合, 仮引数の個数及び型の情報がないことを指定する。

JIS X3010:2003 6.7.5.3 関数宣言子(関数原型を含む)
とのことですが,関数定義をしてしまうと,
「仮引数の個数及び型の情報がない」状態にはできないのでしょうか?

以下のコードではコンパイラによる型チェックが入らないため,
すんなりコンパイルできますが,funcは不正な仕方で呼び出されています。
int func(){}         // int func(void){} と同じ
int main(){func(0);} // int main(void){func(0);} と同じ


もし,関数定義をしても「仮引数の個数及び型の情報がない」状態に
できるのであれば, stdarg.h を使って, , ... を越えられるような気がするのですが。
# ↑は分かる人だけ分かってください。


この投稿にコメントする

削除パスワード

発言に関する情報 題名 投稿番号 投稿者名 投稿日時
<子記事> Re:関数定義で引数情報を無しにできるか? 29196 RiSK 2006/12/09 01:10:36
<子記事> Re:関数定義で引数情報を無しにできるか? 29197 RiSK 2006/12/09 01:20:06


No.29196

Re:関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/09 01:10:36)


typo.
> int func(){}         // int func(void){} と同じ
void func(){}        // void func(void){} と同じ



この投稿にコメントする

削除パスワード

No.29197

Re:関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/09 01:20:06)


>関数定義をしてしまうと,
>「仮引数の個数及び型の情報がない」状態にはできないのでしょうか?

もしかして

int func();
int func(){}
int main(){func(0);}

で,OKだったりするのかしら?


この投稿にコメントする

削除パスワード

No.29198

Re:関数定義で引数情報を無しにできるか?
投稿者---たかぎ(2006/12/09 11:53:20)
http://takagi.in/


>>関数定義をしてしまうと,
>>「仮引数の個数及び型の情報がない」状態にはできないのでしょうか?
>
>もしかして
>
>int func();
>int func(){}
>int main(){func(0);}
>
>で,OKだったりするのかしら?

コンパイルは通りますが、それはエラーの検出機能を抑制したからです。
6.5.2.2 関数呼出し では、関数原型を含まない型の関数呼出しに関して、
実引数の個数と仮引数の個数が等しくない場合, その動作は未定義とする。
とありますから、コンパイルエラーを回避できても正しくないことは確かです(すくなくとも移植性がありません)。

省略記号を使わずに関数定義をしたにも関わらず、可変個引数を使いたいということであれば、唯一の可能性としては次のような古いスタイルだけではないでしょうか。
#include <stdio.h>
#include <varargs.h>

void func(va_alist)
va_dcl
{
    va_list args;
    va_start(args);
    printf("%d\n", va_arg(args, int));
    va_end(args);
}
int main(void)
{
    func(123);
}
もちろん非標準ですが、これなら、省略記号無しに関数定義を行っているにもかかわらず、可変個引数を持つ関数になっています。



この投稿にコメントする

削除パスワード

No.29208

Re:関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/11 14:51:25)


レスありがとうございます。
自分でも調べ直しましたので,まとめます。


以下のコードは未定義動作を引き起こします。
void func(){}
int main(){func(0);}

関数定義の一部である関数宣言子で識別子並びが空の場合, 関数が仮引数をもたないことを指定する。

JIS X3010:2003 6.7.5.3
呼び出される関数を表す式によって指される式の型が関数が定義された型と適合しない場合,その動作は,未定義とする。

JIS X3010:2003 6.5.2.2



以下のコードは未定義動作を引き起こします。
void func();
void func(){}
int main(){func(0);}

コンパイルは通りますが、それはエラーの検出機能を抑制したからです。
6.5.2.2 関数呼出し では、関数原型を含まない型の関数呼出しに関して、
実引数の個数と仮引数の個数が等しくない場合, その動作は未定義とする。
とありますから、コンパイルエラーを回避できても正しくないことは確かです(すくなくとも移植性がありません)。



「仮引数の個数及び型の情報がない」ってのは,
あくまで呼び出す側に対してのもので,関数定義側では
(省略形式を含めて)仮引数の個数及び型の情報は明示ないしは明確になるようです。

第一引数も可変引数の一部にしようとする私の野望は標準の範囲では無理なようです。



ただ,6.5.2.2には
「関数原型を含む型を持つ場合,実引数の個数は,仮引数の個数と一致しなければならない。」
とあるのですが,
void func(); という関数原型を書いてしまうと,
どうやっても,関数原型と定義とを一致させるさせることができないような気がします。
私の理解が変なのだろうか?

あっ,逆にどんな定義を書いてもOKってことになるのかな?
それが「仮引数の個数及び型の情報がない」って事?
「エラーの検出機能を抑制した」って事?



ちなみに,
6.11.6 関数宣言子によると,
空の括弧と伴う関数宣言子(関数原型形式の仮引数型並びではない。)の使用は,廃止予定事項とする。

となっているから,この議論は将来無駄になりますw


この投稿にコメントする

削除パスワード

No.29209

Re:関数定義で引数情報を無しにできるか?
投稿者---たかぎ(2006/12/11 15:20:55)
http://takagi.in/


>void func(); という関数原型を書いてしまうと,
>どうやっても,関数原型と定義とを一致させるさせることができないような気がします。

「関数原型」というのは、仮引数型並びを含む関数型による宣言のことです。void func();は仮引数型並びを持ちませんので、関数原型にはなりません。
関数原型にしてもvoid型にしても、元々のC言語には無く、後からC++から持ってきたものなので、こんな変なことになっているのでしょう。

>となっているから,この議論は将来無駄になりますw

廃止予定と書かれているもので、実際に廃止になったケースはほどんどなかった気がします。
その記述は、「使ってくれるな」という気持ちを表すためだけのもので、おそらく将来もこの仕様はなくならないでしょう。



この投稿にコメントする

削除パスワード

No.29211

Re:関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/11 23:11:51)


>>void func(); という関数原型を書いてしまうと,
>>どうやっても,関数原型と定義とを一致させるさせることができないような気がします。
>
>「関数原型」というのは、仮引数型並びを含む関数型による宣言のことです。void func();は仮引数型並びを持ちませんので、関数原型にはなりません。

がーん。そうなのですか...

確認したところ,
6.2.7 適合型及び合成型 にその旨が書いてありました。
ついでにいうと 6.11.7(そして,よくよく考えると6.11.6) にも
ほのめかすような表現がありますね。

# 本当にさらっと,6.2.7, 6.11.7共に括弧書きの中で。こりゃ,気が付かないわ。
# おいっ!真面目に定義する気あるのか?

つまり,識別子並びopt をもつ関数型の場合は
関数原型とは呼ばないんですね。そして,型チェックが入らない。
基本的なことなのに,ようやく把握しましたよ。


なんで,識別子並びバージョンだと型チェックが入らないんだろ?
やっぱり歴史的経緯なんだろうなぁ。

>廃止予定と書かれているもので、実際に廃止になったケースはほどんどなかった気がします。
>その記述は、「使ってくれるな」という気持ちを表すためだけのもので、おそらく将来もこの仕様はなくならないでしょう。

廃止にもならず,型チェックも入らず,か。



では,訂正して質問し直します。
void func(); という宣言を書いてしまうと,
どうやっても,宣言と定義とを一致させるさせることができないような気がします。
これは,いったいどういう意味でしょうか?

そして,「関数原型」ではない関数の宣言の事はなんと呼ぶのでしょうか?
単なる「hoge型の関数宣言」とでも呼べばいいのでしょうか?

まだ,私が勘違いしていることがありますか?


この投稿にコメントする

削除パスワード

No.29212

Re:関数定義で引数情報を無しにできるか?
投稿者---たかぎ(2006/12/11 23:37:43)
http://takagi.in/


># 本当にさらっと,6.2.7, 6.11.7共に括弧書きの中で。こりゃ,気が付かないわ。

そうですよね。
昔からC言語を扱っている人にとっては、関数原型が無いことの方が常識的だったので、こんな風になったのかも。

>void func(); という宣言を書いてしまうと,
>どうやっても,宣言と定義とを一致させるさせることができないような気がします。
>これは,いったいどういう意味でしょうか?

仮引数型並びがない関数宣言は、もともと標準化以前に使われていた形式で、関数定義は分離形式で記述することを前提にしているようです。
この手の宣言は、あくまでも返却値型を指定するためのものですから、そもそも宣言と定義で引数を一致させる気など元々ないのです。

>そして,「関数原型」ではない関数の宣言の事はなんと呼ぶのでしょうか?

たぶん、気の利いた呼び方は無かったと思います。



この投稿にコメントする

削除パスワード

No.29213

Re:関数定義で引数情報を無しにできるか?
投稿者---RiSK(2006/12/12 00:00:31)


>># 本当にさらっと,6.2.7, 6.11.7共に括弧書きの中で。こりゃ,気が付かないわ。
>
>そうですよね。
>昔からC言語を扱っている人にとっては、関数原型が無いことの方が常識的だったので、こんな風になったのかも。

ふーむ。なるほど。

>仮引数型並びがない関数宣言は、もともと標準化以前に使われていた形式で、関数定義は分離形式で記述することを前提にしているようです。
>この手の宣言は、あくまでも返却値型を指定するためのものですから、そもそも宣言と定義で引数を一致させる気など元々ないのです。

返却値型かー。なるほどー。
軽視される引数たちかわいそう。

>>そして,「関数原型」ではない関数の宣言の事はなんと呼ぶのでしょうか?
>
>たぶん、気の利いた呼び方は無かったと思います。

分かりました。
とにかく廃止予定な関数宣言を書かなければ
関数原型にはなりそうですので,今後も気をつけたいと思います。

可変長引数はあきらめます。(と,ここでも言っておく)

これでこのスレッドは閉じます。
非常に有益でした。ありがとうございました。


この投稿にコメントする

削除パスワード

No.29223

Re:関数定義で引数情報を無しにできるか?
投稿者---Ban(2006/12/13 02:37:51)


>返却値型かー。なるほどー。
>軽視される引数たちかわいそう。

ISO/IEC9899の6.2.5 Typesの「関数の型(function type)」などが
戻り値偏重っぷりをよく出してると思います。

関数の型(function type)自体が「戻り値型からの派生型」だったりしますし。

# ゆえに、ポインタ型も関数の型も総称して「派生宣言子」と呼ばれ、
# 「Tのポインタ型p」が「T* p」であるように「Tを返す関数型f」が「T f()」になる。

<ISO/IEC9899>
-- snip --
A function type describes a function with specified return type.
A function type is characterized by its return type and the number and types of its parameters.
A function type is said to be derived from its return type,
and if its return type is T, the function type is sometimes called "function returning T".
The construction of a function type from a return type is called "function type derivation".
-- snip --
Array, function, and pointer types are collectively called derived declarator types.
-- snip --
</ISO/IEC9899>


この投稿にコメントする

削除パスワード

管理者用メニュー    ツリーに戻る    携帯用URL    ホームページ    ログ    タグ一覧