C言語なら俺に聞け 158
■ このスレッドは過去ログ倉庫に格納されています
=と==は、はっきり区別されてるだろ 連動して常に等しいという規則ならマクロでやればいいし A=1 B=2 C=3 A=B=C PRINT A,B,C >>638 BとCが等しいかの比較結果が A に入る C言語ではA=B=C;でAとBにCの値が入るはずだが C A=1, B=1, C=1 BASIC A=-1, B=1, C=1 ちょー初心者 引数付きの関数で引数が空のときにも意味を持たせたい nanntoka(char adress)なんて関数で 呼び出し側がnantoka()と書いたときも意味を持たせる場合どうすりゃいいの? null判定でいいんですか? だよねー やっぱ数値は工夫のしようがないから無理なのかー やー助かりました C++にはデフォルト引数があるし オーバーロードもできる Cでできるかは知らん int f(const char*s = nullptr); 普通にはできないからやるな (1) printfみたいにやる方法 (2) __VA_ARGS__でやる方法 があるぞい >>650 printfみたいな可変引数でも第一引数は必要なので純粋に引数なしってのはできなかったはず。 >>651 できるぞ 第一引数なしで可変引数にするときは void func(); と、省略記号なしで宣言する ただし言うまでもないが func(); で呼び出したときの第一引数は不定なので 使い途はない >>654 > nanntoka(char adress)なんて関数で って書いてあるのに... >>656 > 呼び出し側がnantoka() とも書いてあるだろ 何が言いたい? >>654 > 第一引数は不定なので いいえ。 未定義動作です。 >>657 勝手に端折るなよ、 書いてあるのは > 呼び出し側がnantoka()と書いたときも意味を持たせる場合どうすりゃいいの? で、答えはできない つまり >>654 > できるぞ がアホだってことな >>654 >第一引数なしで可変引数にするときは 可変引数になってないね 全然意味のない書き込みだね… >>658 不定の値にアクセスしたら未定義の動作だね 何が言いたい? >>659 幼児レベルの罵倒語が必要か? 654は正しいのか誤っているのかどっちだ? >>660 では聞くが可変引数って何だ? JIS X3010にそんな用語はないが int func(void); と int func(...); に対する言及なしで int func(); だけ出てきてるからまともな議論じゃないと思ってスルーしてたが 可変引数は >>651 で出てきてそれに合わせてるだけじゃねーの? int func(void); だとそもそも引数なししか受け付けない。 int func(...); だと引数の型と個数を実装側が期待するものにしなければならない。間違えたら未定義動作。 int func(); だと引数の型がわからないまま関数を使う。間違えてたら未定義動作。 int func(...); の第1引数は普通は型を明示するから int func(const char*, ...); のようになるが。 >>661 いいえ。 一致しない引数で関数を呼出そうとすることが未定義です。 >>664 一致しないって何と何が? funcについて仮引数は宣言されていない よって実引数との型の比較行われず 一致にも不一致にもあたらないぞ >>665 いいえ。 どこかに関数定義は存在し、関数定義 (の仮引数) とその関数呼出し (の実引数) との矛盾 (引数の数があわない・型が適合しない) は許されていません。 可変長引数では無理なのね >>650 の(2)の実装だとどうなるの マクロでコンパウンドリテラルを作ってから (その個数と共に) 渡すという方法が取れると思う。 受け取る関数の型は >>645 の通りではできないけど。 #include <stdio.h> #define foo(...) bar(sizeof((char[]){0, __VA_ARGS__}), (char[]){0, __VA_ARGS__}) void bar(int n, char* args) { if(n==1) { printf("no argment.\n"); } else { printf("argment is %c.\n", args[1]); } } int main(void) { foo('a'); foo(); } >>666 話が噛み合っていないな 引数の数も型も比べる相手がいないのに矛盾しようがない そもそも関数原型を用意しましょうなんていうのはCにおいて後付けの推奨事項に過ぎない 既存のコードを否定するのは影響が大きすぎるからな >>661 自分で「可変引数にするときは」と言っておいて なにが「そんな用語はない」だよ 頭おかしい fn(void) fn(int) こういう2種類の引数を許容したとして 呼ばれた側はどう区別したら良いんだろう コンパイル時に、別関数にアサインしたらいいのかな その場合は受け取る関数も二つ用意してやらないと行けないな 区別はできない 引数を見ようとしたら結果は不定になる 単なるバグだよ (2)の想定はこれだった https://wandbox.org/permlink/EidRL6a8uqiszn2m これも引数0個のときは##__VA_ARGS__か__VA_OPT__が必要で まずかったな >>669 関数定義とその呼び出しを比較するって書かれてるのに、きみが無視するから噛み合わないんだよ。 >>674 void func() { } /* 定義 */ int main() { func(); /* 呼び出し */ } どこが矛盾なんだ? # 迂闊な答えをすると罠があるから気をつけな >>670 その時点ではアバウトな言葉遣いが容認される流れだったが 厳密さを求める流れにあんたが変えたんだよ >>675 その例だけなら矛盾しないね。でも引数渡せないから>645のやりたかったことはできないよね。 >>677 引数が空のときにに意味を持たせるんだったな void func() { puts("no arguments are given"); } int main() { func(); } # さっき言った「罠」がまだここにある まともに話す気なさそうだし、もういいや。 C言語では>>645 に書かれてるようなことはできなくて、 >>654 の「第一引数は不定」はどうせ未定義動作の間違い、 という点に異論が無ければ、これ以上語ることもない。 nantoka()と呼び出した場合、 呼び出された関数は、 nanntoka(char adress)として スタック上からadressを取り出そうとするが ここにある値はNULLではなく、不定値(所謂ゴミ) NULL判定で回避はできない >>678 Once again, once again, you're on your own Who's to blame? who's to blame? it's such a shame No-one ever hears your name, or plays your game >>680 > スタック上からadressを取り出そうとするが だからそれを実行するかどうかもわからんって話 未定義動作ってそういうもんだ グローバル変数 int exists_adress; を介してやれば引数あり/なし のモードを未定義動作を回避しつつ設定できそう 実用性など皆無だが >>682 読み出すまではできるだろ 戻りアドレスか関係ないレジスタの退避値が入っている 問題はここではエラーにならず次にこの値で何かしようとしたらクラッシュする可能性が高い これは単にコンパイラを騙して原因がわかりにくいエラーを出す方法なだけ 全くなんの意味もない >>684 だからコンパイラは読み出すコードを吐く義務はない 未定義動作とわかった時点で呼び出しすらしないコードを吐く可能性もある 未定義動作ってそういうもんだ 読み出さなければ、実行時エラーにならないだろう なんで、なるの? 呼ばれた側の関数は、adressに入っている(はずの)値を使うんだぜ コード吐かなければ、それこそコンパイラのバグになるぞ 実際に呼び出すコードは、呼ばれた側の関数に実装されるが、 呼び出し側の引数セットありと、引数セット無しで、 違うコードが実行されたりするのか? 何が起こっても不思議ではない未定義派と、コンパイラ実装は実質こうなってる派で話が噛み合うはずがないと思うの。 信仰と言うより、勘違いだろう 恥ずかしくて後に引けなくなった感じ 引数セットするのは、呼び出し側 コンパイラが呼び出し側で引数がないと判定した結果、 気を利かせて呼び出さないコードを吐くって一体どういうことだろう 呼ばれた側は機械的にあるはずの引数にアクセスする 呼ばれる側はセットしてないなんて分からないからアクセスしてしまうぞ >「罠」がある(キリッ とかお寒いこと書いちゃうくらいだしよほど視野が狭くなってたんだろうなぁ stdcall と cdecl の話か? どっちにしても引数省略されたのかされてないのか呼ばれた方では判らん C++なら省略の代わりにデフォルト引数入れたりマングリングしたり出来るが Cではどうしようもない >>688-689 ,691-692 コンパイルエラーとして全くコードを吐かないという事すら可能なのに何を言ってるんだよ... 今時未定義動作すら考慮して最適化したりしてる時代なんだぞw https://qiita.com/kaityo256/items/d2677e178be0180482e8 >>686 何か勘違いしてないか コンパイラが未定義動作とわかったらエラーか最低でもワーニングを出す コンパイラにはわからないからバグになるんだよ 一体どこのコンパイラがコード吐かずに停止するんだよ >>697 > コンパイラが未定義動作とわかったらエラーか最低でもワーニングを出す そんな義務はない > コンパイラにはわからないからバグになるんだよ 同一翻訳単位ならわかるだろ 勘違いしてるのは君、と言うか君の知識が浅すぎるだけ >>699 存在するかどうかは関係なく規格上はそう言う処理系でも規格準拠という話 法解釈論「人殺しは違法であり罰される」 実運用論「証拠を完璧に隠滅できれば罰されない」 意固地になっちゃってるから何言っても無駄 意固地になるとアスペチックになるのか アスペチックだから意固地になりやすいのか 意固地もなにも未定義動作なんて規格の話なんだから実運用論とか言われてもねw >>679 第一引数が不定とは、第一引数を何らかの方法で取り出した場合の話だが おまえさん、その方法はどんな方法を想定しているんだ? >>707 >654が言ってるのはどうせこんなのだろうと思ってた。 https://wandbox.org/permlink/aiZH8Ytc91RyQ7HL #include <stdio.h> void func(); int main() { func(); } void func(int x) { printf("%d\n", x); } 実体記述時と、宣言&呼び出し時とで、引数の型や個数の不一致 コンパイルが通るかもしれんけど、どう動くかわからないし 俺の環境ではこう動くからと、それを信じて採用するには怖すぎる >>709 654は俺でまあそんなとこだが 俺は今679に聞いている おそらく「654と同じ」とかなんとか言って 自分の手の内は隠したまま人の批判をするんだろうけどな >>711 え? 679 (ワッチョイ 835f-GGE9) だから答えたのに何でよくわからんイチャモンつけられてんの? いやまぁ、予想通りで結論に異論無いならいいんだけどさ。 省略時のデフォルト引数と(マングリング等による)別実装 C以前の言語でもありそうだし前者は検討してそうなもんだけど見送ったなりの理由があるんだろうか 想定が合ってたということで改めて結論も明記しとくと、 >709 のプログラムが未定義動作を起こすのは不定な x の値を使用するからではなく、 func(int x) に対して引数の数が不正な関数呼び出し func() を行うからであって、 x の値を使用しない場合(例えば関数内を空にした場合など)ても未定義動作になる、という話ね。 >>712 ほらな、やっぱり自分の手の内は晒さない 661の立場だと void func(int x) { } ・・・・・ func(); は、記述のほうで x をリファレンスしてないからセーフで未定義には該当しないと読めるが そいう主張なのかな 実装の話 関数側でスタックに詰まれた引数をクリーンアップする呼び出し規約(pascalcall や stdcall) だと 明後日に飛んでいくのか 引き数の値で関数内の処理を分けるか普通に関数分ければいいやん 普通の人ならそうするが、 普通で無い方法が無いかを いろいろ議論している 暇つぶしとも言う >>718 DLLの呼び出しみたいに呼び出し先の実装をコンパイラが知らない場合 例えば引数をスタックに積む呼び出し規約だと ↓正常な動作 1)戻り先のアドレスをスタックに積む 2)引数をスタックに積む 3)DLL側のコード実行時にpopしてスタックから引数ゲット 4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん これが↓異常な動作 1)戻り先のアドレスをスタックに積む 2)なんもない 3)DLL側のコード実行時にpopしてスタックから引数ゲット 4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん 5)わし、迷子 ってなるんちゃうん? 引数がレジスタ渡しなら、ただ変な数値受け取るだけで済むけど、今ここでの話じゃ限定してないようだし 呼び出しって引数をスタックに積んでから、呼び出すんじゃなかったかな >>725 そうだよ だから func(int);な関数をfunc(void); で呼び出したらスタックにずれが生じる可能性がある 引数をスタックに積んでから、戻りアドレスを積んでCallするなら、 func関数はスタック先頭位置にあるアドレスに戻るだけではないかな 積まれている引数はその下だからズレないと思う >>727 >引数をスタックに積んでから、戻りアドレスを積んでCallするなら、 逆だぞ 戻りアドレスをスタックに積んでから引数をスタックに積む、その状態でfuncをコールする そうしないと、次のpopでは戻りアドレスを受け取ることになり、引数を受け取れない コールされたfuncはpopし引数を受け取って処理(この間にスタックへのpush/popがあったりして)、最後にpopして戻りアドレスを受け取って呼び出し元に帰る 戻りアドレスをスタックに積むのは、機械語のCALL命令が行うんでしょう? VCでアセンブラソース出力させてみました int main() { call(1); call(); return 0; } int call() { return 0; } _main PROC ; Line 2 push ebp mov ebp, esp ; Line 3 push 1 call _call add esp, 4 ; Line 4 call _call ; Line 5 xor eax, eax ; Line 6 pop ebp ret 0 _main ENDP _call PROC ; Line 8 push ebp mov ebp, esp ; Line 9 xor eax, eax ; Line 10 pop ebp ret 0 _call ENDP フレームポインタってのもあって まあなんでもいいんです >729 全てのCPUにCALL相当の命令があるとは限らないってことを頭の片隅に。 CALL命令のないCPUにCってどういう風に実装するのかな キッと神様のような人だろうと思う ■ このスレッドは過去ログ倉庫に格納されています
read.cgi ver 07.5.5 2024/06/08 Walang Kapalit ★ | Donguri System Team 5ちゃんねる