C言語なら俺に聞け 159

■ このスレッドは過去ログ倉庫に格納されています
2022/08/04(木) 23:32:27.83ID:yWVViPyIM
!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

C2x ドラフト
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2731.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言語なら俺に聞け 158
https://mevius.5ch.net/test/read.cgi/tech/1640401906/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2022/08/04(木) 23:46:06.88ID:hPtMGH660
現時点んでの C2x 最新ドラフトはこっち
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n2912.pdf
2022/08/04(木) 23:50:16.33ID:nIz8Ddm70
訂正ありがとう
2022/08/08(月) 01:13:34.41ID:/9Y6mnF30
n3047がC23の投票に掛けられる模様
2022/08/08(月) 01:16:49.11ID:JJ3NlnG00
おっ、こないだの会議の結果が反映されたドラフトが出てたのか。
2022/08/13(土) 08:01:13.53ID:2Qk1ejrP0
配列の初期化に変数使えるのはGCC拡張ってマジか・・・
これ↓

int arr[3] = { a, b, c };

知らなかった・・・
2022/08/13(土) 08:05:10.38ID:2Qk1ejrP0
>>6
あれ?
-std=c11 つけてコンパイルしてもエラーにならないな
>>6は一応C標準てことでいいのかな?
2022/08/13(土) 09:53:55.13ID:RGh4OO0V0
>>6-7
言語仕様を確認してみたら、変数が静的記憶域期間を持つときは
初期化子に現れる全ての式が定数式でなければならない (変数を含められない) という制限はある。
自動記憶域期間なら初期化子に変数を使っても問題ない。
GCC でもそのような挙動になる。
2022/08/13(土) 09:54:36.52ID:F6UXSz0Jd
>>6
staticやグローバルにすると・・・
2022/08/13(土) 10:02:52.43ID:RGh4OO0V0
関連する挙動を色々と試してたんだけど、
GCC では const 付きの変数の挙動が少し C++ 寄りに拡張されているっぽい。

C++ では const 付き変数の初期化子が定数式である場合にはその変数も定数式になるが、
C では単に代入できない変数という扱いのはずなんだけど、
GCC では定数式っぽい振る舞いをする場合がある (全面的に定数式扱いというわけではない) ように見える。
2022/08/13(土) 17:52:01.55ID:D+zbBXbXd
>>9
それが静的記憶域っちゅうこっちゃがなーー
2022/08/13(土) 20:18:21.81ID:F6UXSz0Jd
>>11
だからそれを言ってる
2022/08/14(日) 00:23:10.64ID:yTFzwOo0d
もう>>8に書いてあるじゃん
2022/08/14(日) 00:37:06.28ID:E4oXLohw0
あーなるほどstaticかぁ
お前らありがとん
2022/08/14(日) 08:08:18.99ID:BqkowVN+d
K&R Cでは配列の初期化子にも同様の制限があって
その理由は合理的だった
その後ある事情で無理が通って道理が引っ込んだ
16デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/14(日) 11:44:40.04ID:VI2zLni0a
staticには意味が複数あるのがC言語の挫折ポイントのひとつ
2022/08/14(日) 12:08:31.19ID:vdIvBFYd0
予約語を増やさないという方針自体は互換性を損なわないために真っ当なものだと思うけど、
名前がかぶったら単に一括置換で対処できる程度のことでもあるしなぁ……。
2022/08/14(日) 12:20:02.25ID:1rNkdimaa
>>16
そんなので挫折するならもっと前に挫折するだろw
2022/08/14(日) 12:34:09.99ID:+OkjgujJ0
挫折自慢大会が開催されました
2022/08/14(日) 13:14:34.32ID:GttZqyyI0
Scheme 手習い、を挫折しました、いつ再トライしようかしら?
2022/08/14(日) 15:10:21.65ID:vdIvBFYd0
自分の性分に合ったものは気合いを入れなくても割とスルっと出来ちゃったりするし、
そういうところから周りに広げていく形でやってけばいいんでないかな。
業務で必要とかならそうも言っておれんだろうけど。
22デフォルトの名無しさん (ワッチョイ 42ad-9bk+)
垢版 |
2022/08/14(日) 16:55:08.09ID:YzvfyuVN0
Kotlinもよろしく
23デフォルトの名無しさん (ワッチョイ 9901-oUG4)
垢版 |
2022/08/14(日) 17:14:45.00ID:b9F5IowR0
完全な文脈自由文法で設計されていれば、コンパイラも簡単に作れるけどな。
しかし、Javaのその特性は完全に無視され、誰にも気づかれなかった。
お前らも気づいていない。
2022/08/14(日) 21:52:34.16ID:vdIvBFYd0
構文解析だけ簡単でもコンパイラが簡単なわけではないが……。
部分的にでも簡単であるに越したことは無いけどさ。
2022/08/15(月) 06:53:02.58ID:m+99U1QQd
いや宣言文→実行部のように決まっている文脈ガチガチのほうがコンパイラは作りやすい
2022/08/15(月) 08:31:44.94ID:zxOEKBbO0
今時字句解析とか構文解析で難しいとかないでしょ
それなりのツールもあるからBNF書ければ自動生成できたりするし
2022/08/15(月) 09:21:08.58ID:DfKndVH30
>>26
言語仕様のほうも処理しやすいように寄せてきてるからだよ。
パーサジェネレータを前提として設計された言語仕様ならパーサジェネレータで処理しやすいのは当たり前の話。
2022/08/15(月) 09:27:22.60ID:zxOEKBbO0
>>27
難しいって一体どんな言語仕様を想定してるんだ?w
2022/08/15(月) 09:47:41.49ID:DfKndVH30
>>28
FORTRAN 77
2022/08/15(月) 10:35:55.74ID:zxOEKBbO0
>>29
字句解析と構文解析を一体でやらないといけないから面倒ではあるけど難しいという程じゃなくね?
そもそも人間にとっても分かりにくい言語仕様を採用するのもどうかと思うが
2022/08/15(月) 11:11:29.28ID:DfKndVH30
>>30
今の主要なプログラミング言語はそう (処理段階の分離が極端に難しい仕様には) ならなかったという話をしてる。

