C言語の設計ミスった危険な関数トップ10決めようぜ
0050デフォルトの名無しさん
垢版 |
2019/12/11(水) 06:55:08.36ID:IbA4V9X0
>>46
メモリが640kバイトしか使えなかった頃からのものだしな
0052デフォルトの名無しさん
垢版 |
2019/12/11(水) 15:20:43.27ID:JkExA39E
大昔って端末やエディタなんかでも1行256とか1024バイト程度しか扱えなかったばず
0053デフォルトの名無しさん
垢版 |
2019/12/11(水) 15:32:22.68ID:8OP/pbId
256 の時代は割と長かった希ガス
0054デフォルトの名無しさん
垢版 |
2019/12/13(金) 06:37:32.10ID:o1f1J6fH
昔は1行の長さを先に決めてファイルをクリエイトしました
途中で変更はできません
0055デフォルトの名無しさん
垢版 |
2019/12/14(土) 13:26:55.02ID:TlZt0bii
関数そのものじゃないが
breakにラベル指定出来なかったのは設計ミスやろ
0057デフォルトの名無しさん
垢版 |
2019/12/14(土) 22:43:29.04ID:8CJijD11
gotoはラベルのスコープが広いから使いにくい。ループごとに別のラベル名を
付けないといけないし、ラベル名を別のループ用のものと書き間違えると
意図しない所へ飛んで行ってしまう。スパゲッティでバグの元。

ループにラベルを付ければ、スコープがそのループ内に限定され、そのループの
外にある別のループに同じラベル名を付けることができるから、書きやすく
読みやすい。例えば、こんな感じ。

for @outer (i = 1; i <= 3; i++) {
  for (j = 1; j <= 3; j++) {
    printf("%d, %d\n", i, j);
    if (i * j > 3) break @outer;
  }
}
for @outer (i = 1; i <= 5; i++) {
  for (j = 1; j <= 5; j++) {
    printf("%d, %d\n", i, j);
    if (i * j > 5) break @outer;
  }
}
0061デフォルトの名無しさん
垢版 |
2019/12/15(日) 09:51:38.77ID:5sPbacoo
ネストの数がわからないような巨大な構造は
それだけで最低だ
そんなんだと名前付きループにした所で
@outerなんて名前が使い回されて
同じ名前のループがネストされて
それこそ難読コードになる
それならユニークなラベルによるgotoの方が良い

>>57くらいのループなら
break 2;
は名前を考える手間が無くて楽だし
見にくくもない
0062デフォルトの名無しさん
垢版 |
2019/12/15(日) 09:57:28.64ID:5sPbacoo
とは書いたけど
どっちも有るならどっちも欲しい

どっちかだけげならbreak 2;の方が欲しい
って感じ
0063デフォルトの名無しさん
垢版 |
2019/12/15(日) 10:52:04.89ID:6aWNd1w0
>>61
> そんなんだと名前付きループにした所で
> @outerなんて名前が使い回されて
> 同じ名前のループがネストされて
> それこそ難読コードになる
無能の妄想w
0064デフォルトの名無しさん
垢版 |
2019/12/15(日) 11:05:09.82ID:5sPbacoo
ループの先頭、ループの終わり、break部分
3箇所見ないとダメってだけでダメな仕様
0065デフォルトの名無しさん
垢版 |
2019/12/15(日) 12:32:17.60ID:bDjAMWVj
>>64
なぜか自分の前提は
> >>57くらいのループなら
なのにラベルにした途端にループの頭とbreakとループの終わりが一瞥でわからないとかアホすぎ
0068デフォルトの名無しさん
垢版 |
2019/12/15(日) 13:48:44.02ID:o9m7qUoD
>>60
ネスト変わるような変更あるたびにbreakの引数勝手に書き換えてくれるエディタとかマクロが流行る
0070デフォルトの名無しさん
垢版 |
2019/12/15(日) 16:52:03.21ID:u46gpj2V
歪んだ教育のせいで
gotoに拒絶反応を示す人が多いんだよな

