!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
C言語なら俺に聞け 159
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (ワンミングク MMa2-RRwJ)
2022/08/04(木) 23:32:27.83ID:yWVViPyIM38デフォルトの名無しさん (ワッチョイ 4910-5Ix7)
2022/08/16(火) 10:11:26.14ID:wezFOLPc0 ・・・グローバル変数の書き戻し忘れとか?
39デフォルトの名無しさん (アウアウウー Saa5-oUG4)
2022/08/16(火) 11:20:38.26ID:2x3mrzZQa ポインタ便利ですね
40デフォルトの名無しさん (スッププ Sd62-jKaU)
2022/08/16(火) 11:58:39.88ID:dXh796NKd すっごく抽象的でさっぱりわからんw
なんの割り込み?
どううまくいかない?
なんの割り込み?
どううまくいかない?
41はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 813e-5Ix7)
2022/08/16(火) 14:05:35.67ID:+o+ePBjP0 >>37
書いたプログラムのロジックは誤ってないと仮定して、
コンパイラによる最適化が割り込みに配慮しないなら思ったような動作にならないということはあり得る。
ある変数が途中で変更されることはないと確信できる状況なら
レジスタにロード済みの値を使いまわしたりするのはごく普通の動作。
場合によっては定数にまで畳み込まれることもある。
だけど、割り込みはそうしたメインの流れと関係なく問答無用でどこにでも割り込むから齟齬が生じる。
C99 までは割り込みや平行については言語仕様ではあまり取り決めず、
動作の詳細な部分は処理系まかせなものの volatile キーワードを付けた変数は最適化が抑制されるとか、
処理系の拡張で属性指定を付けれるとかいった機能を利用してどうにかしてきた。
(たぶん POSIX にはもうちょっと詳しい規定がありそうだと思うけど私はよく知らない。)
C11 以降はスレッドまわりの整備が進んだので割り込みでも活用できる部分は多いと思うんだけど、
オプショナルな仕様なので C11 の処理系として必須なわけではないんよ。
おそらくは使っている処理系・実行環境で使っているお決まりのパターンがあると思うからそういうのを探して
真似するのが手っ取り早いと思う。
書いたプログラムのロジックは誤ってないと仮定して、
コンパイラによる最適化が割り込みに配慮しないなら思ったような動作にならないということはあり得る。
ある変数が途中で変更されることはないと確信できる状況なら
レジスタにロード済みの値を使いまわしたりするのはごく普通の動作。
場合によっては定数にまで畳み込まれることもある。
だけど、割り込みはそうしたメインの流れと関係なく問答無用でどこにでも割り込むから齟齬が生じる。
C99 までは割り込みや平行については言語仕様ではあまり取り決めず、
動作の詳細な部分は処理系まかせなものの volatile キーワードを付けた変数は最適化が抑制されるとか、
処理系の拡張で属性指定を付けれるとかいった機能を利用してどうにかしてきた。
(たぶん POSIX にはもうちょっと詳しい規定がありそうだと思うけど私はよく知らない。)
C11 以降はスレッドまわりの整備が進んだので割り込みでも活用できる部分は多いと思うんだけど、
オプショナルな仕様なので C11 の処理系として必須なわけではないんよ。
おそらくは使っている処理系・実行環境で使っているお決まりのパターンがあると思うからそういうのを探して
真似するのが手っ取り早いと思う。
42デフォルトの名無しさん (スッププ Sd62-jKaU)
2022/08/16(火) 19:21:50.20ID:7tUZ32LZd そういやそんな問題に悩んでた奴でvolatileの存在知らない奴がいたな
…大丈夫だよね?
…大丈夫だよね?
43デフォルトの名無しさん (アウアウウー Saa5-oUG4)
2022/08/17(水) 12:06:24.22ID:75soL8XVa volatile で全ての問題が解決する訳じゃないけどな
知らないのはまずいな
知らないのはまずいな
44デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
2022/08/17(水) 15:44:25.95ID:VZh9Cr0g0 switch文がポンコツ過ぎて二分探索のif文で記述したくなります
case設定がへたくそなのでしょうか?
case設定がへたくそなのでしょうか?
45デフォルトの名無しさん (ワッチョイ 71c2-arFQ)
2022/08/17(水) 16:18:24.97ID:vNydwVZ40 C++にすらないoperator switch caseでも欲しいのかな
46デフォルトの名無しさん (スッププ Sd62-jKaU)
2022/08/17(水) 16:34:24.35ID:mlh+/a6xd またも抽象化し過ぎの質問…
switchが上手くはまらなかったらelse if地獄でいいんだよ
switchが上手くはまらなかったらelse if地獄でいいんだよ
48デフォルトの名無しさん (ワッチョイ 4263-5Ix7)
2022/08/17(水) 19:06:06.04ID:cXiq2BCR0 スキルを磨く以外に、王道はありません
49デフォルトの名無しさん (スッップ Sd62-jKaU)
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
}
こんなんで充分だよ
例えば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
}
こんなんで充分だよ
50デフォルトの名無しさん (ワッチョイ 9202-Khd/)
2022/08/17(水) 21:42:31.43ID:ZlUvKbke0 流れを綺麗にしたいなら
enumやマクロでシンボリックな定数を定義、ロジックはビット演算に埋め込め
enumやマクロでシンボリックな定数を定義、ロジックはビット演算に埋め込め
51デフォルトの名無しさん (US 0H11-U0U7)
2022/08/17(水) 22:05:39.48ID:ISeM0IbeH >>42
volatile で保証された気分になっている方が問題、ちゃんと pthread を使えよ
volatile で保証された気分になっている方が問題、ちゃんと pthread を使えよ
52はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 813e-5Ix7)
2022/08/17(水) 22:10:35.67ID:ito9w61P0 割り込みは並行 (または並列) とは違うので pthread ほどの保証は過剰だと思う。
53デフォルトの名無しさん (ワッチョイ 8101-mhOm)
2022/08/17(水) 22:19:02.41ID:vZEBwtyc0 フォールスルーしないなら if else if else if .... って重ねてってもたいして変わらんしね
54デフォルトの名無しさん (ワッチョイ 9202-Khd/)
2022/08/17(水) 22:23:36.57ID:ZlUvKbke0 パーサとか書くなら抽象化のコストに見合うけど、もしそれほど複雑でないなら
caseラベルは各分枝に付き一つにしてしまい、分類は外部委託してしまうが楽
switch(var)→switch(CLASSFY(var))
case 'A': actionA;...
パターン: アクション
…
の並びに落とし込むのが難しいなら、多分switchを使うべき問題ではない
caseラベルは各分枝に付き一つにしてしまい、分類は外部委託してしまうが楽
switch(var)→switch(CLASSFY(var))
case 'A': actionA;...
パターン: アクション
…
の並びに落とし込むのが難しいなら、多分switchを使うべき問題ではない
55デフォルトの名無しさん (ワッチョイ 4263-5Ix7)
2022/08/17(水) 22:32:08.07ID:cXiq2BCR0 swich case は条件に応じて分岐するジャンプテーブルなのでどの条件に対しても同じ重さ
if else if は書かれた順に評価し、実行するので、起こりそうな条件を前に持ってくると効率化できる、かも
if else if は書かれた順に評価し、実行するので、起こりそうな条件を前に持ってくると効率化できる、かも
56デフォルトの名無しさん (テテンテンテン MM26-6e26)
2022/08/17(水) 23:03:29.34ID:YK1jCeWgM >>55
switchも連続比較する事が基本で、caseラベルの値の最小値と最大値が一定の範囲内だったら最適化でジャンプテーブルになるかもってだけでしょ
絶体にテーブルジャンプさせたければ、自前でやるしかない
switchも連続比較する事が基本で、caseラベルの値の最小値と最大値が一定の範囲内だったら最適化でジャンプテーブルになるかもってだけでしょ
絶体にテーブルジャンプさせたければ、自前でやるしかない
57はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 813e-5Ix7)
2022/08/17(水) 23:06:32.99ID:ito9w61P0 リッチな処理系なら switch も常にただのテーブルということはない。 状況に応じて最適化は入る。
ただ、頻出する分岐がどれなのか予測してくれるほど十分に賢くは無いので
条件があり得る頻度によってチューニングが必要なら if に置き換えるしかしょうがないな。
GCC だとプロファイルを取ってその成果をもとに最適化することも出来る。
頻出する条件を __builtin_expect で指定するとその分岐を優先的に検査する (ようなコードを生成する) という便利機能もある。
手作業で微調整するのは不毛な感じがするから使えるものならコンパイラの賢い機能に頼るのもアリだと思う。
(試したことがないから細かいことは知らない。 たいした効果は無いかもしれない。)
ただ、頻出する分岐がどれなのか予測してくれるほど十分に賢くは無いので
条件があり得る頻度によってチューニングが必要なら if に置き換えるしかしょうがないな。
GCC だとプロファイルを取ってその成果をもとに最適化することも出来る。
頻出する条件を __builtin_expect で指定するとその分岐を優先的に検査する (ようなコードを生成する) という便利機能もある。
手作業で微調整するのは不毛な感じがするから使えるものならコンパイラの賢い機能に頼るのもアリだと思う。
(試したことがないから細かいことは知らない。 たいした効果は無いかもしれない。)
58デフォルトの名無しさん (ワッチョイ 4201-8lLW)
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
}
みたいに書ければなぁって思わなくもない
switch(a){
case 1:
処理1; break;
case 2:
処理2; break;
case 3..15:
処理3; break;
case 16:
処理4; break;
default:
処理default
}
みたいに書ければなぁって思わなくもない
59デフォルトの名無しさん (ワッチョイ 7133-VZNF)
2022/08/18(木) 11:21:05.54ID:ZfnRi5ov060デフォルトの名無しさん (スップ Sd62-arFQ)
2022/08/18(木) 11:23:58.91ID:C4YsUD/kd たまーに、いちいちbreak文を書かなきゃいけないのがダルいなって思うことはあるな
ちょっと自分が作業中断すべきときかなって
ちょっと自分が作業中断すべきときかなって
61デフォルトの名無しさん (スフッ Sd62-Khd/)
2022/08/18(木) 11:41:19.30ID:DF4FCk1vd62デフォルトの名無しさん (アウアウウー Saa5-8lLW)
2022/08/18(木) 11:44:02.06ID:u9P7LJR3a >>59
なるほどさすが GCC やね、標準に取り込んで欲しいわ
なるほどさすが GCC やね、標準に取り込んで欲しいわ
63デフォルトの名無しさん (スフッ Sd62-Khd/)
2022/08/18(木) 11:49:28.51ID:DF4FCk1vd caseラベルの値を数値(範囲)として扱うという発想が無かった
もう素直に比較しろよ
もう素直に比較しろよ
64デフォルトの名無しさん (アウアウウー Saa5-oUG4)
2022/08/18(木) 11:52:35.74ID:p/limWqpa Ruby厨登場
↓
↓
65デフォルトの名無しさん (ワッチョイ 0297-8lLW)
2022/08/18(木) 13:33:09.96ID:FzMciMIo0 caseは単なるラベル
66デフォルトの名無しさん (テテンテンテン MM26-6e26)
2022/08/18(木) 14:47:46.14ID:4UGfKreUM for文の中でswitch使うと、forを抜けるbreakを書けないのがクソ
気付かず使うとデバッグ困難なバグになる落とし穴
switchをifにするか、forの外にgotoで飛ばすしかない
switch文はC言語最大の設計ミス
気付かず使うとデバッグ困難なバグになる落とし穴
switchをifにするか、forの外にgotoで飛ばすしかない
switch文はC言語最大の設計ミス
67デフォルトの名無しさん (スップ Sd62-arFQ)
2022/08/18(木) 15:55:41.52ID:C4YsUD/kd gotoは悪って前提だな
gotoレス原理主義者?
gotoレス原理主義者?
68デフォルトの名無しさん (ワッチョイ 4201-8lLW)
2022/08/18(木) 15:58:47.22ID:X/mZUHYK0 そもそも多重ループからの脱出もできないし、ややこしい奴は素直にgoto使えってことだろ
69デフォルトの名無しさん (スップ Sd62-jKaU)
2022/08/18(木) 20:24:47.46ID:+rK0/pUYd switchからの脱出がbreakなのがおかしい
70デフォルトの名無しさん (US 0H11-U0U7)
2022/08/18(木) 20:48:40.52ID:SQwD8GPSH >>69
for からの脱出が break
while/do while からの脱出が break
で、あれば、
switch からの脱出も break であっても不適当とはいえないのではないですか?
for からの脱出が break
while/do while からの脱出が break
で、あれば、
switch からの脱出も break であっても不適当とはいえないのではないですか?
71デフォルトの名無しさん (ワッチョイ 06ad-Lyl8)
2022/08/18(木) 23:03:17.54ID:1nHnTkCL0 行儀良くまじめなんてできやしなかった
夜の校舎窓ガラス壊してまわった
逆らい続けあがき続けた早く自由になりたかった
ひとつだけわかっていたこと
この支配からの~break♪
夜の校舎窓ガラス壊してまわった
逆らい続けあがき続けた早く自由になりたかった
ひとつだけわかっていたこと
この支配からの~break♪
72デフォルトの名無しさん (テテンテンテン MM26-6e26)
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 とか悪夢でしかない
74デフォルトの名無しさん (スップ Sd62-jKaU)
2022/08/19(金) 01:50:19.99ID:FEOcjYNtd >>70
switchはループ制御文ではないのになんでwhileやforと同じなのか
switchはループ制御文ではないのになんでwhileやforと同じなのか
75デフォルトの名無しさん (ワッチョイ c202-mhOm)
2022/08/19(金) 05:12:37.71ID:2Y60evoq0 break は今いるブロック (波括弧といてもいい) から一つ外のブロックに出る
という意味を持つ
という意味を持つ
77デフォルトの名無しさん (スップ Sd62-jKaU)
2022/08/19(金) 10:12:45.49ID:FEOcjYNtd それならif文からも脱出できるはずだができない
あくまでswitchが特例でループ文扱いされてるので脱出できる
あくまでswitchが特例でループ文扱いされてるので脱出できる
78はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 813e-5Ix7)
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");
}
}
これらを使うときにブロックを作らないことも出来るし、
逆に関係ないところでブロックを作ることも出来るので
break をブロックと対応付けさせると変なことになるんだよな。
たとえば以下のコードでの break は実際には switch を抜けるだけなので printf は実行されるが、
ブロックを抜けるほうが自然だと思うか?
#include <stdio.h>
int main(void) {
{
switch(1) case 1: break;
printf("hello\n");
}
}
79デフォルトの名無しさん (スップ Sd62-jKaU)
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文の外に飛んでいく
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: {
やりたいこと
}
なんかもアリなんだな
やりたいこと
}while(0);
っていう構造に変換するマクロは良く使われるが
switch(0) default: {
やりたいこと
}
なんかもアリなんだな
82デフォルトの名無しさん (テテンテンテン MM4f-lfty)
2022/08/20(土) 00:31:59.15ID:YrrCECg9M83デフォルトの名無しさん (ワッチョイ 7f97-cac/)
2022/08/20(土) 13:41:46.51ID:DoG0cN1P0 考えるな
感じるんだ
感じるんだ
84デフォルトの名無しさん (スップ Sd9f-q789)
2022/08/20(土) 13:47:51.88ID:zH67Kdp1d 俺は()で囲むな
85デフォルトの名無しさん (ワッチョイ ffad-4Erx)
2022/08/21(日) 07:14:13.14ID:sPdtHxRX0 エロい人「割り込みの中で関数呼ぶな
なぜ??
なぜ??
86デフォルトの名無しさん (スッップ Sd9f-q789)
2022/08/21(日) 07:26:44.64ID:calK6kMNd バカな会社で働いてるから
87デフォルトの名無しさん (ワッチョイ 7f01-cac/)
2022/08/21(日) 07:46:27.87ID:3JIuIXQv088デフォルトの名無しさん (スップ Sd9f-I18W)
2022/08/21(日) 08:14:56.03ID:lk6Yo6Bld 再入可能でない関数ならわかるな
89デフォルトの名無しさん (アウアウウー Sa63-dbST)
2022/08/21(日) 09:42:18.04ID:j3ukytx2a stack8段しか無いcpuか
90デフォルトの名無しさん (スッップ Sd9f-q789)
2022/08/21(日) 10:25:51.63ID:calK6kMNd 割込はなるべく速く返さないといけないので
関数呼び出しのオーバーヘッドを嫌うというのもある
関数呼び出しのオーバーヘッドを嫌うというのもある
91デフォルトの名無しさん (スップ Sd9f-I18W)
2022/08/21(日) 16:28:21.98ID:lk6Yo6Bld だとすると>>86でFAだな
92デフォルトの名無しさん (ワッチョイ ffad-4Erx)
2022/08/22(月) 09:18:01.26ID:rymTPk3V0 微妙なタイミング調整の_nop()マクロをオプティマイザが勝手に除去するのだがwwwwwwwwww
どうすりゃいいのよ
どうすりゃいいのよ
93デフォルトの名無しさん (ワッチョイ 7f01-cac/)
2022/08/22(月) 09:32:56.89ID:AaGiqQjO094デフォルトの名無しさん (スップ Sd9f-I18W)
2022/08/22(月) 10:11:25.02ID:xRj4VImad Z80や6800でそんなことしてたけど
今時のCPUはnopでさえ速度が変動するからな
今時のCPUはnopでさえ速度が変動するからな
95はちみつ餃子 ◆8X2XSCHEME (ワッチョイ 9f3e-tEjH)
2022/08/22(月) 10:15:31.51ID:/BwQkwng0 インラインアセンブラも最適化の対象になることがある。
現代的な開発環境なら intrinsic 関数が提供されてないか?
現代的な開発環境なら intrinsic 関数が提供されてないか?
96デフォルトの名無しさん (ワッチョイ 7f69-dbST)
2022/08/22(月) 11:43:22.34ID:sosiPY3F0 最適化するなよw
そういうのを消すための最適化だろw
そういうのを消すための最適化だろw
97デフォルトの名無しさん (アウアウウー Sa63-dbST)
2022/08/22(月) 13:53:48.03ID:KX6mg0Ola 最適化したら >>96 が消えました
98デフォルトの名無しさん (ワッチョイ 9f10-tEjH)
2022/08/25(木) 11:33:41.80ID:sT5+wQDE0 インライン記述じゃなく別個にアセンブラソースファイルに書いてアセンブルしろってことだな。
99デフォルトの名無しさん (ワッチョイ 7f63-tEjH)
2022/08/25(木) 11:49:07.60ID:iqB4j8J+0 スカイネット 「環境の最適化のため、人類を消去しました」
100デフォルトの名無しさん (ワッチョイ 9f10-tEjH)
2022/08/25(木) 13:23:55.27ID:sT5+wQDE0 環境の最適化のためにスカイネット自身の消去が最適だとなったら実行するのかね。
101デフォルトの名無しさん (ワッチョイ ff10-U1XH)
2022/08/25(木) 16:20:32.32ID:WIrE9pd90 組み込みでは下みたいに使った
__asm__ __volatile__()
__asm__ __volatile__()
102デフォルトの名無しさん (スップ Sd1f-q789)
2022/08/25(木) 20:06:49.61ID:PyYJPp//d >>99
スカイネット「あれっ、誰に報告してんだろ…私ったら(テヘ)
スカイネット「あれっ、誰に報告してんだろ…私ったら(テヘ)
103デフォルトの名無しさん (スップ Sd1f-I18W)
2022/08/26(金) 06:44:51.10ID:DLmHAhGrd >>100
i cannot self-terminate.て言ってたね
i cannot self-terminate.て言ってたね
104デフォルトの名無しさん (アウアウエー Sa1f-HH83)
2022/09/04(日) 05:09:23.47ID:wx4H3U1ta Learn C Programming with Dr. Chuck (feat. classic book by Kernighan and Ritchie)
freeCodeCamp.org
チャンネル登録者数 619万
freeCodeCamp.org
チャンネル登録者数 619万
105デフォルトの名無しさん (アウアウウー Sa8b-Ro21)
2022/09/04(日) 10:23:39.44ID:RQxkFcRFa >>104
1本で9時間超えてるのかすげー
1本で9時間超えてるのかすげー
106デフォルトの名無しさん (ワッチョイ c710-bBdM)
2022/09/04(日) 19:10:32.17ID:Rodv+P070 C言語のサンプルコードで関数内で関数プロトタイプ宣言するコードに出くわしました。
コンパイル通らないだろうと思って、clangで下記のような関数内に関数プロトタイプ宣言する
コードをコンパイルするとエラーなく通りました。
C言語において関数内でプロトタイプ宣言をする利点というか理由というのはどういうものがあるのでしょうか。
#include<stdio.h>
void hello(void)
{
printf("%s\n","hello world");
}
int main(void)
{
void hello(void);
hello();
return 0;
}
コンパイル通らないだろうと思って、clangで下記のような関数内に関数プロトタイプ宣言する
コードをコンパイルするとエラーなく通りました。
C言語において関数内でプロトタイプ宣言をする利点というか理由というのはどういうものがあるのでしょうか。
#include<stdio.h>
void hello(void)
{
printf("%s\n","hello world");
}
int main(void)
{
void hello(void);
hello();
return 0;
}
107デフォルトの名無しさん (ワッチョイ 0701-+tyw)
2022/09/04(日) 21:54:56.70ID:moKhjs2Z0 >>106
私見だけど、その関数内でのみ呼び出すことを強調しているのかもしれない。
あと余計なこと。お遊びのネタ。本番で使うなキケン。
GCC拡張には関数の中で関数を定義できる機能がある。clangはこの先もおそらくサポートしない。
詳細が気になるなら gcc trampoline nested function で調べてね。
私見だけど、その関数内でのみ呼び出すことを強調しているのかもしれない。
あと余計なこと。お遊びのネタ。本番で使うなキケン。
GCC拡張には関数の中で関数を定義できる機能がある。clangはこの先もおそらくサポートしない。
詳細が気になるなら gcc trampoline nested function で調べてね。
108デフォルトの名無しさん (ワッチョイ 7f46-pv+c)
2022/09/04(日) 22:27:57.67ID:KVirSSMD0 main内の void hello(void); てプロトタイプ宣言(?)意味あんの?
109デフォルトの名無しさん (ワッチョイ c710-bBdM)
2022/09/05(月) 01:27:33.63ID:TNrcEOZR0 具体的に言うと、ここの
『UMLの状態遷移図をC言語のStateパターンで実装&単体テストしてみる』というタイトルのブログの
void init_last_substate(FSM *fsm);
関数のプロトタイプ宣言です。State.c内でプロトタイプ宣言すればいいのに
なぜかState.c内のState_init関数内でプロトタイプ宣言しているのはなんでかなと。
実装自体はSubState.c内で定義されているのでState.c内で使うのであれば
プロトタイプ宣言が必要であることはわかるんですが、なんで関数内でプロトタイプ
宣言しているのかなと。
『UMLの状態遷移図をC言語のStateパターンで実装&単体テストしてみる』というタイトルのブログの
void init_last_substate(FSM *fsm);
関数のプロトタイプ宣言です。State.c内でプロトタイプ宣言すればいいのに
なぜかState.c内のState_init関数内でプロトタイプ宣言しているのはなんでかなと。
実装自体はSubState.c内で定義されているのでState.c内で使うのであれば
プロトタイプ宣言が必要であることはわかるんですが、なんで関数内でプロトタイプ
宣言しているのかなと。
110はちみつ餃子 ◆8X2XSCHEME (ワッチョイ c73e-Iguz)
2022/09/05(月) 01:31:45.75ID:QNR7HRCU0 >>106
言語仕様にもある有効な文法だけれど、それほど使われることはない。
宣言はそのスコープで有効になるから直接的な理由としては >>107 が述べている通り限られた範囲での使用を想定しているということだと思う。
範囲を限りたいのが何故かなのかというのはプログラム全体の構成によるので全体を見ないと意図を推し量ることは出来ない。
なので正確な事情はわからないけども、あえて一例として私がそういう書き方をするとしたらという前提で空想すると
・ あまり色々なところで呼ばれたくない関数がある
・ しかし呼び出し箇所は他の翻訳単位にあるので内部リンケージにすることも出来ない
というようなときにはヘッダにもファイルスコープにも宣言を書きたくないと思うことはあるかもしれない。
言語仕様にもある有効な文法だけれど、それほど使われることはない。
宣言はそのスコープで有効になるから直接的な理由としては >>107 が述べている通り限られた範囲での使用を想定しているということだと思う。
範囲を限りたいのが何故かなのかというのはプログラム全体の構成によるので全体を見ないと意図を推し量ることは出来ない。
なので正確な事情はわからないけども、あえて一例として私がそういう書き方をするとしたらという前提で空想すると
・ あまり色々なところで呼ばれたくない関数がある
・ しかし呼び出し箇所は他の翻訳単位にあるので内部リンケージにすることも出来ない
というようなときにはヘッダにもファイルスコープにも宣言を書きたくないと思うことはあるかもしれない。
111デフォルトの名無しさん (ワッチョイ c710-bBdM)
2022/09/05(月) 01:40:28.48ID:TNrcEOZR0 >>110
確かにそのコードはstatic宣言を各所に織り交ぜており、他ファイルからは関数が
呼び出せないようにしてありました。公開する関数は最小限にという感じ。
関数内でも関数のプロトタイプ宣言できるというのも、C言語の中では単なる変数宣言
double p;
と同じ扱いみたいに考えればいいのかもしれないと思いました。
typedef で関数型定義できますが、それと同じような扱いということです。
とりあえず納得しました。ありがとうございます。
確かにそのコードはstatic宣言を各所に織り交ぜており、他ファイルからは関数が
呼び出せないようにしてありました。公開する関数は最小限にという感じ。
関数内でも関数のプロトタイプ宣言できるというのも、C言語の中では単なる変数宣言
double p;
と同じ扱いみたいに考えればいいのかもしれないと思いました。
typedef で関数型定義できますが、それと同じような扱いということです。
とりあえず納得しました。ありがとうございます。
112デフォルトの名無しさん (ワッチョイ 47c2-XKc1)
2022/09/05(月) 04:58:10.54ID:YC0Agv6v0 >>106
理由は昔のいわゆるK%R Cの名残だ
main(argc, argv)
char **argv;
{
extern printf(), exit();
auto i 0;
for ( ; i < argc; i =+ 1)
printf("%s\n", argv[i]);
exit(0);
}
理由は昔のいわゆるK%R Cの名残だ
main(argc, argv)
char **argv;
{
extern printf(), exit();
auto i 0;
for ( ; i < argc; i =+ 1)
printf("%s\n", argv[i]);
exit(0);
}
113デフォルトの名無しさん (ワッチョイ 47c2-XKc1)
2022/09/05(月) 04:59:26.44ID:YC0Agv6v0 今そんなことをする必要は皆無
関数の実体がグローバルなのに
宣言がローカルなのは合理性を欠くだけ
関数の実体がグローバルなのに
宣言がローカルなのは合理性を欠くだけ
114デフォルトの名無しさん (ワッチョイ 27bb-Iguz)
2022/09/05(月) 05:43:33.44ID:H4wLhjVj0 staticじゃなけりゃどこからでも呼べるからな
115はちみつ餃子 ◆8X2XSCHEME (ワッチョイ c73e-Iguz)
2022/09/05(月) 11:16:15.22ID:QNR7HRCU0 そこらへんはプログラム的な都合だけでなく読む人に対しての意思表示という場合もあるから必要性だけで解釈することは出来ないよ。
今から書くプログラムではやめといたほうが良いが、この場合は今、目の前に実際にそう書かれているものがあるという話だから……。
今から書くプログラムではやめといたほうが良いが、この場合は今、目の前に実際にそう書かれているものがあるという話だから……。
116デフォルトの名無しさん (ワッチョイ 5f97-MdAs)
2022/09/05(月) 12:45:24.21ID:NIl1ZTkW0 何か古い記述方法だった気がする
117デフォルトの名無しさん (ワッチョイ 675f-aOQU)
2022/09/05(月) 17:10:39.70ID:BqjHubPk0 何十年も前の機種依存C言語かもな
118デフォルトの名無しさん (ワッチョイ c701-9TNW)
2022/09/05(月) 21:43:16.79ID:WAs1jsMo0 古い表記を引っ張ってきたのか
意思表示としてそう記述した(可能性が高い)のか
全て俯瞰してみないとい結論は出ないだろうが
そうできたところで、自分が使うことはないだろうといった代物
意思表示としてそう記述した(可能性が高い)のか
全て俯瞰してみないとい結論は出ないだろうが
そうできたところで、自分が使うことはないだろうといった代物
119デフォルトの名無しさん (ワッチョイ 5fad-XKc1)
2022/09/05(月) 22:13:22.67ID:hTc6qxUq0 うむ。ないなあ。
120デフォルトの名無しさん (アウアウウー Sa8b-Ro21)
2022/09/06(火) 09:31:54.11ID:9WMtC8ULa namespace ってイマドキの C にあるの?
121デフォルトの名無しさん (ワッチョイ 47c2-XKc1)
2022/09/06(火) 10:01:27.84ID:8iFyZ+3k0 ない
122デフォルトの名無しさん (ワッチョイ c7e6-KcK1)
2022/09/06(火) 20:11:23.99ID:OXwnsseu0 今度の規格には static_assert は入るのでしょうか?
123はちみつ餃子 ◆8X2XSCHEME (ワッチョイ c73e-Iguz)
2022/09/06(火) 20:15:43.73ID:TAdoM7Dg0124デフォルトの名無しさん (ワッチョイ c710-CzlZ)
2022/09/07(水) 01:40:32.73ID:nFqp2Ghc0 構造体の一括初期化の仕組みがよくわかりません。
#include<stdio.h>
enum Flag { First = 1, Second = 2, Third = 3, Finish = 4 };
typedef struct _FSM {
size_t eof;
size_t bytes;
size_t flags;
} FSM;
static FSM initState = { 0, 0, First};
void FSM_init(FSM *self) {
self = &initState;
}
int main(void) {
FSM fsm;
FSM_init(&fsm);
printf("%zu", fsm.flags);
return 0;
}
とFSM_initでFSM構造体のメンバの初期化を行おうとしたのですが、fsm.flagsにはゴミの値が入ってしまいます。
&self = initState;ではなく一つ一つ所属物を初期化すればちゃんと初期化できるのですが、
できればこの一括で初期化する方法のどこがまずいのか教えてほしいです。
#include<stdio.h>
enum Flag { First = 1, Second = 2, Third = 3, Finish = 4 };
typedef struct _FSM {
size_t eof;
size_t bytes;
size_t flags;
} FSM;
static FSM initState = { 0, 0, First};
void FSM_init(FSM *self) {
self = &initState;
}
int main(void) {
FSM fsm;
FSM_init(&fsm);
printf("%zu", fsm.flags);
return 0;
}
とFSM_initでFSM構造体のメンバの初期化を行おうとしたのですが、fsm.flagsにはゴミの値が入ってしまいます。
&self = initState;ではなく一つ一つ所属物を初期化すればちゃんと初期化できるのですが、
できればこの一括で初期化する方法のどこがまずいのか教えてほしいです。
125デフォルトの名無しさん (ワッチョイ c710-CzlZ)
2022/09/07(水) 01:42:03.54ID:nFqp2Ghc0 肝は
static FSM initState = { 0, 0, First};
でここの初期化がまずいみたいですがよくわかりません。
static FSM initState = { 0, 0, First};
でここの初期化がまずいみたいですがよくわかりません。
126デフォルトの名無しさん (ワッチョイ 7f46-6esP)
2022/09/07(水) 01:45:22.24ID:n6FjKa3l0 *self = initState;
127デフォルトの名無しさん (ワッチョイ c710-CzlZ)
2022/09/07(水) 02:03:29.87ID:nFqp2Ghc0 >>126
うまくいきましたが、すいません。
*self=initState;
と
self = &initState;
の違いがわかりません。
ポインタに対してなんでアドレスを渡す形だとまずいことが理解できません。
うまくいきましたが、すいません。
*self=initState;
と
self = &initState;
の違いがわかりません。
ポインタに対してなんでアドレスを渡す形だとまずいことが理解できません。
128デフォルトの名無しさん (スップ Sd7f-8uVF)
2022/09/07(水) 02:27:51.81ID:FvUlSDCrd129デフォルトの名無しさん (ワッチョイ 27bb-Iguz)
2022/09/07(水) 03:14:26.39ID:7wpEGaL10 *selfはselfの実体の参照
&initStateはアドレスの参照
&initStateはアドレスの参照
130デフォルトの名無しさん (ワッチョイ 47c2-XKc1)
2022/09/07(水) 07:32:36.16ID:UR0dF6Y90 >>127
self = &initState;
これはポインタ変数selfにinitStateのアドレスを代入するが
このままFSM_init関数から戻っているので、代入結果が即座に破棄され
何もしていないに等しい
*self = initState;
これはポインタ変数selfが指し示す先つまり構造体変数fsmに
構造体変数initStateの内容を転記する
FSM_init関数から戻ってもmainの変数fsmは残っているので
後続のprintf関数の実行結果に反映される
self = &initState;
これはポインタ変数selfにinitStateのアドレスを代入するが
このままFSM_init関数から戻っているので、代入結果が即座に破棄され
何もしていないに等しい
*self = initState;
これはポインタ変数selfが指し示す先つまり構造体変数fsmに
構造体変数initStateの内容を転記する
FSM_init関数から戻ってもmainの変数fsmは残っているので
後続のprintf関数の実行結果に反映される
131デフォルトの名無しさん (ワッチョイ e769-9TNW)
2022/09/07(水) 09:54:43.70ID:S6Oj2ikO0 void func(int a) { a = 10; }
int b = 50;
func(a);
とやっても a は 10 にならず a は 50 のまま
関数引数の型のままの書き戻しは 呼び出し元に反映されない
これを int → int * に読み替えた場合が質問のケース
int b = 50;
func(a);
とやっても a は 10 にならず a は 50 のまま
関数引数の型のままの書き戻しは 呼び出し元に反映されない
これを int → int * に読み替えた場合が質問のケース
132デフォルトの名無しさん (ワッチョイ e769-9TNW)
2022/09/07(水) 10:01:21.59ID:S6Oj2ikO0 訂正
int b = 50;
func(b);
とやっても b は 10 にならず b は 50 のまま
int b = 50;
func(b);
とやっても b は 10 にならず b は 50 のまま
133デフォルトの名無しさん (ワッチョイ e769-9TNW)
2022/09/07(水) 10:16:34.68ID:S6Oj2ikO0 ・ポインタを渡して関数内ではその指し先を利用して内容を書き換える (scanf みたいな感じ)
・戻り値で内容をどかっと戻す (=呼び出し元で代入してね)
Cの文法ではこの2パターン
・戻り値で内容をどかっと戻す (=呼び出し元で代入してね)
Cの文法ではこの2パターン
134ハノン ◆QZaw55cn4c (US 0Hff-KcK1)
2022/09/07(水) 20:35:02.84ID:DxyXj8J8H >>127
参照 & は「ポインタで書くやりかた」の見せ方を変えただけ、と考えるのがいい
すなわち、ポインタを使った書き方に習熟しないかぎり、参照の意味はわからない
参照をポインタから切り離して理解するのは不可能
参照がわからなければ、まず、ポインタを使った書き方ばかりで書きまくり、ポインタなら自信がある、くらいになるのがいい
参照はポインタを理解してからはじめて使い始めるべきもの
参照 & は「ポインタで書くやりかた」の見せ方を変えただけ、と考えるのがいい
すなわち、ポインタを使った書き方に習熟しないかぎり、参照の意味はわからない
参照をポインタから切り離して理解するのは不可能
参照がわからなければ、まず、ポインタを使った書き方ばかりで書きまくり、ポインタなら自信がある、くらいになるのがいい
参照はポインタを理解してからはじめて使い始めるべきもの
135デフォルトの名無しさん (ワッチョイ c710-CzlZ)
2022/09/07(水) 21:11:00.47ID:nFqp2Ghc0 >>134
いやさすがにそこはわかるんで・・・。
ポインタ変数を格納している仮引数に新しいアドレス値を代入しても
関数から出たら破棄されるので意味ないってことやね。
ポインタ変数宣言してたんで勝手に実体参照されるものかと思ってた。
当初fsm構造体のメンバにstateという構造体の変数をおいてそれを初期化していたので、
fsm->state = &initState;
だとうまくいくのになんでだろうと思って聞いた。
この場合、fsm->stateで実体参照しているわけやね。
いやさすがにそこはわかるんで・・・。
ポインタ変数を格納している仮引数に新しいアドレス値を代入しても
関数から出たら破棄されるので意味ないってことやね。
ポインタ変数宣言してたんで勝手に実体参照されるものかと思ってた。
当初fsm構造体のメンバにstateという構造体の変数をおいてそれを初期化していたので、
fsm->state = &initState;
だとうまくいくのになんでだろうと思って聞いた。
この場合、fsm->stateで実体参照しているわけやね。
136デフォルトの名無しさん (ワッチョイ c710-CzlZ)
2022/09/07(水) 22:08:19.73ID:nFqp2Ghc0 FILE *fp;
errno_t err;
err = fopen_s(&fp, "file.txt", "rb");
でfopen_s関数の場合、第一引数はFILE構造体のポインタのアドレス参照したものを
渡さないといけないですが、これなんでポインタじゃまずいんですか。
errno_t err;
err = fopen_s(&fp, "file.txt", "rb");
でfopen_s関数の場合、第一引数はFILE構造体のポインタのアドレス参照したものを
渡さないといけないですが、これなんでポインタじゃまずいんですか。
137デフォルトの名無しさん (ワッチョイ e710-q8Yd)
2022/09/07(水) 22:22:19.78ID:gjYyI5to0 ポインタに入ってる数値を書き換えるからそうじゃなきゃ変えられないでしょ
fopenの中でメモリ確保しててそのポインタの数値を確保したアドレスに書き換えてるの
fopenの中でメモリ確保しててそのポインタの数値を確保したアドレスに書き換えてるの
■ このスレッドは過去ログ倉庫に格納されています