だから昔のものから例になりそうなものを抽出しただけで、この頃の知見のまま設計された大きな言語があったら
現代的なツールでも扱いにくいだろうということ。
2022/08/15(月) 11:28:00.05ID:zxOEKBbO0
>>31
だから多少面倒なだけだろ
そもそもスペース無視するとか予約語を識別子に使えるとか人間側にも優しくない仕様ででかい言語仕様とか頭おかしい
2022/08/15(月) 11:39:32.94ID:DfKndVH30
>>32
漠然と変だとは思ってたとしても、知見の確立がなかったとしたらそのまま進むしかしょうがないだろう。
まあ、そうなっていない世界でのもしもの話、実際に無かった以上は想像でしかないけどな。
2022/08/15(月) 12:01:53.74ID:zxOEKBbO0
>>33
そもそもFORTRAN77以前でも
DO 100 I = 1. 5
なんて言う「代入文」を書く奴なんてほとんどいなかったわけで知見が確立しないまま言語仕様だけでかくなるとかまずありえんわ
まあ妄想に浸りたいだけなら勝手にやっててくださいな
2022/08/15(月) 12:48:46.30ID:RzREpsfh0
ほとんどいない笑
たまにはいたんですね?
2022/08/15(月) 13:28:30.95ID:zxOEKBbO0
>>35
タイプミスとか、難読大会とか
想像力ないの?
37デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
垢版 |
2022/08/16(火) 10:07:24.32ID:6bNCuhdm0
割り込みルーチン内で速度を稼ぐためにグローバル変数をローカル変数にコピーして
それを元に色々処理しようとするとうまくいかない
グローバル変数を直接使って処理するとうまくいく
こういうことはありえるのかな?
2022/08/16(火) 10:11:26.14ID:wezFOLPc0
・・・グローバル変数の書き戻し忘れとか?
39デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/16(火) 11:20:38.26ID:2x3mrzZQa
ポインタ便利ですね
2022/08/16(火) 11:58:39.88ID:dXh796NKd
すっごく抽象的でさっぱりわからんw
なんの割り込み?
どううまくいかない?
2022/08/16(火) 14:05:35.67ID:+o+ePBjP0
>>37
書いたプログラムのロジックは誤ってないと仮定して、
コンパイラによる最適化が割り込みに配慮しないなら思ったような動作にならないということはあり得る。

ある変数が途中で変更されることはないと確信できる状況なら
レジスタにロード済みの値を使いまわしたりするのはごく普通の動作。
場合によっては定数にまで畳み込まれることもある。
だけど、割り込みはそうしたメインの流れと関係なく問答無用でどこにでも割り込むから齟齬が生じる。