2重ループを抜けるなら素直にgotoを使えって
0071デフォルトの名無しさん
垢版 |
2019/12/15(日) 16:53:29.68ID:pTp+dpJs
アセンブラの
jmp 1f
とかを C でやりたいという話なのか?
やってみりゃいいじゃん。プリプロセッサの出力を処理すればいい。
1 パスで出来ると思うよ。
ひょっとしてもう誰かがやってるかも。
0072デフォルトの名無しさん
垢版 |
2019/12/15(日) 18:05:59.04ID:5sPbacoo
for (i = 1; i <= 3; i++) {
  for (j = 1; j <= 3; j++) {
    printf("%d, %d\n", i, j);
    if (i * j > 3) goto outer;
  }
} outer:;
0073デフォルトの名無しさん
垢版 |
2019/12/15(日) 18:58:38.98ID:5sPbacoo
for (i = 1; i <= 3; i++) {
  for (j = 1; j <= 3; j++) {
    printf("%d, %d\n", i, j);
    if (i * j > 3) goto outer;
  }
}
printf("complete\n");
outer:;
0075デフォルトの名無しさん
垢版 |
2019/12/16(月) 09:05:52.89ID:AI1GDY0I
ラベルのスコープを狭くしたいという話のようだから
マクロの中で使ってこそ真価を発揮するんじゃないかな。
フル仕様のパースが必要というわけではなく、かなり手抜きできそうではある。
あれば便利というのは否定しないが、C でそこまで必要かというと…
0076デフォルトの名無しさん
垢版 |
2019/12/16(月) 12:33:03.93ID:0jmxiGrg
{
goto hoge;
hoge:;
}
{
goto hoge;
hoge:;
}
これで二重になってたら困るしある意味なってなくても困るな
0077デフォルトの名無しさん
垢版 |
2019/12/16(月) 13:21:05.83ID:ZZ8St2Js
マクロで二重以上のループってのもなかなか考えづらいなあ

一応、ラベル名をパラメータとする手もある

使う側のコストを考えるとgotoの為にパラメータを増やさないよな
gotoを使わない主義者がよくやってるように
余分な変数を使って実装するんだろうね
0078デフォルトの名無しさん
垢版 |
2019/12/16(月) 13:23:11.26ID:ZZ8St2Js
アセンブラだとマクロローカルラベルってのがあったりする
ラベルを頻繁に使うので

あと
@@/@b/@fのように、
直近のラベルを指定する仕組みもある
0079デフォルトの名無しさん
垢版 |
2019/12/16(月) 13:28:49.41ID:ZZ8St2Js
>>72 >>73 みたいなのって
gotoの使いどころだと思うんだけだ
gotoを使わない人はどう書いてるの?

特に >>57 の答えを聞いてみたい
0080デフォルトの名無しさん
垢版 |
2019/12/16(月) 15:17:28.75ID:arH1mwfY
void print_data(void) {
 for (i = 1; i <= 3; i++) {
   for (j = 1; j <= 3; j++) {
     printf("%d, %d\n", i, j);
     if (i * j > 3) return;
   }
 }
}
print_data();
printf("complete\n");
0082デフォルトの名無しさん
垢版 |
2019/12/16(月) 16:51:44.02ID:arH1mwfY
void print_data(void) {
 for (i = 1; i <= 3; i++) {
   for (j = 1; j <= 3; j++) {
     printf("%d, %d\n", i, j);
     if (i * j > 3) return;
   }
 }
}
print_data();
outer より後に処理が続く場合
printf("complete\n");
0083デフォルトの名無しさん
垢版 |
2019/12/16(月) 16:55:03.26ID:arH1mwfY
"短い処理"をいちいち関数にしなくて済むから、break 2とかはあってもいいが、
長い処理は関数にしてないとろくにテストできないんだからgotoなんていらない
0085デフォルトの名無しさん
垢版 |
2019/12/16(月) 19:09:09.12ID:lsrBHsJG
gotoの基本的な使い方くらい知っておいた方が良いかと
ループを抜ける為だけに関数を分けないといけなくなるし
挙げ句の果てに言語の欠陥とか言い出す
0086デフォルトの名無しさん
垢版 |
2019/12/16(月) 20:06:51.00ID:3ha1TSe5
今のC言語ではネストしたループから抜けるのはフラグを使うかgotoしかないからたいていgoto使ってるけどgotoなんて野蛮なものはできたら使いたくないから他の言語で実装されてるラベル付きbreakなりレベル付きbreakが欲しいって話だろ
今更gotoの基本的な使い方ガーとか言ってる奴はどんだけ低レベルなんだよw
0088デフォルトの名無しさん
垢版 |
2019/12/16(月) 20:21:09.65ID:xr9KOlE0
gotoは野蛮とかいう歪んだ教育のせいで
わざわざ変数を定義したりわざわざ関数を分けたりして
わざわざ見にくいコードにしちゃう

