X



C言語なら俺に聞け 158

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん (ブーイモ MMcf-4SjH)
垢版 |
2021/12/25(土) 12:11:46.61ID:xxeaCAplM
!extend:checked:vvvvv:1000:512
(新スレ立ての際上記コマンドを2行書き込んでください)
C言語の話題のみ取り扱います C++の話題はC++スレへ
質問には最低限の情報(ソース/コンパイラ/OS)を付ける
数行で収まらないソースは以下を適当に使ってURLを晒す
https://paiza.io/
https://ideone.com/
http://codepad.org/

C17
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf

C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf

C99
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
http://kikakurui.com/x3/X3010-2003-01.html

C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/

JPCERT C コーディングスタンダード
https://www.jpcert.or.jp/sc-rules/

※前スレ
C言語なら俺に聞け 157
https://mevius.5ch.net/test/read.cgi/tech/1624846971/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
0645デフォルトの名無しさん (ワッチョイ 03ad-b0/F)
垢版 |
2022/06/11(土) 15:01:54.40ID:s3NqXqGx0
ちょー初心者

引数付きの関数で引数が空のときにも意味を持たせたい
nanntoka(char adress)なんて関数で
呼び出し側がnantoka()と書いたときも意味を持たせる場合どうすりゃいいの?
null判定でいいんですか?
0647デフォルトの名無しさん (ワッチョイ 03ad-b0/F)
垢版 |
2022/06/11(土) 15:15:18.40ID:s3NqXqGx0
だよねー
やっぱ数値は工夫のしようがないから無理なのかー
やー助かりました
0649デフォルトの名無しさん (ワッチョイ 63d2-asUV)
垢版 |
2022/06/11(土) 15:48:15.36ID:nZnmEekY0
C++にはデフォルト引数があるし
オーバーロードもできる
Cでできるかは知らん

int f(const char*s = nullptr);
0654デフォルトの名無しさん (ワッチョイ cfae-/e9c)
垢版 |
2022/06/12(日) 05:58:21.10ID:rhQkMiRe0
>>651
できるぞ
第一引数なしで可変引数にするときは
void func();
と、省略記号なしで宣言する

ただし言うまでもないが
func();
で呼び出したときの第一引数は不定なので
使い途はない
0662デフォルトの名無しさん (スップ Sd1f-asUV)
垢版 |
2022/06/13(月) 08:40:16.72ID:si/cekt2d
int func(void); と
int func(...); に対する言及なしで
int func(); だけ出てきてるからまともな議論じゃないと思ってスルーしてたが

可変引数は >>651 で出てきてそれに合わせてるだけじゃねーの?
0663デフォルトの名無しさん (スップ Sd1f-asUV)
垢版 |
2022/06/13(月) 08:54:28.35ID:si/cekt2d
int func(void); だとそもそも引数なししか受け付けない。
int func(...); だと引数の型と個数を実装側が期待するものにしなければならない。間違えたら未定義動作。
int func(); だと引数の型がわからないまま関数を使う。間違えてたら未定義動作。

int func(...); の第1引数は普通は型を明示するから
int func(const char*, ...); のようになるが。
0667デフォルトの名無しさん (オッペケ Sr87-bFL4)
垢版 |
2022/06/13(月) 11:04:47.60ID:YiPaBYDZr
可変長引数では無理なのね
>>650の(2)の実装だとどうなるの
0668はちみつ餃子 ◆8X2XSCHEME (ワッチョイ ff3e-GGE9)
垢版 |
2022/06/13(月) 11:30:06.51ID:zy+KupId0
マクロでコンパウンドリテラルを作ってから (その個数と共に) 渡すという方法が取れると思う。
受け取る関数の型は >>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();
}
0669デフォルトの名無しさん (ワッチョイ cfae-/e9c)
垢版 |
2022/06/13(月) 11:35:06.46ID:BOW2YZM80
>>666
話が噛み合っていないな
引数の数も型も比べる相手がいないのに矛盾しようがない
そもそも関数原型を用意しましょうなんていうのはCにおいて後付けの推奨事項に過ぎない
既存のコードを否定するのは影響が大きすぎるからな
0671デフォルトの名無しさん (ワッチョイ cf63-GGE9)
垢版 |
2022/06/13(月) 11:48:35.71ID:cwJzo4Jp0
fn(void)
fn(int)