C99 までは割り込みや平行については言語仕様ではあまり取り決めず、
動作の詳細な部分は処理系まかせなものの volatile キーワードを付けた変数は最適化が抑制されるとか、
処理系の拡張で属性指定を付けれるとかいった機能を利用してどうにかしてきた。
(たぶん POSIX にはもうちょっと詳しい規定がありそうだと思うけど私はよく知らない。)

C11 以降はスレッドまわりの整備が進んだので割り込みでも活用できる部分は多いと思うんだけど、
オプショナルな仕様なので C11 の処理系として必須なわけではないんよ。

おそらくは使っている処理系・実行環境で使っているお決まりのパターンがあると思うからそういうのを探して
真似するのが手っ取り早いと思う。
2022/08/16(火) 19:21:50.20ID:7tUZ32LZd
そういやそんな問題に悩んでた奴でvolatileの存在知らない奴がいたな
…大丈夫だよね?
2022/08/17(水) 12:06:24.22ID:75soL8XVa
volatile で全ての問題が解決する訳じゃないけどな
知らないのはまずいな
44デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
垢版 |
2022/08/17(水) 15:44:25.95ID:VZh9Cr0g0
switch文がポンコツ過ぎて二分探索のif文で記述したくなります
case設定がへたくそなのでしょうか?
2022/08/17(水) 16:18:24.97ID:vNydwVZ40
C++にすらないoperator switch caseでも欲しいのかな
2022/08/17(水) 16:34:24.35ID:mlh+/a6xd
またも抽象化し過ぎの質問…
switchが上手くはまらなかったらelse if地獄でいいんだよ
2022/08/17(水) 18:48:10.50ID:ito9w61P0
>>44
具体的に何が不満なの?
2022/08/17(水) 19:06:06.04ID:cXiq2BCR0
スキルを磨く以外に、王道はありません
2022/08/17(水) 19:37:59.93ID:GqH3uV+md
具体的にどうポンコツなのかわからんけど
例えばaが1だったら処理1、2だったら処理2、3-15だったら処理3、16なら処理4
それ以外は処理default

if( a == 1 ){
  処理1
}else if( a == 2 ){
  処理2
}else if( a <= 15 ){
  処理3
}else if( a == 16 ){
  処理4
}else{
  処理default
}

こんなんで充分だよ
2022/08/17(水) 21:42:31.43ID:ZlUvKbke0
流れを綺麗にしたいなら
enumやマクロでシンボリックな定数を定義、ロジックはビット演算に埋め込め
2022/08/17(水) 22:05:39.48ID:ISeM0IbeH
>>42
volatile で保証された気分になっている方が問題、ちゃんと pthread を使えよ
2022/08/17(水) 22:10:35.67ID:ito9w61P0
割り込みは並行 (または並列) とは違うので pthread ほどの保証は過剰だと思う。
2022/08/17(水) 22:19:02.41ID:vZEBwtyc0
フォールスルーしないなら if else if else if .... って重ねてってもたいして変わらんしね
2022/08/17(水) 22:23:36.57ID:ZlUvKbke0
パーサとか書くなら抽象化のコストに見合うけど、もしそれほど複雑でないなら
caseラベルは各分枝に付き一つにしてしまい、分類は外部委託してしまうが楽
switch(var)→switch(CLASSFY(var))
case 'A': actionA;...

パターン: アクション

の並びに落とし込むのが難しいなら、多分switchを使うべき問題ではない
2022/08/17(水) 22:32:08.07ID:cXiq2BCR0
swich case は条件に応じて分岐するジャンプテーブルなのでどの条件に対しても同じ重さ
if else if は書かれた順に評価し、実行するので、起こりそうな条件を前に持ってくると効率化できる、かも
2022/08/17(水) 23:03:29.34ID:YK1jCeWgM
>>55
switchも連続比較する事が基本で、caseラベルの値の最小値と最大値が一定の範囲内だったら最適化でジャンプテーブルになるかもってだけでしょ
絶体にテーブルジャンプさせたければ、自前でやるしかない
2022/08/17(水) 23:06:32.99ID:ito9w61P0
リッチな処理系なら switch も常にただのテーブルということはない。 状況に応じて最適化は入る。
ただ、頻出する分岐がどれなのか予測してくれるほど十分に賢くは無いので
条件があり得る頻度によってチューニングが必要なら if に置き換えるしかしょうがないな。

