- 1 名前:デフォルトの名無しさん (ワッチョイ 0f63-sFbk) mailto:sage [2023/04/21(金) 14:05:20.18 ID:rqj2HSDF0.net]
- !extend:checked:vvvvv:1000:512
(新スレ立ての際上記コマンドを2行書き込んでください) C言語の話題のみ取り扱います C++の話題はC++スレへ 質問には最低限の情報(ソース/コンパイラ/OS)を付ける 数行で収まらないソースは以下を適当に使ってURLを晒す https://paiza.io/ https://ideone.com/ codepad.org/ C17 www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4713.pdf C11 www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf C23 最新ドラフト https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3047.pdf C99 www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf kikakurui.com/x3/X3010-2003-01.html C FAQ 日本語訳 www.kouno.jp/home/c_faq/ JPCERT C コーディングスタンダード https://www.jpcert.or.jp/sc-rules/ ※前スレ C言語なら俺に聞け 160 https://mevius.5ch.net/test/read.cgi/tech/1672191630/ VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
- 974 名前:デフォルトの名無しさん mailto:sage [2023/10/29(日) 15:24:11.31 ID:V/yNBYFm0.net]
- コンストラクタ用意したら、それはもはやCではない
- 975 名前:はちみつ餃子 mailto:sage [2023/10/29(日) 16:10:21.42 ID:C0ma4yse0.net]
- >>968
コンストラクタこそ要らないだろ。 関数として書けば済む話だから。 ああいうのは色んな機能と連携して便利になるので 個々に見てしまうとたいして便利ではない。
- 976 名前:デフォルトの名無しさん (ワッチョイ 1379-JwVi) mailto:sage [2023/10/29(日) 17:23:22.94 ID:x+5RB5aB0.net]
- >>968
Cでtypedef+無名構造体/共用体のペアはstruct tag書式より使われてると思うが これはstructをいちいち書かされるC固有の仕様の問題であって、C++では最初から型宣言自体のやり方が違う つまりCの仕様をC++に合わせる意味は無く、C++との互換性はどうでもいい
- 977 名前:デフォルトの名無しさん mailto:sage [2023/10/29(日) 22:25:46.25 ID:ce2BuRgD0.net]
- >>965
例外の無いCでのdeferの意味は、単に後処理(デストラクタ)をコンストラクタ(Cではmallocや初期化関数)の直下に書けるという意味がある 関数の下に書けばいいといっても、gotoで飛ばしてんじゃ、プログラミング言語として欠陥が有ると思うよ goto使うな→エラー処理で使えば綺麗に書けるよ!って、やっぱおかしいだろw
- 978 名前:デフォルトの名無しさん (ワッチョイ 1989-FUJr) mailto:sage [2023/10/29(日) 23:50:43.25 ID:eMkvRHiW0.net]
- defer って分からんのですが、関数単位での atexit() みたいなもの?
- 979 名前:デフォルトの名無しさん (ワッチョイ d95d-kYJB) mailto:sage [2023/10/30(月) 00:11:39.03 ID:2SouKz/I0.net]
- double* q = malloc(something);
defer { free(q); } ↑これ見れば一目瞭然だな exitと関数やブロックを抜ける時に発動する けど、Cは書かれた通りに動くという前提を少し逸脱してんだよね それでも絶対便利ではある 難しい問題だな
- 980 名前:デフォルトの名無しさん (ワッチョイ 1989-FUJr) mailto:sage [2023/10/30(月) 00:12:01.02 ID:hHEGE8Ol0.net]
- 合ってるよね、うん
それ(他言語の defer 相当機能)って、問題解決にC言語を採用する環境では、OS上のプロセスの切り出し単位の設計、にマッピングすれば済む事ではないのかな? 建設的な議論の参考ネタとして: perl言語が嫌われた理由の一つに「同じ事をいろんな書き方で書ける」言語設計ポリシーがあって、それは他人が書いたコードをメンテする立場だと「あらゆる書き方に精通してないとメンテできない」デメリットになり pythonはそれを反面教師として「同じ事はだいたいみんな同じ書き方になるような言語設計を目指す」ポリシーにした、と認識してます
- 981 名前:デフォルトの名無しさん (ワッチョイ 1989-FUJr) mailto:sage [2023/10/30(月) 00:33:24.74 ID:hHEGE8Ol0.net]
- ああ、ブロック単位なのね…
とすると、上手なC言語のプログラマー達が習慣的にやってきた方法は以下ですよね: ■実装すべき処理を関数にマッピングするとき(主処理、失敗時処理を)細かく分ける ■関数をイベントハンドラとして「登録する」流儀の ミドルレイヤを書いて、そのミドルシステム上で 実装対象の「意味のある処理単位」を書くよう、プロジェクト単位でコーディングルールを定め、守り&守らせ ■◯◯失敗時には△△を行う、を明確に設計し実装して、それが分かりやすい納入プログラムとする で解決してきた、と思います。 つまり defer 機能がなくても同じ事をやる手法は既に確立している。 前のレスでの主張と合わせ、defer 機能を追加しないのが正解、と言いたいです
- 982 名前:デフォルトの名無しさん (ワッチョイ 9b5f-zW/F) mailto:sage [2023/10/30(月) 01:02:35.88 ID:tKZ3J0Lw0.net]
- breakでいつでもブロックを離脱できればgotoより明確でスムーズでかっこよくdeferっぽいことできるよな
- 983 名前:デフォルトの名無しさん (ワッチョイ 937c-cQ99) [2023/10/30(月) 01:09:19.67 ID:SHIqNVOV0.net]
- かっこいいかなぁ、、、
- 984 名前:デフォルトの名無しさん (ワッチョイ 1989-FUJr) mailto:sage [2023/10/30(月) 01:25:52.81 ID:hHEGE8Ol0.net]
- >>978
{int rc=0; do{ ★始め 処理 rc=1; break; ★失敗した 処理 break; ★成功した } while(0); if(rc) { ★ 異常時処理 }} ★終り とかそういう話? こういうのを #define で「エセ構文糖」みたいに定義する人もいますよね。(自分はあまり好きじゃない。格好悪いと思う) C言語用の単体テストフレームワークで unity ってのがあります。unity ではテストコード内で 独自の try ~ catch 風文法を書けるのですが、それがまさに (setjmp longjmp も使って) #define でエセ構文糖風に実装してました。需要があれば再度調べてここで概要報告しますw
- 985 名前:はちみつ餃子 mailto:sage [2023/10/30(月) 09:24:19.57 ID:I7fISnX+0.net]
- >>975
Go の defer に倣うなら defer 文に書けるのは関数かメソッドの呼出し。 (式一般、文一般を書けるわけではない。) 呼出しは関数の末尾だが引数は書いてある場所で評価されるというルール。 C 風の文法で書くなら double* q = malloc(something); defer free(q); q=NULL; return; というように書いても malloc した場所はちゃんと free されることになる。 このルールのおかげで前準備と後始末を近い場所に書けて「対応関係は」一目瞭然と言えるが、 そのために変則的な評価規則が入ってるわけ。 式単位での順序が入れ替わるってだけじゃなくて引数の評価と関数の呼び出しが 分離されるってだいぶん変な仕組みだよな。
- 986 名前:デフォルトの名無しさん [2023/10/30(月) 10:15:21.12 ID:xnp7PI6ya.net]
- >>973-974
Nim の defer 良いよね
- 987 名前:デフォルトの名無しさん [2023/10/30(月) 10:15:44.95 ID:xnp7PI6ya.net]
- >>973-974
Nim の defer 良いよね
- 988 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 10:17:23.47 ID:hHEGE8Ol0.net]
- 正常ルートは終わる時 q==NULL なのに、その前の
defer free(q) したときのqの値でfree() するんですね うへぇ… 誤解釈してバグ出しそう てかこれは、ひねり出された意地悪サンプルで…実際のプログラミングでdefer式が効果的となる使用例ではない、ですよね?
- 989 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 10:34:41.68 ID:hHEGE8Ol0.net]
- この話で改めてあぶり出されるのは、
あるプログラミング言語を深く理解して「書ける」「読める」ようになることには「自分なりの 上手なエラー処理の書き方 を探して身に付ける」事が含まれる、って事ですよね。 それは人類の資産なんだけど、実際の存在場所は あまたのプログラマー達の脳内 であって、一朝一夕に書き換えられる物じゃない。 だから言語仕様を改定して新機能を足すのは、新言語を作る時よりは慎重になる必要がある、と解釈しました
- 990 名前:デフォルトの名無しさん [2023/10/30(月) 11:45:07.40 ID:Ccd5zWuDd.net]
- nullptrはもっと早く入れるべきだった。
- 991 名前:はちみつ餃子 mailto:sage [2023/10/30(月) 11:57:46.53 ID:I7fISnX+0.net]
- >>984
Go でどうだか知らんけど C に defer を入れたとしたらというテーマでの話なら malloc と free を対応づけるのは考えられる用途の筆頭でしょ。 逆にこういう変則的な評価規則を持ち込まないとしたら、 つまり defer 文に書いたものが単に return の直前に評価されるだけということにしたら 途中で書き換えられる可能性が出てきて 前準備と後始末が対応づいているかどうか一目瞭然とはいかなくなる。 どこかしらでなんか汚い感じにはなるよ。 そういう汚さを受け入れてもなお欲しいほどの利便性かというとやっぱり疑問は残る。 汚さを受け入れていいなら goto の汚さを受け入れるのとそんなに差があるとも思えないし。
- 992 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 12:40:32.59 ID:2SouKz/I0.net]
- >>980
意地でもgoto使いたくない時にはそれでもいいけど、それの欠点は中にswitch文を書くと、breakで抜けれるのはswitch文からだけになる事だな 自分ではwhileを抜けた気になって実は抜けてないという、微妙なバグを生み出す可能性があるなw
- 993 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 16:19:29.96 ID:hHEGE8Ol0.net]
- >>988
do {...} while(0) なので、必ず1回実行し、2回目はないです
- 994 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 16:52:46.78 ID:bW5EQkS/0.net]
- >>989
適当だけどこういうことでは? {int rc=0; do{ ★始め 処理1 siwtch(x){ case 0: rc=1; break; ★失敗した ※siwtchから抜けるだけでwhileからは抜け出せていない case 1: break; ★成功だけど処理2は実行しない ※siwtchから抜けるだけでwhileからは抜け出せていない case 2: break; ★成功で処理2も行う } 処理2 break; ★成功した } while(0); if(rc) { ★ 異常時処理 }} ★終り
- 995 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 16:58:35.91 ID:hHEGE8Ol0.net]
- >>990
おっしゃる事、分かります。具体的に書いてくれてありがとうm(_ _)m
- 996 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 17:01:08.71 ID:hHEGE8Ol0.net]
- >>987
はい… mallocとfreeを確保と解放の例とするのは異論ないです deferより一つ上位の話は、エラー処理をバグなく、分かりやすく書こうというテーマだ、で合ってますよね。 その上で、deferがないとこんな面倒なのが、deferがあるとこんなに分かりやすい 例がよいのです 確保と解放の書き方検討で、私が検討するのは例えばこんな感じです: ■(1)ある意味のある処理単位が、リソースを 2個以上使う 場合を考えると、1個の場合より検討がよく進む。特に、 ■■(1a)初期化が途中で失敗した場合、すでに確保が成功してしまった資源をどう解放するか ■■(1b)資源の変数は最初に、確保処理のエラー戻り値と同じ値で初期化をすると、スッキリする事が多い ■(2)正常ルートでの解放と、エラールートでの解放で、コードを共通とするか、別とするか。 ■■(2a)確保、主、開放 の処理を、同じ「関数」で書くのと、別の「関数」に分けるのはどちらが良いか ■■(2b)「goto エラーラベル;」を好きか嫌いか ■(3)プログラマーによる解放処理の前の 「if(確保済みなら)」のガードが、必要なもの(fcloseなど)と、不要なもの(free)があるので、マニュアル確認は要る もっと語りたいけど、レス分けます、というか時間を置きます。あまり一人が語りすぎると、嫌がる人もいますよね
- 997 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 17:09:39.89 ID:hHEGE8Ol0.net]
- てかキータで書いて、皆さんの意見を聞いて修正していったり、してみようかな…
- 998 名前:デフォルトの名無しさん mailto:sage [2023/10/30(月) 17:17:16.34 ID:hHEGE8Ol0.net]
- とりあえず次スレ立てました。即死防止の保守書き込みは要らない、で良いのかな?
C言語なら俺に聞け 162 https://mevius.5ch.net/test/read.cgi/tech/1698653580/
- 999 名前:デフォルトの名無しさん (スプッッ Sd73-cQ99) [2023/10/30(月) 18:42:32.58 ID:Ccd5zWuDd.net]
- >>994
乙。 あなたの男気に女気に惚れました。
- 1000 名前:はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 9b3e-g5YV) mailto:sage [2023/10/30(月) 22:27:42.13 ID:I7fISnX+0.net]
- Golang の defer はあくまで関数の終わりまで遅延させる (ブロックの終わりではない) ので
呼び出される defer の個数が動的になりうるんだな。 https://go.dev/tour/flowcontrol/13 この挙動も C には馴染まなさそうだな。
- 1001 名前:デフォルトの名無しさん (ワッチョイ 1379-JwVi) mailto:sage [2023/10/30(月) 22:37:34.66 ID:n3VNJX5I0.net]
- 俺は某画像ライブラリのリソーストラッカーみたいに開放が必要な物を全部紐付けて後で開放する仕掛けを使ってる
まあCには何にも縛られないのが良いんだし好きにしたらいいよ
- 1002 名前:デフォルトの名無しさん (ワッチョイ d95d-kYJB) mailto:sage [2023/10/30(月) 23:34:44.67 ID:2SouKz/I0.net]
- 構文的にはC#っぽく
using (double* p = malloc(...); free(p)) { p を使う } でも良いかも知れない これだと1ループのforに似ててCに良く馴染むな もちろんreturnとかexitで脱出してもfreeは呼ばれる
- 1003 名前:デフォルトの名無しさん (ワントンキン MM53-wL8D) [2023/10/31(火) 10:19:02.32 ID:i2gAy2CGM.net]
- そんなもんが規格に入るわけないんだから無駄話だろ
- 1004 名前:デフォルトの名無しさん (ワントンキン MM53-wL8D) [2023/10/31(火) 10:19:24.66 ID:i2gAy2CGM.net]
- うめ
- 1005 名前:1001 [Over 1000 Thread ID:Thread.net]
- このスレッドは1000を超えました。
新しいスレッドを立ててください。 life time: 192日 20時間 14分 5秒
- 1006 名前:過去ログ ★ [[過去ログ]]
- ■ このスレッドは過去ログ倉庫に格納されています
|

|