こういう2種類の引数を許容したとして
呼ばれた側はどう区別したら良いんだろう
コンパイル時に、別関数にアサインしたらいいのかな
その場合は受け取る関数も二つ用意してやらないと行けないな
0679デフォルトの名無しさん (ワッチョイ 835f-GGE9)
垢版 |
2022/06/13(月) 16:19:19.10ID:Bgq8kBxf0
まともに話す気なさそうだし、もういいや。

C言語では>>645に書かれてるようなことはできなくて、
>>654の「第一引数は不定」はどうせ未定義動作の間違い、
という点に異論が無ければ、これ以上語ることもない。
0680デフォルトの名無しさん (ワッチョイ cf63-GGE9)
垢版 |
2022/06/13(月) 16:34:27.02ID:cwJzo4Jp0
nantoka()と呼び出した場合、
呼び出された関数は、
nanntoka(char adress)として
スタック上からadressを取り出そうとするが
ここにある値はNULLではなく、不定値(所謂ゴミ)
NULL判定で回避はできない
0682デフォルトの名無しさん (アウアウウー Sa67-MmlY)
垢版 |
2022/06/13(月) 18:45:35.75ID:+5MOS3Faa
>>680
> スタック上からadressを取り出そうとするが
だからそれを実行するかどうかもわからんって話
未定義動作ってそういうもんだ
0683デフォルトの名無しさん (スッップ Sd1f-asUV)
垢版 |
2022/06/13(月) 18:53:43.72ID:HsopZ7m+d
グローバル変数 int exists_adress; を介してやれば引数あり/なし のモードを未定義動作を回避しつつ設定できそう
実用性など皆無だが
0684デフォルトの名無しさん (スップ Sd1f-7fB6)
垢版 |
2022/06/13(月) 19:17:35.58ID:ir4nxYTVd
>>682
読み出すまではできるだろ
戻りアドレスか関係ないレジスタの退避値が入っている
問題はここではエラーにならず次にこの値で何かしようとしたらクラッシュする可能性が高い
これは単にコンパイラを騙して原因がわかりにくいエラーを出す方法なだけ
全くなんの意味もない
0692デフォルトの名無しさん (ワッチョイ cf63-GGE9)
垢版 |
2022/06/13(月) 20:09:56.04ID:cwJzo4Jp0
引数セットするのは、呼び出し側
コンパイラが呼び出し側で引数がないと判定した結果、
気を利かせて呼び出さないコードを吐くって一体どういうことだろう