GCC だとプロファイルを取ってその成果をもとに最適化することも出来る。
頻出する条件を __builtin_expect で指定するとその分岐を優先的に検査する (ようなコードを生成する) という便利機能もある。
手作業で微調整するのは不毛な感じがするから使えるものならコンパイラの賢い機能に頼るのもアリだと思う。
(試したことがないから細かいことは知らない。 たいした効果は無いかもしれない。)
2022/08/18(木) 04:30:48.90ID:X/mZUHYK0
まあ確かに>>49
switch(a){
case 1:
 処理1; break;
case 2:
 処理2; break;
case 3..15:
 処理3; break;
case 16:
 処理4; break;
default:
 処理default
}
みたいに書ければなぁって思わなくもない
2022/08/18(木) 11:21:05.54ID:ZfnRi5ov0
>>58
GCCの拡張だけどあるよ
Clangでも使える
https://wandbox.org/permlink/XQ2uCo7afhhQRyzH
2022/08/18(木) 11:23:58.91ID:C4YsUD/kd
たまーに、いちいちbreak文を書かなきゃいけないのがダルいなって思うことはあるな
ちょっと自分が作業中断すべきときかなって
2022/08/18(木) 11:41:19.30ID:DF4FCk1vd
>>59
コンパイル時定数なら利益なくね?
case:3 case:4...case:15に展開するRANGE(3, 15)マクロで十分
2022/08/18(木) 11:44:02.06ID:u9P7LJR3a
>>59
なるほどさすが GCC やね、標準に取り込んで欲しいわ
2022/08/18(木) 11:49:28.51ID:DF4FCk1vd
caseラベルの値を数値(範囲)として扱うという発想が無かった
もう素直に比較しろよ
2022/08/18(木) 11:52:35.74ID:p/limWqpa
Ruby厨登場
2022/08/18(木) 13:33:09.96ID:FzMciMIo0
caseは単なるラベル
2022/08/18(木) 14:47:46.14ID:4UGfKreUM
for文の中でswitch使うと、forを抜けるbreakを書けないのがクソ
気付かず使うとデバッグ困難なバグになる落とし穴
switchをifにするか、forの外にgotoで飛ばすしかない
switch文はC言語最大の設計ミス
2022/08/18(木) 15:55:41.52ID:C4YsUD/kd
gotoは悪って前提だな
gotoレス原理主義者?
2022/08/18(木) 15:58:47.22ID:X/mZUHYK0
そもそも多重ループからの脱出もできないし、ややこしい奴は素直にgoto使えってことだろ
2022/08/18(木) 20:24:47.46ID:+rK0/pUYd
switchからの脱出がbreakなのがおかしい
2022/08/18(木) 20:48:40.52ID:SQwD8GPSH
>>69
for からの脱出が break
while/do while からの脱出が break

で、あれば、

switch からの脱出も break であっても不適当とはいえないのではないですか?
71デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
垢版 |
2022/08/18(木) 23:03:17.54ID:1nHnTkCL0
行儀良くまじめなんてできやしなかった
夜の校舎窓ガラス壊してまわった
逆らい続けあがき続けた早く自由になりたかった

ひとつだけわかっていたこと
この支配からの~break♪
2022/08/18(木) 23:06:15.16ID:4f/YBTxPM
Javaのswitch式を逆輸入して欲しい
評判が良いのかどうか分からんけど
73デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 00:43:51.91ID:Djh9jYCCa
endfor とか endwhile とか endcase とか悪夢でしかない
2022/08/19(金) 01:50:19.99ID:FEOcjYNtd
>>70
switchはループ制御文ではないのになんでwhileやforと同じなのか
2022/08/19(金) 05:12:37.71ID:2Y60evoq0
break は今いるブロック (波括弧といてもいい) から一つ外のブロックに出る
という意味を持つ
2022/08/19(金) 09:19:24.91ID:FT/EuRcZ0
>>75
そんなわけないだろ。
2022/08/19(金) 10:12:45.49ID:FEOcjYNtd
それならif文からも脱出できるはずだができない
あくまでswitchが特例でループ文扱いされてるので脱出できる
2022/08/19(金) 10:34:49.15ID:FT/EuRcZ0
switch やループ構文はブロックとは独立した構文で、
これらを使うときにブロックを作らないことも出来るし、
逆に関係ないところでブロックを作ることも出来るので
break をブロックと対応付けさせると変なことになるんだよな。

たとえば以下のコードでの break は実際には switch を抜けるだけなので printf は実行されるが、
ブロックを抜けるほうが自然だと思うか?

#include <stdio.h>