生でポインタを扱う野蛮なC言語なんか使わないで
上品な言語を使った方が良いよ
0090デフォルトの名無しさん
垢版 |
2019/12/16(月) 20:47:58.36ID:LjjtFzBx
自分は小規模な字句解析みたいなのでもgoto使うことがある。
ラベルで状態を表してgotoで遷移する。
goto使わなかったら状態を変数に入れて、
ループの中でswitchで場合分けするようなコードになって辛い。
0094デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:12:14.62ID:arH1mwfY
>>87
returnで抜けるためというか、

1. gotoで抜けたい
2. 関数にするか
3. あ、そもそもコードが複雑なんだな
4. 関数にして正解だった

こんな感じかな。

gotoで抜けたいと思う=コードが複雑になってるという警鐘だと思ってる。
0095デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:22:18.57ID:xr9KOlE0
>>82みたいな意味不明な関数の分け方をすると
>>57は、より複雑な記述をしたいっていう主張だし

gotoに親を殺された人の言うことは支離滅裂
理由が後付けだからそうなる
0096デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:27:34.28ID:arH1mwfY
> で>>82みたいな意味不明な関数の分け方をすると

なんで意味不明?
そもそもその処理に意味をもたせてから言おうよw
処理に意味をもたせると、関数にしたほうが良いと思うからさ
0097デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:32:01.57ID:arH1mwfY
> 理由が後付けだからそうなる

質問の方が先なのに、理由を先に言えるわけがないw

Q. 多重ループから抜けるのに、gotoは必要ですか?
A. 必要ありません。多重ループが必要になるぐらい複雑なら関数にしますから


これが普通だから、後付にはならないよね。
0103デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:42:13.32ID:xr9KOlE0
話を戻して

・ループを抜けた後に関数の後処理が必要な場合
・ループを抜けた後にローカル変数を使った処理をする場合
・他、意味的に関数内で処理したい場合

はどうするの?
0104デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:44:03.17ID:arH1mwfY
> ・ループを抜けた後に関数の後処理が必要な場合
前処理を関数の中でするな

> ・ループを抜けた後に関数の後処理が必要な場合
戻り値を返せ

>・他、意味的に関数内で処理したい場合
自分で具体例が思いつかないなら出すな
0105デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:45:01.13ID:arH1mwfY
コピペミスったな

>・ループを抜けた後にローカル変数を使った処理をする場合
戻り値を返せ
0107デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:52:22.49ID:arH1mwfY
>>106
なにが?

ってか、もう少し具体例を書けよ。
それみれば設計がおかしいという結論になる

例えて言うなら、パーサーの処理の中でネットワークにアクセスしたい時困るから
ネットワークモジュールはグローバルにアクセスできるようにしておくべき
みたいなことを言ってるようなもんだよ。それは設計がおかしい。
0110デフォルトの名無しさん
垢版 |
2019/12/16(月) 22:58:13.41ID:arH1mwfY
>>108
「ループ」という言い方がおかしい。
ループで「実装」しているのであって
やっているのはなにかの「処理」だろう?