呼ばれた側は機械的にあるはずの引数にアクセスする
呼ばれる側はセットしてないなんて分からないからアクセスしてしまうぞ
0693デフォルトの名無しさん (オッペケ Sr87-bFL4)
垢版 |
2022/06/13(月) 20:10:29.53ID:8KDu5nutr
>「罠」がある(キリッ
とかお寒いこと書いちゃうくらいだしよほど視野が狭くなってたんだろうなぁ
0694デフォルトの名無しさん (アウアウウー Sa67-hiZJ)
垢版 |
2022/06/13(月) 20:15:33.10ID:iGSNe98na
stdcall と cdecl の話か?
どっちにしても引数省略されたのかされてないのか呼ばれた方では判らん
C++なら省略の代わりにデフォルト引数入れたりマングリングしたり出来るが
Cではどうしようもない
0700デフォルトの名無しさん (ワッチョイ ff01-MmlY)
垢版 |
2022/06/13(月) 22:14:04.47ID:PLcvpN2h0
>>697
> コンパイラが未定義動作とわかったらエラーか最低でもワーニングを出す
そんな義務はない
> コンパイラにはわからないからバグになるんだよ
同一翻訳単位ならわかるだろ
勘違いしてるのは君、と言うか君の知識が浅すぎるだけ

>>699
存在するかどうかは関係なく規格上はそう言う処理系でも規格準拠という話
0710デフォルトの名無しさん (ワッチョイ f369-Aiv4)
垢版 |
2022/06/14(火) 10:32:47.66ID:rBU/2bdp0
実体記述時と、宣言&呼び出し時とで、引数の型や個数の不一致
コンパイルが通るかもしれんけど、どう動くかわからないし
俺の環境ではこう動くからと、それを信じて採用するには怖すぎる
0713デフォルトの名無しさん (ワッチョイ f369-Aiv4)
垢版 |
2022/06/14(火) 10:50:39.67ID:rBU/2bdp0
省略時のデフォルト引数と(マングリング等による)別実装
C以前の言語でもありそうだし前者は検討してそうなもんだけど見送ったなりの理由があるんだろうか
0714デフォルトの名無しさん (ワッチョイ 835f-GGE9)
垢版 |
2022/06/14(火) 10:52:59.20ID:2fucKJss0
想定が合ってたということで改めて結論も明記しとくと、
>709 のプログラムが未定義動作を起こすのは不定な x の値を使用するからではなく、
func(int x) に対して引数の数が不正な関数呼び出し func() を行うからであって、
x の値を使用しない場合(例えば関数内を空にした場合など)ても未定義動作になる、という話ね。
0716デフォルトの名無しさん (ワッチョイ f369-Aiv4)
垢版 |
2022/06/14(火) 11:13:15.99ID:rBU/2bdp0
661の立場だと
 void func(int x) { }
 ・・・・・
 func();
は、記述のほうで x をリファレンスしてないからセーフで未定義には該当しないと読めるが
そいう主張なのかな
0717デフォルトの名無しさん (オッペケ Sr87-bFL4)
垢版 |
2022/06/14(火) 11:51:03.61ID:2oEiwFQbr
引っ込みつかなくなると大変だね
0721デフォルトの名無しさん (ワッチョイ ffad-L0LW)
垢版 |
2022/06/14(火) 19:11:20.40ID:DieH08Hx0
引き数の値で関数内の処理を分けるか普通に関数分ければいいやん
0724デフォルトの名無しさん (ワッチョイ ffad-/fjj)
垢版 |
2022/06/14(火) 23:50:32.80ID:dnqAP5Hg0
>>718
DLLの呼び出しみたいに呼び出し先の実装をコンパイラが知らない場合
例えば引数をスタックに積む呼び出し規約だと
↓正常な動作
1)戻り先のアドレスをスタックに積む
2)引数をスタックに積む
3)DLL側のコード実行時にpopしてスタックから引数ゲット
4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん
これが↓異常な動作
1)戻り先のアドレスをスタックに積む
2)なんもない
3)DLL側のコード実行時にpopしてスタックから引数ゲット
4)いろいろ処理してpopして戻り先アドレスをゲットしてりたーん
5)わし、迷子
ってなるんちゃうん?
引数がレジスタ渡しなら、ただ変な数値受け取るだけで済むけど、今ここでの話じゃ限定してないようだし
0727デフォルトの名無しさん (ワッチョイ cf63-GGE9)
垢版 |
2022/06/15(水) 00:43:20.78ID:kIvvyTdz0
引数をスタックに積んでから、戻りアドレスを積んでCallするなら、
func関数はスタック先頭位置にあるアドレスに戻るだけではないかな
積まれている引数はその下だからズレないと思う
0728デフォルトの名無しさん (ワッチョイ ffad-/fjj)
垢版 |
2022/06/15(水) 00:57:26.32ID:3+VQJWvy0
>>727
>引数をスタックに積んでから、戻りアドレスを積んでCallするなら、
逆だぞ
戻りアドレスをスタックに積んでから引数をスタックに積む、その状態でfuncをコールする
そうしないと、次のpopでは戻りアドレスを受け取ることになり、引数を受け取れない
コールされたfuncはpopし引数を受け取って処理(この間にスタックへのpush/popがあったりして)、最後にpopして戻りアドレスを受け取って呼び出し元に帰る
0735デフォルトの名無しさん (アウアウウー Sa67-iSSN)
垢版 |
2022/06/15(水) 15:38:51.27ID:IEWflW3Ga
>>728
馬鹿発見
■ このスレッドは過去ログ倉庫に格納されています