int main(void) {
{
switch(1) case 1: break;
printf("hello\n");
}
}
2022/08/19(金) 12:00:39.57ID:FEOcjYNtd
そんな極端な例でなくても…

case 1:
if( x < 4 ){
………
break;
}
………
break;

普通によく書くと思うが
このif文の中のbreakでもちゃんと一番内側のswitch文の外に飛んでいく

switch(k){

case 1:
{
int tmp_x; //この中だけで使う一時変数
………
break;
}
case 2:
………
}

こんな書き方でも(あまりよくないけど)ブロックは無視してswitch文の外に飛んでいく
80デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 18:10:20.82ID:opjWCie4a
for の中の if の中の break で単に if から脱出されても
おまえなにしとんねん
開いた口が塞がらない状態になる罠
81デフォルトの名無しさん (アウアウウー Saa5-oUG4)
垢版 |
2022/08/19(金) 18:16:48.08ID:opjWCie4a
do{
やりたいこと
}while(0);
っていう構造に変換するマクロは良く使われるが
switch(0) default: {
やりたいこと
}
なんかもアリなんだな
2022/08/20(土) 00:31:59.15ID:YrrCECg9M
>>81
switchの方は初めて見た!
知らずに見たらちょっと考えちゃうよw
2022/08/20(土) 13:41:46.51ID:DoG0cN1P0
考えるな
感じるんだ
2022/08/20(土) 13:47:51.88ID:zH67Kdp1d
俺は()で囲むな
85デフォルトの名無しさん (ワッチョイ ffad-4Erx)
垢版 |
2022/08/21(日) 07:14:13.14ID:sPdtHxRX0
エロい人「割り込みの中で関数呼ぶな
なぜ??
2022/08/21(日) 07:26:44.64ID:calK6kMNd
バカな会社で働いてるから
2022/08/21(日) 07:46:27.87ID:3JIuIXQv0
>>85
環境によるけど割り込みに専用のスタック使ってるシステムとかだとそのスタックサイズはそれほど大きくなかったりするからかもね
てかそのエロい人に聞けよ
2022/08/21(日) 08:14:56.03ID:lk6Yo6Bld
再入可能でない関数ならわかるな
89デフォルトの名無しさん (アウアウウー Sa63-dbST)
垢版 |
2022/08/21(日) 09:42:18.04ID:j3ukytx2a
stack8段しか無いcpuか
2022/08/21(日) 10:25:51.63ID:calK6kMNd
割込はなるべく速く返さないといけないので
関数呼び出しのオーバーヘッドを嫌うというのもある
2022/08/21(日) 16:28:21.98ID:lk6Yo6Bld
だとすると>>86でFAだな
92デフォルトの名無しさん (ワッチョイ ffad-4Erx)
垢版 |
2022/08/22(月) 09:18:01.26ID:rymTPk3V0
微妙なタイミング調整の_nop()マクロをオプティマイザが勝手に除去するのだがwwwwwwwwww
どうすりゃいいのよ
2022/08/22(月) 09:32:56.89ID:AaGiqQjO0
>>92
インラインアセンブラ
そもそも今時命令実行タイミングに依存する構成にするなよ...
2022/08/22(月) 10:11:25.02ID:xRj4VImad
Z80や6800でそんなことしてたけど
今時のCPUはnopでさえ速度が変動するからな
2022/08/22(月) 10:15:31.51ID:/BwQkwng0
インラインアセンブラも最適化の対象になることがある。
現代的な開発環境なら intrinsic 関数が提供されてないか?
96デフォルトの名無しさん (ワッチョイ 7f69-dbST)
垢版 |
2022/08/22(月) 11:43:22.34ID:sosiPY3F0
最適化するなよw
そういうのを消すための最適化だろw
97デフォルトの名無しさん (アウアウウー Sa63-dbST)
垢版 |
2022/08/22(月) 13:53:48.03ID:KX6mg0Ola
最適化したら >>96 が消えました
2022/08/25(木) 11:33:41.80ID:sT5+wQDE0
インライン記述じゃなく別個にアセンブラソースファイルに書いてアセンブルしろってことだな。
2022/08/25(木) 11:49:07.60ID:iqB4j8J+0
スカイネット 「環境の最適化のため、人類を消去しました」
2022/08/25(木) 13:23:55.27ID:sT5+wQDE0
環境の最適化のためにスカイネット自身の消去が最適だとなったら実行するのかね。
2022/08/25(木) 16:20:32.32ID:WIrE9pd90
組み込みでは下みたいに使った
__asm__ __volatile__()
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

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