int func(int n){
ロック
処理
アンロック
return 結果;
}


「処理」という名前をつけたくなるならば、
そこは独立した関数にするべきだろう
0111デフォルトの名無しさん
垢版 |
2019/12/16(月) 23:02:27.04ID:xr9KOlE0
double sigma(const double *a){
ループで総和と2乗和と数を計算
標準偏差を計算
return 標準偏差
}
0117デフォルトの名無しさん
垢版 |
2019/12/16(月) 23:17:03.74ID:xr9KOlE0
関数分けってのは意味、機能、汎用性、...で分けるべきであって
単にループを抜けるのにreturnを使いたいから分けるとかを考えるべきじゃない
0119デフォルトの名無しさん
垢版 |
2019/12/16(月) 23:42:01.03ID:arH1mwfY
>>118
だから意味とか汎用性とかで分けると
自然にループに抜けるときにreturnを使えば良くなるんだよ
0121デフォルトの名無しさん
垢版 |
2019/12/16(月) 23:48:10.14ID:arH1mwfY
>>112
だから「ループ」と書くなっちゅうねんw
関数を設計するならこんな感じやろ?

int func(int n){
int a[10] = {0};
memset_random(a, sizeof(a)); // a配列をランダムな値で埋める
int chksum = chksum(a, sizeof(a)); // a配列のチェックサムを計算
return 値
}

関数の中でループしてようが何して用が関係ないわ
0126デフォルトの名無しさん
垢版 |
2019/12/17(火) 07:10:23.36ID:JvBVW/sd
gotoもbreakも無い
ループを抜けるときはreturn
switchを抜ける時もreturm
関数は単一の処理しか出来ない

こんな言語はイヤだね
0130デフォルトの名無しさん
垢版 |
2019/12/17(火) 12:33:06.04ID:vDeQfs2U
自分より下の人間を叩くしか能がないんだろ
ID:arH1mwfYなんてスルーでいいと思うんだがそれしか叩けないからいつまでたっても終わらないw
0134デフォルトの名無しさん
垢版 |
2019/12/17(火) 19:18:33.78ID:6LhBKKEf
>>132
自分で似たようなものを作ればいいだろ。汎用的なものがあっても使い勝手や性能で何かしら不満が出るのだから、自分の要求に合致するものを自分で作りな。
0135デフォルトの名無しさん
垢版 |
2019/12/17(火) 20:52:31.46ID:QeraReD1
特定の用途においてローカルラベルが役に立つことも無くはないかもしれないな。
自分でそれをやるかどうかは別にして。
いずれにせよ、gcc では式の中で変数を宣言できるのだから
ローカルラベルが可能になっても驚かないよ。
0137デフォルトの名無しさん
垢版 |
2019/12/19(木) 00:12:48.48ID:vqVcyk4J
PHPはbreakにネスト数指定できるよな
0139デフォルトの名無しさん
垢版 |
2019/12/19(木) 16:51:03.60ID:86m15ms9
longjmp についても調査してほしいな。
特に例は挙げないが、誰もが使っているようなプログラムでも結構使われてる。
0140デフォルトの名無しさん
垢版 |
2019/12/19(木) 16:57:20.13ID:+cpLTGtZ
static
0143デフォルトの名無しさん
垢版 |
2020/07/09(木) 10:22:15.80ID:vrNDocOm
発明って言うか当時はそれが普通だったろ
0144デフォルトの名無しさん
垢版 |
2020/07/09(木) 10:51:31.74ID:I92CxMlL
longjmpは「設計上のミス」ではないんでは。
むしろそういう動作をする目的で設計・導入されたように思えるけど
(longjmpに関するRationaleを読んでないので当てずっぽうw)
0148デフォルトの名無しさん
垢版 |
2020/07/10(金) 22:26:03.98ID:U1HXCT7S
returnが1変数しか対応していないこと。

ポインター祭りになって可読性がウンコになる
レスを投稿する


ニューススポーツなんでも実況