C言語の話題のみ取り扱います。C++の話題はC++スレへ。
上級者専用です。10,000行程度のソースを扱えない人は以下スレへ。
C言語なら俺に聞け
https://mevius.5ch.net/test/read.cgi/tech/1519046038/
適宜以下を使用してください。
https://paiza.io/
https://ideone.com/
http://codepad.org/
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/
次スレを立てる時は本文の1行目に以下を追加して下さい。
!extend:on:vvvvv:1000:512
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
探検
C言語相談室(上級者専用)
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (ワッチョイ 139f-Cjmv)
2018/03/02(金) 22:48:03.65ID:2Cs+DkMh045デフォルトの名無しさん (ワッチョイ f564-n6Dg)
2018/05/12(土) 15:19:25.30ID:V7PQOWmO0 >>44
その言い方、Rustを結構使っているように見えますが、違いますか?
Cが「ミニマルだ」ということには——少なくともISO C99規格を見るに——あまり賛同できないんですが、
それはまぁ、置いておいて、私がRustを触った限り、あれはC++の代替に見えます。
C++が現在も(規格を拡張する方向に)積極的に開発されているのは分かっていますし、
「だからRustが取って代わる必要はないのだ」という理論的帰結も理解できますが、
ポインタの安全性ややはり名前空間の宣言あたりを見ると(あくまで触りですが)どうしてもC++の文法を彷彿とさせるの
構造が多いように思いますね。
その言い方、Rustを結構使っているように見えますが、違いますか?
Cが「ミニマルだ」ということには——少なくともISO C99規格を見るに——あまり賛同できないんですが、
それはまぁ、置いておいて、私がRustを触った限り、あれはC++の代替に見えます。
C++が現在も(規格を拡張する方向に)積極的に開発されているのは分かっていますし、
「だからRustが取って代わる必要はないのだ」という理論的帰結も理解できますが、
ポインタの安全性ややはり名前空間の宣言あたりを見ると(あくまで触りですが)どうしてもC++の文法を彷彿とさせるの
構造が多いように思いますね。
46デフォルトの名無しさん (ワッチョイ f564-n6Dg)
2018/05/12(土) 15:20:29.04ID:V7PQOWmO0 あ、すいません。一行目で使ったことがないと断られていました。
いや、なぜ確認しなかったんだろう、失礼しました。
いや、なぜ確認しなかったんだろう、失礼しました。
47デフォルトの名無しさん (ワッチョイ 559f-XfH4)
2018/05/18(金) 23:11:30.66ID:qSToTkUZ0 >>45
> あれはC++の代替に見えます。
それは正しい。
というか、「後継」と「代替」はこの場合明確に区別して使われるべきだ。
・「○○の後継」---○○言語を発展させたもの。
上位互換であり、○○言語と共に使うことを考慮されている。
・「○○の代替」---○○言語の代わりに使うもの。
基本的に○○言語と一緒に使うことはない。排他的使用となる。
Rustの謳い文句は、「効率的なCバインディング」であって、
「効率的な『C++』バインディング」ではないんだよ。
CのDLLは当然呼べるが、C++のDLLを呼べるように出来ているか?
C++の「後継」と言うのなら、基本的にはC++の資産を全活用できる方向になってないといけない。
ただしそもそもC++は「後継」用のAPIを整備して無いと思うんだが。
C++の例外「実装」についてググッても、まともな文献が出てこないだろ。
おそらくあれは「実装」まで言及した仕様ではなく、「言語としての動作規定」しかされてないんだ。
(元々C++はそういうノリだし)
だからtry-catchを含んだ関数をDLL化できて他言語から呼べるかはかなり疑問だ。
勿論、昔からの課題だから今は解決されているかもしれんが。
> Throwing C++ exceptions across DLL boundaries is only possible when all modules use the same C++ runtime,
> in which case they share a heap as well. But this can be a maintenance burden,
> especially when libraries from multiple vendors are involved, so it is discouraged.
> https://stackoverflow.com/questions/5107948/throwing-c-exceptions-across-dll-boundaries
だからCのDLLは他言語(Rust/Ruby/C++/C#)等から直接呼べるが、
C++のDLLを呼べます、と謳っている奴はいないだろ。
この点において、C++は後継言語の存在を許していない。
だからRustはCの「後継」であり、C++の「代替」というのが妥当な見方なんだよ。
実際、RustがあればC++を使う意味がないだろ。
> あれはC++の代替に見えます。
それは正しい。
というか、「後継」と「代替」はこの場合明確に区別して使われるべきだ。
・「○○の後継」---○○言語を発展させたもの。
上位互換であり、○○言語と共に使うことを考慮されている。
・「○○の代替」---○○言語の代わりに使うもの。
基本的に○○言語と一緒に使うことはない。排他的使用となる。
Rustの謳い文句は、「効率的なCバインディング」であって、
「効率的な『C++』バインディング」ではないんだよ。
CのDLLは当然呼べるが、C++のDLLを呼べるように出来ているか?
C++の「後継」と言うのなら、基本的にはC++の資産を全活用できる方向になってないといけない。
ただしそもそもC++は「後継」用のAPIを整備して無いと思うんだが。
C++の例外「実装」についてググッても、まともな文献が出てこないだろ。
おそらくあれは「実装」まで言及した仕様ではなく、「言語としての動作規定」しかされてないんだ。
(元々C++はそういうノリだし)
だからtry-catchを含んだ関数をDLL化できて他言語から呼べるかはかなり疑問だ。
勿論、昔からの課題だから今は解決されているかもしれんが。
> Throwing C++ exceptions across DLL boundaries is only possible when all modules use the same C++ runtime,
> in which case they share a heap as well. But this can be a maintenance burden,
> especially when libraries from multiple vendors are involved, so it is discouraged.
> https://stackoverflow.com/questions/5107948/throwing-c-exceptions-across-dll-boundaries
だからCのDLLは他言語(Rust/Ruby/C++/C#)等から直接呼べるが、
C++のDLLを呼べます、と謳っている奴はいないだろ。
この点において、C++は後継言語の存在を許していない。
だからRustはCの「後継」であり、C++の「代替」というのが妥当な見方なんだよ。
実際、RustがあればC++を使う意味がないだろ。
48デフォルトの名無しさん (ワッチョイ 559f-XfH4)
2018/05/18(金) 23:12:06.97ID:qSToTkUZ0 Cは大規模コードに対するサポートが全くない。
とはいえ、「やれば出来るだろ by Linus」なのは事実だが、実際それでは辛いわけで、
コンパイラに任せられるところは任すという方向で上手く手抜きできるように進化させたのがC++だ。
Rustも同じ方向なのだから同様の物になるのは当たり前。
当然、どちらかを使用すれば事足り、RustとC++は排他関係になる。
つまり、RustはCの「後継」であり、C++の「代替」だ。おそらくここまでは大体の人が納得するはず。
問題はCの「代替」にもなり得るか?という点であり、だからそこが議論されているわけだ。
今現在もCを使うメリットは速度面しかない。したがって速度面のデメリットがなければ良く、
「ゼロコスト抽象化」等、速さにこだわっているのはそこなんだよ。
ただ俺個人としては、全体を一つの言語で書く必要なんて全くなくて、
NumPyのアプローチ、つまりどうでもいいところ(9割以上)はスクリプト言語で書き、
必要なところだけCのDLLを呼ぶ、というのが正しい気がするが。C#もこの方向だね。
この場合、リソース管理をGC言語側に任せられ、
また個別関数単位での切り出しになり、
DLL内関数はお互い独立(非依存)で行っても1,000行とかでしかなく、
Cでも全く問題にならないんだよ。
だからRustも微妙に中途半端な方向だとは思うが、
もし仮にCを代替できるのなら、それは素晴らしいと思うよ。
とはいえ、「やれば出来るだろ by Linus」なのは事実だが、実際それでは辛いわけで、
コンパイラに任せられるところは任すという方向で上手く手抜きできるように進化させたのがC++だ。
Rustも同じ方向なのだから同様の物になるのは当たり前。
当然、どちらかを使用すれば事足り、RustとC++は排他関係になる。
つまり、RustはCの「後継」であり、C++の「代替」だ。おそらくここまでは大体の人が納得するはず。
問題はCの「代替」にもなり得るか?という点であり、だからそこが議論されているわけだ。
今現在もCを使うメリットは速度面しかない。したがって速度面のデメリットがなければ良く、
「ゼロコスト抽象化」等、速さにこだわっているのはそこなんだよ。
ただ俺個人としては、全体を一つの言語で書く必要なんて全くなくて、
NumPyのアプローチ、つまりどうでもいいところ(9割以上)はスクリプト言語で書き、
必要なところだけCのDLLを呼ぶ、というのが正しい気がするが。C#もこの方向だね。
この場合、リソース管理をGC言語側に任せられ、
また個別関数単位での切り出しになり、
DLL内関数はお互い独立(非依存)で行っても1,000行とかでしかなく、
Cでも全く問題にならないんだよ。
だからRustも微妙に中途半端な方向だとは思うが、
もし仮にCを代替できるのなら、それは素晴らしいと思うよ。
49デフォルトの名無しさん (ワッチョイ 89fa-9WOx)
2018/05/23(水) 19:34:50.63ID:Au5e7VGg0 僕の知り合いの知り合いができたパソコン一台でお金持ちになれるやり方
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
8UTJJ
役に立つかもしれません
グーグルで検索するといいかも『ネットで稼ぐ方法 モニアレフヌノ』
8UTJJ
50デフォルトの名無しさん (ワッチョイ 398a-EdLk)
2018/05/24(木) 16:09:00.92ID:6FiN0bsr0 114.149.223.252
51デフォルトの名無しさん (ワッチョイ 2964-8/hF)
2018/07/02(月) 19:57:22.74ID:tgZxuU9E0 RustはCの「後継」であり、C++の「代替」
これでRust周りの(宗教戦争じみた)論争の理由が理解できた。
これでRust周りの(宗教戦争じみた)論争の理由が理解できた。
52デフォルトの名無しさん (ワッチョイ 45fa-2e90)
2018/07/04(水) 22:51:20.65ID:gFgZc5FG0 NTB
53デフォルトの名無しさん (ワッチョイ 87b3-JyQx)
2018/07/09(月) 23:31:02.20ID:bV3eVpry0 NTR
54デフォルトの名無しさん (ワッチョイ 3764-7dBI)
2018/07/26(木) 02:18:42.03ID:BvZq73xc0 ポインタってさ、「指示子」と和訳したら分かりやすいと思うんだが
そうしなかった理由ってなんだろ
それとも俺の感性がおかしいだけか
そうしなかった理由ってなんだろ
それとも俺の感性がおかしいだけか
55デフォルトの名無しさん (アウアウウー Sa43-lgLX)
2018/07/26(木) 02:38:35.19ID:rK3i9Ft7a 昔、筧先生ってひとがいて…
56デフォルトの名無しさん (ワッチョイ 3764-7dBI)
2018/07/27(金) 01:03:48.10ID:GvW3yrkV0 >>55
kwsk
kwsk
57デフォルトの名無しさん (ワッチョイ 6f9f-53i4)
2018/07/27(金) 03:35:26.85ID:O4NPrPXG0 ちょっと10回言ってみ
言い辛いよな
言い辛いよな
58デフォルトの名無しさん (ワッチョイ 3764-7dBI)
2018/07/27(金) 17:21:35.88ID:GvW3yrkV0 え? なに? もしかして昔なにか荒れる原因になった ANDOR 問題のある人が使ってた用語なのか。
若いもんで知らなかったわ すいません。
若いもんで知らなかったわ すいません。
59デフォルトの名無しさん (ワッチョイ 9f93-BNWp)
2018/07/28(土) 09:57:54.67ID:VMG9DnUG0 「指示子のgcc拡張」みたいな早口言葉モドキができて面白いかも。
60デフォルトの名無しさん (アウアウエー Saaa-2QVD)
2018/07/28(土) 13:58:33.27ID:39ICzHjEa 指示子の指示子
指示子の配列
配列の指示子
配列の指示子の指示子
指示子の配列の指示子
ダブル指示子
配列の指示子の配列 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
指示子の配列
配列の指示子
配列の指示子の指示子
指示子の配列の指示子
ダブル指示子
配列の指示子の配列 👀
Rock54: Caution(BBR-MD5:1341adc37120578f18dba9451e6c8c3b)
61デフォルトの名無しさん (ワッチョイ e3af-hN3z)
2018/07/28(土) 15:05:25.84ID:BHZfW2WL0 >>60
なんかおこられてやんの
なんかおこられてやんの
62デフォルトの名無しさん (アウアウエー Saaa-2QVD)
2018/07/28(土) 15:08:57.51ID:39ICzHjEa こんなので目玉付くんだなω
63デフォルトの名無しさん (ワッチョイ 4364-vmb7)
2018/08/05(日) 00:49:09.36ID:fZk3Cg460 C99(ISO/IEC 9899:1999)で,main()関数の型がintな理由ってどこかに書いてあるっけ。
今ふと,リターンコードって0から255の整数なんだから
uint8_t main(...
としても問題ないよなと思ってさ。
今ふと,リターンコードって0から255の整数なんだから
uint8_t main(...
としても問題ないよなと思ってさ。
64デフォルトの名無しさん (ワッチョイ 4364-vmb7)
2018/08/05(日) 00:50:03.59ID:fZk3Cg460 すまん。途中で送信してしまった。
そうするとコンパイラにmain()の型はintだと怒られた。
そうするとコンパイラにmain()の型はintだと怒られた。
65デフォルトの名無しさん (アウアウウー Saa7-Okn4)
2018/08/05(日) 01:34:55.28ID:/g7t90jda 型がintというのは決まってる。
実際の範囲は実装依存。windowsだと違ってなかったか?
実際の範囲は実装依存。windowsだと違ってなかったか?
66デフォルトの名無しさん (ワッチョイ a39f-Xflc)
2018/08/05(日) 07:12:37.38ID:cdvogGHQ0 main()が戻す値は呼び出す側の問題だとは思うが、その部分(crt0とか)は普通はC言語に合わせてintを
返してくると想定して作られていると思う。しかしその部分まで自作するというのであればなんでもアリではある。
https://en.wikipedia.org/wiki/Crt0
返してくると想定して作られていると思う。しかしその部分まで自作するというのであればなんでもアリではある。
https://en.wikipedia.org/wiki/Crt0
67デフォルトの名無しさん (ワッチョイ 6393-o77x)
2018/08/05(日) 08:37:27.73ID:5+7WSxVZ0 シェルが受け入れるコマンドの終了ステータスの値が0-255の範囲、
てのはUNIX系もDOS系も(珍しく)一致してるのね。
unsigned char の外に出ないことは間違いないわね。
ANSI以前の古いCでの「宣言なしに使われた外部関数はintの値を返す」
という仕様が、規格化したときに互換性の問題を生まないように
main()の返り値はintと決めたんじゃないかしら。
てのはUNIX系もDOS系も(珍しく)一致してるのね。
unsigned char の外に出ないことは間違いないわね。
ANSI以前の古いCでの「宣言なしに使われた外部関数はintの値を返す」
という仕様が、規格化したときに互換性の問題を生まないように
main()の返り値はintと決めたんじゃないかしら。
68デフォルトの名無しさん (ワッチョイ 4364-vmb7)
2018/08/05(日) 12:29:08.02ID:fZk3Cg460 なるほど。まあ過去互換性は重要だしね。
ただ,CはPOSIXというOSの標準規格を定めてる団体が関与して設計されてるから「リターンコードは0--255。よってmain関数の型はuint8_t」と割り切ってくれてもいいのになぁ。
とか勝手に思ったりしてる。
ただ,CはPOSIXというOSの標準規格を定めてる団体が関与して設計されてるから「リターンコードは0--255。よってmain関数の型はuint8_t」と割り切ってくれてもいいのになぁ。
とか勝手に思ったりしてる。
69デフォルトの名無しさん (アウアウウー Saa7-Okn4)
2018/08/05(日) 13:13:57.79ID:/g7t90jda まあintが妥当だろう。
しかし、_exit()に渡すのがintでwait()した時も一応exit statusはintだよな。
どこで上位ビット欠落させてんだ?
しかし、_exit()に渡すのがintでwait()した時も一応exit statusはintだよな。
どこで上位ビット欠落させてんだ?
70デフォルトの名無しさん (ワッチョイ a39f-Xflc)
2018/08/05(日) 18:30:06.69ID:cdvogGHQ071デフォルトの名無しさん (ワッチョイ 4364-vmb7)
2018/08/06(月) 01:15:24.28ID:/d0+B2Ty0 ちょっとCの範疇を越えた話になるけど
リターンコードが0--255ってどういう段階で決定されたんだろう。
DOSとUnixが同じ範囲のリターンコードを持ってるって、偶然とは考えがたいんだけども
リターンコードが0--255ってどういう段階で決定されたんだろう。
DOSとUnixが同じ範囲のリターンコードを持ってるって、偶然とは考えがたいんだけども
72デフォルトの名無しさん (ワッチョイ b3e3-0Uuo)
2018/08/06(月) 02:07:20.39ID:xc/1a6k50 unix等の先行者を参考にDOSを作ったんだから
73デフォルトの名無しさん (ワッチョイ 6393-o77x)
2018/08/06(月) 07:45:24.26ID:1aQ1rnwf0 DOSの終了ステータスはUNIXの仕様をそのまま使用だと思う。
UNIXの方は、子プロセスを作って別の仕事をさせるって定型処理で、
「親プロセスで子プロセスの終了を待つ」ためのwait()系の関数が、
・子プロセスが正常終了した場合は子プロセスの終了ステータス
・子プロセスが割込みで中断された場合は割込みの種類
という2つの情報を1個の返り値で戻すことと関係あるのじゃないかな。
1個の整数値を上位と下位のビット群に分けて別の情報として使うために
それぞれの情報量を1バイトずつに制限した、と。
UNIXの方は、子プロセスを作って別の仕事をさせるって定型処理で、
「親プロセスで子プロセスの終了を待つ」ためのwait()系の関数が、
・子プロセスが正常終了した場合は子プロセスの終了ステータス
・子プロセスが割込みで中断された場合は割込みの種類
という2つの情報を1個の返り値で戻すことと関係あるのじゃないかな。
1個の整数値を上位と下位のビット群に分けて別の情報として使うために
それぞれの情報量を1バイトずつに制限した、と。
74デフォルトの名無しさん (ワッチョイ 3323-yKTt)
2018/08/06(月) 08:23:05.65ID:jTWGCXc00 UNIX板のおじさんに聞いてみたら
75デフォルトの名無しさん (ワッチョイ 5ed5-ISgX)
2018/08/26(日) 08:24:46.45ID:dLFVucRz0 auto変数で char配列を可変長で動的に確保する方法は無いかな。
アセンブラレベルならスタックポインタを操作すれば可能だと思うが。
文字列処理の内部バッファとして入力に合わせたサイズを確保したいんだが、とりあえず今は固定長バッファとそれを超える場合は malloc でやってる。
アセンブラレベルならスタックポインタを操作すれば可能だと思うが。
文字列処理の内部バッファとして入力に合わせたサイズを確保したいんだが、とりあえず今は固定長バッファとそれを超える場合は malloc でやってる。
76さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 09:09:31.40ID:Vxoswi+gd alloca
77デフォルトの名無しさん (ワッチョイ eab3-vpIp)
2018/08/26(日) 09:18:39.26ID:O9adGcKd078デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 09:29:28.31ID:ik1BtrwR07975 (ワッチョイ 5ed5-ISgX)
2018/08/26(日) 09:31:08.30ID:dLFVucRz0 >>76-77
ありがとう、まさにぴったり。
言語レベルでの可変長配列は C11 から(オプションだけど)入ってるんだね。
90年代からメンテされてるコードだからそっちは使えなそうだけど、alloca を検討してみる。
ありがとう、まさにぴったり。
言語レベルでの可変長配列は C11 から(オプションだけど)入ってるんだね。
90年代からメンテされてるコードだからそっちは使えなそうだけど、alloca を検討してみる。
80デフォルトの名無しさん (ワッチョイ eab3-vpIp)
2018/08/26(日) 10:56:05.32ID:O9adGcKd0 >>79
環境わからんからなんとも言えんが組込みとかWindowsとか意外にスタックサイズがしょぼい環境あるから気を付けてね
環境わからんからなんとも言えんが組込みとかWindowsとか意外にスタックサイズがしょぼい環境あるから気を付けてね
81デフォルトの名無しさん (アウアウウー Saa1-ROXf)
2018/08/26(日) 11:49:56.37ID:hQMrm9ZNa いやいや、C99からだよ。C11でオプションになった。答える方はそのくらい知っとけよ。
まあ入力が小さいのが予め分かってないと使いにくい機能だよ。
まあ入力が小さいのが予め分かってないと使いにくい機能だよ。
82デフォルトの名無しさん (ワッチョイ ed9f-PcWx)
2018/08/26(日) 13:04:10.92ID:HHP/3bjy0 >>75
その入力というのがファイルからの1行入力みたいなものならば getline() 使ってしまえば
自分で考える必要がなくて楽だ。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/getline.3.html
その入力というのがファイルからの1行入力みたいなものならば getline() 使ってしまえば
自分で考える必要がなくて楽だ。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/getline.3.html
83デフォルトの名無しさん (ワッチョイ bd93-zO5i)
2018/08/26(日) 15:51:52.71ID:0Dyu3Dip0 発端の >>75 の意図次第だが、free()しなくても安全に蒸発して欲しいとか、
ヒープの確保と解放の処理時間を嫌っての話ならgetline()はちょいと違うね。
文字数の予測が難しい入力を扱うにはとても便利なんだけど。
それにしても「上級者専用」って看板が架かってることを意識すると
このスレッドは書き込みにくいな。気後れしちゃう。
ヒープの確保と解放の処理時間を嫌っての話ならgetline()はちょいと違うね。
文字数の予測が難しい入力を扱うにはとても便利なんだけど。
それにしても「上級者専用」って看板が架かってることを意識すると
このスレッドは書き込みにくいな。気後れしちゃう。
84デフォルトの名無しさん (ワッチョイ ed68-DNis)
2018/08/26(日) 16:14:52.46ID:tQPCeAJ90 alloca
85デフォルトの名無しさん (アウアウウー Saa1-ROXf)
2018/08/26(日) 16:21:37.62ID:hQMrm9ZNa 動的確保が無難なんだよね。最後にfreeすればいいだけだし。
最近まで知らなかったんだけどscanfで%msで動的確保してくれるの便利だな。scanf自体はなかなか難しくて使いづらいが…
最近まで知らなかったんだけどscanfで%msで動的確保してくれるの便利だな。scanf自体はなかなか難しくて使いづらいが…
8675 (ワッチョイ 5ed5-ISgX)
2018/08/26(日) 17:31:54.88ID:dLFVucRz0 >>81
あ、C99で入ったのをC11でオプショナルに格下げ(?)されたってことか。
処理系によっては厳しい実装なのかな。
やりたいことってのは文字列のエスケープを含んだ組み立てなんだけど、使用するエスケープ関数がありものでその仕様は入力文字列長に対して2倍以上の出力バッファを与えないといけないことになってる(出力サイズを指定して打ち切らせることができない)。
実際に2倍に膨らむことは稀だし、エスケープするのも文字列中の一部なので、自分の処理で最終的に出す出力結果は論理最大よりかなり小さくなる(自分の処理は指定された出力長で打ち切る)。
まず来ることが無い事態のために論理最大の配列を取っておくのもどうかと思い、いい方法があるかここで相談させてもらった。
しかし想定外のことが起きちゃった時にどうなるべきかを考えてどうするかを決めるから、もしかしたら動的配列の意義が無くなって別の方法にするかもしれない。
この処理自体は高頻度で呼ばれるから、高速で省メモリそして内部的な都合での打ち切りは極力避けた作りにしたいって感じ。
いろいろコメントありがとう
あ、C99で入ったのをC11でオプショナルに格下げ(?)されたってことか。
処理系によっては厳しい実装なのかな。
やりたいことってのは文字列のエスケープを含んだ組み立てなんだけど、使用するエスケープ関数がありものでその仕様は入力文字列長に対して2倍以上の出力バッファを与えないといけないことになってる(出力サイズを指定して打ち切らせることができない)。
実際に2倍に膨らむことは稀だし、エスケープするのも文字列中の一部なので、自分の処理で最終的に出す出力結果は論理最大よりかなり小さくなる(自分の処理は指定された出力長で打ち切る)。
まず来ることが無い事態のために論理最大の配列を取っておくのもどうかと思い、いい方法があるかここで相談させてもらった。
しかし想定外のことが起きちゃった時にどうなるべきかを考えてどうするかを決めるから、もしかしたら動的配列の意義が無くなって別の方法にするかもしれない。
この処理自体は高頻度で呼ばれるから、高速で省メモリそして内部的な都合での打ち切りは極力避けた作りにしたいって感じ。
いろいろコメントありがとう
87デフォルトの名無しさん (ワッチョイ ed68-DNis)
2018/08/26(日) 17:43:02.62ID:tQPCeAJ90 あらかじめプールしておいて使いまわす
足りない時だけ臨時で増やす
足りない時だけ臨時で増やす
88さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 18:09:50.26ID:Vxoswi+gd ReactOSというOSでフォントエンジンの改良を行っているが、
Google Chromeというブラウザでおかしくなる。
何故かEIPレジスタがゼロになって、初回例外が発生する。KDBという付属のデバッガでトレースしたが、
どこの関数で例外が発生しているかわからない。
たすけて。。。
Google Chromeというブラウザでおかしくなる。
何故かEIPレジスタがゼロになって、初回例外が発生する。KDBという付属のデバッガでトレースしたが、
どこの関数で例外が発生しているかわからない。
たすけて。。。
89さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 18:15:57.28ID:Vxoswi+gd90さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 18:22:22.54ID:Vxoswi+gd 晒しあげ
91さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 18:39:01.79ID:Vxoswi+gd スタック破壊の可能性か。。。
92デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 19:04:13.59ID:ik1BtrwR0 >>85
> 動的確保が無難なんだよね。最後にfreeすればいいだけだし。
結局の所、結論としてはそうだね。
>>86
多分素直にmallocする関数をラップして使う方がいい。
仕様の動向自体は知らんが、
> 処理系によっては厳しい実装なのかな。
技術的にはこれはない。alloca相当(ポインタ相当)にすればいいだけなので。
ただ、間接アクセスになるから速度は落ちるし、
mallocに対しての利点は『自分で』freeしなくて済むことくらいしかない。
(『自分で』ソースに書かなくてよくなるだけで、速度上のメリットはない。
reallocaが無い為、最初のバッファ(=サイズが不明)はヒープ上に動的確保するしかなく、
自分で書いてなくてもどこかでfreeされてるだけだから。なら最初からgetlineでもいいし)
ただ、そちらの実装は(おそらくバッファオーバラン対策で)一旦固定長バッファに取り込み、
その後alloca領域に対してのコピーか?
ならまあ一応freeしなくていい速度上のメリットは残るが、
一般的にはスタックサイズ管理のコストが増える方が問題とされ、その実装はないとも思うが。
結局、allocaもイマイチなんだよ。だから標準にもなりきれない。
> 動的確保が無難なんだよね。最後にfreeすればいいだけだし。
結局の所、結論としてはそうだね。
>>86
多分素直にmallocする関数をラップして使う方がいい。
仕様の動向自体は知らんが、
> 処理系によっては厳しい実装なのかな。
技術的にはこれはない。alloca相当(ポインタ相当)にすればいいだけなので。
ただ、間接アクセスになるから速度は落ちるし、
mallocに対しての利点は『自分で』freeしなくて済むことくらいしかない。
(『自分で』ソースに書かなくてよくなるだけで、速度上のメリットはない。
reallocaが無い為、最初のバッファ(=サイズが不明)はヒープ上に動的確保するしかなく、
自分で書いてなくてもどこかでfreeされてるだけだから。なら最初からgetlineでもいいし)
ただ、そちらの実装は(おそらくバッファオーバラン対策で)一旦固定長バッファに取り込み、
その後alloca領域に対してのコピーか?
ならまあ一応freeしなくていい速度上のメリットは残るが、
一般的にはスタックサイズ管理のコストが増える方が問題とされ、その実装はないとも思うが。
結局、allocaもイマイチなんだよ。だから標準にもなりきれない。
93デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 19:12:21.53ID:ik1BtrwR0 >>83
>>1,13読んで以下にどうぞ。
C言語なら俺に聞け
https://mevius.5ch.net/test/read.cgi/tech/1534430162/
>>12
>>89
それがこのスレの正しい使い方かもしれんね。
ぱっと見て分かるものでもないけどさ。
>>1,13読んで以下にどうぞ。
C言語なら俺に聞け
https://mevius.5ch.net/test/read.cgi/tech/1534430162/
>>12
>>89
それがこのスレの正しい使い方かもしれんね。
ぱっと見て分かるものでもないけどさ。
94デフォルトの名無しさん (アウアウウー Saa1-ROXf)
2018/08/26(日) 19:20:25.22ID:uLlG7vHAa allocaとか動的サイズ指定の配列はスタックだから基本的にはmallocするよりは速いよ。頑張っても同等。
繰り返して呼ぶなら差が出るかもね。
繰り返して呼ぶなら差が出るかもね。
95デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 19:53:34.99ID:ik1BtrwR0 ああ、言い直しておくよ。
allocaとmallocなら、
確保:allocaの方が速い
使用:同速(ただし初回からキャッシュが当たる分allocaの方が速い)
解放:freeの必要が無い分、allocaの方が速い
(ただし実装によっては上位でfreeしてるだけであり、同速)
管理:通常、ヒープサイズ>>>>>>スタックサイズの為、サイズ管理が必要
速度差が見えるような使い方が出来るのなら、ある意味大したもんだと思うよ。
allocaとmallocなら、
確保:allocaの方が速い
使用:同速(ただし初回からキャッシュが当たる分allocaの方が速い)
解放:freeの必要が無い分、allocaの方が速い
(ただし実装によっては上位でfreeしてるだけであり、同速)
管理:通常、ヒープサイズ>>>>>>スタックサイズの為、サイズ管理が必要
速度差が見えるような使い方が出来るのなら、ある意味大したもんだと思うよ。
96デフォルトの名無しさん (アウアウカー Sad5-nhzT)
2018/08/26(日) 20:17:14.11ID:iSNBdVUGa スタックって確かスレッド毎に肥大化してくよね?
で、肥大化してもスレッドが停止するまで縮小しない
あってる?
で、肥大化してもスレッドが停止するまで縮小しない
あってる?
97さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 35b3-5N5t)
2018/08/26(日) 20:19:54.25ID:r4V1HxTD0 関数から戻るとき(エピローグ)にスタックは縮小することがある。
98さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd0a-5N5t)
2018/08/26(日) 20:26:06.20ID:Vxoswi+gd 実際のx86 CPUでスタックポインタを表しているのが、ESPレジスタの値。スタックサイズの増減はESPの書き換えに過ぎない。
9975 (ワッチョイ 5ed5-ISgX)
2018/08/26(日) 20:30:48.56ID:dLFVucRz0 流れのついでに聞いてみたいけど、malloc はスレッドセーフでしょ。
てことは内部で排他をかけてると思うけど、となるとマルチスレッド下で malloc や free を多発させるとパフォーマンス的に良くなかったりしないかな。
言ってなくてごめんだけど、今回の処理はマルチスレッドで動くんだ。
なのでバッファはスタック上に取れると都合がいいという事情もあるし、特別な初期化手順や終了手順も用意したくないから事前に malloc して使い回すってのもやりづらい。
ちなみに動作環境は x86 linux だから、alloca は SP をズラすだけの非常に高速な実装になってるんじゃないかと想像してるから、関心は高い。
でも、最悪でもスタック上に収まるバッファという前提にするなら最初から論理最大サイズ固定のバッファで良くね?なんて話もあるから、実際にどうするかはこれから検討。
てことは内部で排他をかけてると思うけど、となるとマルチスレッド下で malloc や free を多発させるとパフォーマンス的に良くなかったりしないかな。
言ってなくてごめんだけど、今回の処理はマルチスレッドで動くんだ。
なのでバッファはスタック上に取れると都合がいいという事情もあるし、特別な初期化手順や終了手順も用意したくないから事前に malloc して使い回すってのもやりづらい。
ちなみに動作環境は x86 linux だから、alloca は SP をズラすだけの非常に高速な実装になってるんじゃないかと想像してるから、関心は高い。
でも、最悪でもスタック上に収まるバッファという前提にするなら最初から論理最大サイズ固定のバッファで良くね?なんて話もあるから、実際にどうするかはこれから検討。
100デフォルトの名無しさん (ブーイモ MM8e-0l9r)
2018/08/26(日) 20:39:55.03ID:QMrmo6TZM glibcのmallocならサブarenaから獲得してくるから性能問題にはならないらしい
101デフォルトの名無しさん (ファミワイ FF49-DNis)
2018/08/26(日) 21:03:16.49ID:KvfxyzVvF そうだよ
条件後出しω
条件後出しω
102デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 21:06:39.43ID:ik1BtrwR0 >>99
サイズの問題がないのならallocaを使うことに問題はない。
mallocより遅くなる理由もないので。
ただ、普通に組めば分かるが、
> malloc や free を多発させる
ってのがあり得ない。
仮にこれがallocaで有効に代用出来るとするなら、再帰下降パーサ等、「再帰」が必要になるが、
再帰下降パーサの場合はインミュータブルでよく、元の文書をオフセット付きで参考して終わりだ。
再びallocaすることはない。
同様に、ループでパースするのなら、ループの外でmallocして十分な領域を確保し、
そこに上書きで使うことになる。だからmalloc/freeは1回ずつで済む。
もう一度言うが、allocaはスタックだから、「再帰」しないと領域を追加出来ない。
この使い方は普通無いし、君もやって無いと思うよ。
でも、普通のmallocを全部allocaで代用しても、サイズ以外の問題は無いから、可能ならそれでもいい。
サイズの問題がないのならallocaを使うことに問題はない。
mallocより遅くなる理由もないので。
ただ、普通に組めば分かるが、
> malloc や free を多発させる
ってのがあり得ない。
仮にこれがallocaで有効に代用出来るとするなら、再帰下降パーサ等、「再帰」が必要になるが、
再帰下降パーサの場合はインミュータブルでよく、元の文書をオフセット付きで参考して終わりだ。
再びallocaすることはない。
同様に、ループでパースするのなら、ループの外でmallocして十分な領域を確保し、
そこに上書きで使うことになる。だからmalloc/freeは1回ずつで済む。
もう一度言うが、allocaはスタックだから、「再帰」しないと領域を追加出来ない。
この使い方は普通無いし、君もやって無いと思うよ。
でも、普通のmallocを全部allocaで代用しても、サイズ以外の問題は無いから、可能ならそれでもいい。
103デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 21:08:26.06ID:ik1BtrwR0 > alloca は SP をズラすだけの非常に高速な実装になってるんじゃないかと想像してるから
これはその通り。
> 最初から論理最大サイズ固定のバッファで良くね?
これもその通り。上記ループなら普通これで行く。
それがスタック上で問題になるサイズならmalloc/freeが1回ずつ必要になる。
だから君の今の実装>>75もさほど悪いわけでもない。
今風の「実装を外に漏らさない」方針なら子関数でmalloc/freeやallocaすることになる。
おそらくそれで考えているのだと思うが、元々のCの思想はそれとは違い、
char* buff = (char*)malloc( ... ); // または char buff[2048]; 等
while (....) {
parse_func(buff, .... );
}
free(buff);
として外側で確保し、それをparse_funcに渡す。
これにより、変数の寿命とスタックの動作を一致させ、freeし忘れもなくなる。
この方法だと、allocaで毎回「SP をズラすだけ」すらする必要なく、parse_func内は最速になる。
(allocaを毎回繰り返すよりも速い)
これはその通り。
> 最初から論理最大サイズ固定のバッファで良くね?
これもその通り。上記ループなら普通これで行く。
それがスタック上で問題になるサイズならmalloc/freeが1回ずつ必要になる。
だから君の今の実装>>75もさほど悪いわけでもない。
今風の「実装を外に漏らさない」方針なら子関数でmalloc/freeやallocaすることになる。
おそらくそれで考えているのだと思うが、元々のCの思想はそれとは違い、
char* buff = (char*)malloc( ... ); // または char buff[2048]; 等
while (....) {
parse_func(buff, .... );
}
free(buff);
として外側で確保し、それをparse_funcに渡す。
これにより、変数の寿命とスタックの動作を一致させ、freeし忘れもなくなる。
この方法だと、allocaで毎回「SP をズラすだけ」すらする必要なく、parse_func内は最速になる。
(allocaを毎回繰り返すよりも速い)
104デフォルトの名無しさん (アウアウウー Saa1-ROXf)
2018/08/26(日) 21:12:44.54ID:uLlG7vHAa あくまで処理系依存の話として…
マルチスレッド固有の問題はほぼない気がしますね。malloc/freeは単に別の領域確保していくだけだしスタックの場合はスレッド生成時に確保すると。
で、まあmallocの実装はそこまで悪くないと思うけどスタックが速いし、さらに静的領域の方がちょっと命令数は少なくなるでしょう。
マルチスレッド固有の問題はほぼない気がしますね。malloc/freeは単に別の領域確保していくだけだしスタックの場合はスレッド生成時に確保すると。
で、まあmallocの実装はそこまで悪くないと思うけどスタックが速いし、さらに静的領域の方がちょっと命令数は少なくなるでしょう。
10575 (ワッチョイ 5ed5-ISgX)
2018/08/26(日) 21:36:27.43ID:dLFVucRz0106デフォルトの名無しさん (ブーイモ MM8e-0l9r)
2018/08/26(日) 21:52:41.59ID:QMrmo6TZM >>96
実行環境依存だが、win/linuxならその認識で良い
allocaは便利だがスタックの肥大化を加速させるので
環境によっては注意が必要
>>105
興味があれば
https://youtu.be/0-vWT-t0UHg
実行環境依存だが、win/linuxならその認識で良い
allocaは便利だがスタックの肥大化を加速させるので
環境によっては注意が必要
>>105
興味があれば
https://youtu.be/0-vWT-t0UHg
107さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 35b3-5N5t)
2018/08/26(日) 22:03:50.42ID:r4V1HxTD0 >>97-98 間違いです。すみません。
108デフォルトの名無しさん (ワッチョイ 954f-kiUO)
2018/08/26(日) 22:07:11.30ID:ik1BtrwR0 >>105
以下読め。マルチスレッドに関する疑問点については全部書いてあるから。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/malloc.3.html
以下読め。マルチスレッドに関する疑問点については全部書いてあるから。
https://linuxjm.osdn.jp/html/LDP_man-pages/man3/malloc.3.html
109デフォルトの名無しさん (アウアウウー Saa1-ROXf)
2018/08/26(日) 22:08:38.19ID:uLlG7vHAa11075 (ワッチョイ 5ed5-UqfJ)
2018/08/26(日) 23:49:28.30ID:dLFVucRz0 >>106
すげーおもしろかった!
マルチスレッドでどうやってるかについても分かったよ。
過渡期の性能を犠牲にして使っていくうちにいい状態に収束するようにしてるのね。
しかし malloc のコードが 5000行てw
ただ、mmap すればメモリ管理のコストが小さい的な言いぶりはどうかなって気はするな、動画の中でもツッコミ入ってるっぽいけど。
結局カーネルだって何らかの形でアドレス空間の空きを検索するし、アドレス空間を割り当てる処理にしても排他はかけてるはずだから、それなりのコストはかかるし競合の問題もあるよね(ユーザーがやる処理よりも高効率だろうと思うけど)。
>>105
malloc の話を持ち出したのは、排他とかで結構遅いんじゃね?ってのが出発点なので、
排他はしてるって言うし mmap だからという説明じゃ解決って話でもないかなって感じ。
>>109
>>75 の頃の時点では K&R アロケータ程度の認識だったからマルチスレッド下ですげー遅そうな印象だったけど、さすがによく考えられているということは分かったよ。
ちなみにこれも読み始めてた。
https://www.valinux.co.jp/technologylibrary/document/linux/malloc0001/
>>106 の動画を見てだいぶ見通しがよくなった。
すげーおもしろかった!
マルチスレッドでどうやってるかについても分かったよ。
過渡期の性能を犠牲にして使っていくうちにいい状態に収束するようにしてるのね。
しかし malloc のコードが 5000行てw
ただ、mmap すればメモリ管理のコストが小さい的な言いぶりはどうかなって気はするな、動画の中でもツッコミ入ってるっぽいけど。
結局カーネルだって何らかの形でアドレス空間の空きを検索するし、アドレス空間を割り当てる処理にしても排他はかけてるはずだから、それなりのコストはかかるし競合の問題もあるよね(ユーザーがやる処理よりも高効率だろうと思うけど)。
>>105
malloc の話を持ち出したのは、排他とかで結構遅いんじゃね?ってのが出発点なので、
排他はしてるって言うし mmap だからという説明じゃ解決って話でもないかなって感じ。
>>109
>>75 の頃の時点では K&R アロケータ程度の認識だったからマルチスレッド下ですげー遅そうな印象だったけど、さすがによく考えられているということは分かったよ。
ちなみにこれも読み始めてた。
https://www.valinux.co.jp/technologylibrary/document/linux/malloc0001/
>>106 の動画を見てだいぶ見通しがよくなった。
111デフォルトの名無しさん (ワッチョイ a69f-8MCF)
2018/08/27(月) 00:24:32.33ID:+HD/yYG+0 >>63
5.1.2.2.1
5.1.2.2.1
112デフォルトの名無しさん (ワッチョイ 2564-Yh1A)
2018/08/27(月) 04:36:47.89ID:y2YT/eYl0113デフォルトの名無しさん (アウアウカー Sad5-nhzT)
2018/08/28(火) 10:01:58.54ID:AJzSIbICa >>106
サンクス
サンクス
114デフォルトの名無しさん (ワッチョイ 0564-v81z)
2018/09/01(土) 15:23:05.79ID:Z9gelboG0 POSIX準拠を念頭にC言語を書かれている方に訊きたいのですが、機能検査マクロって実際どのように使われていますか
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600
↑僕はこのくらいであればシステム互換性は担保されると思ってるんだけど
未だにPOSIX 1998にしか対応してないOSやコンパイラとかあるんですかね。
少なくとも_XOPEN_SOURCEが600以上じゃないと<math.h>においてM_PI定数が扱えないので
数式処理のプログラムをよく書く身としてはちょっと困るんですけども……。
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600
↑僕はこのくらいであればシステム互換性は担保されると思ってるんだけど
未だにPOSIX 1998にしか対応してないOSやコンパイラとかあるんですかね。
少なくとも_XOPEN_SOURCEが600以上じゃないと<math.h>においてM_PI定数が扱えないので
数式処理のプログラムをよく書く身としてはちょっと困るんですけども……。
116デフォルトの名無しさん (アウアウエー Sa93-3g/R)
2018/09/01(土) 16:42:41.27ID:PErE712pa 好きな人が古い環境を使っているという事情でもなければ、単に無視すれば良いのでは
117さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd43-3h0E)
2018/09/01(土) 16:56:39.73ID:AtDk99X7d >>114
CMakeで環境を判定して、マクロを定義するのが王道だと思う。
CMakeで環境を判定して、マクロを定義するのが王道だと思う。
118デフォルトの名無しさん (ブーイモ MM43-HPK/)
2018/09/01(土) 18:20:25.47ID:vZp6TokWM #ifdefでM_PIがないときだけ自分で定義するのが手っ取り早いと思うけど。
119デフォルトの名無しさん (ワッチョイ a54f-rkYf)
2018/09/01(土) 18:57:55.32ID:uNlfHVUP0120さまよえる蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd43-3h0E)
2018/09/04(火) 02:12:16.08ID:I66W1B5fd >>119
使い物にするのが、依頼人の要望だから、私はそれを、果たすのみ。。。
使い物にするのが、依頼人の要望だから、私はそれを、果たすのみ。。。
121デフォルトの名無しさん (ワッチョイ c964-vX2D)
2018/09/24(月) 03:37:05.87ID:1deJaFMg0 上級者ではないんだけど 経験豊富な人に訊きたいのでここに書きます
https://git.musl-libc.org/cgit/musl/tree/include/stdlib.h
↑ここなどを見るとEXIT_SUCCESSは0で固定されています(OSによる場合分けがない)。
ということは少なくもMusl LibCプロジェクトは正常返り値を0と決めてかかっているということでしょう。
WindowsやUnix系のOSでは正常返り値は0ですが、ほかの値は絶対に考えなくていいのでしょうか
みなさんはいままで正常返り値が0でない処理系(というかOS)を見たことなどありますか。
https://git.musl-libc.org/cgit/musl/tree/include/stdlib.h
↑ここなどを見るとEXIT_SUCCESSは0で固定されています(OSによる場合分けがない)。
ということは少なくもMusl LibCプロジェクトは正常返り値を0と決めてかかっているということでしょう。
WindowsやUnix系のOSでは正常返り値は0ですが、ほかの値は絶対に考えなくていいのでしょうか
みなさんはいままで正常返り値が0でない処理系(というかOS)を見たことなどありますか。
122デフォルトの名無しさん (アウアウエー Sa4a-KpFT)
2018/09/24(月) 04:02:22.36ID:bIT2p0fxa 0が成功を示すと規格で決まっております。
123デフォルトの名無しさん (ワッチョイ 4233-tHrl)
2018/09/24(月) 12:40:59.88ID:indqm+5q0 >>121
もしプロセス終了コードの具体的な数値(数値かどうか)が異なるシステムがあるなら、
正常終了を示す main() の戻り値 0 をその環境用の終了コードで成功の値にマップするのは
そのシステム向けの処理系の仕事になる。
成功・失敗の区別以外に興味がない限りCのコードを書くプログラマが気にする必要はない
と規格は想定している。
もしプロセス終了コードの具体的な数値(数値かどうか)が異なるシステムがあるなら、
正常終了を示す main() の戻り値 0 をその環境用の終了コードで成功の値にマップするのは
そのシステム向けの処理系の仕事になる。
成功・失敗の区別以外に興味がない限りCのコードを書くプログラマが気にする必要はない
と規格は想定している。
124デフォルトの名無しさん (ワッチョイ c123-wH+P)
2018/09/24(月) 13:59:06.82ID:KzNCIBHJ0125デフォルトの名無しさん (ワッチョイ c964-vX2D)
2018/09/24(月) 17:18:25.80ID:1deJaFMg0126さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 11:56:24.75ID:7zcwA4Ik0 せっかく上級者が集まっているんだし、評論でもやりましょう。
https://github.com/reactos/reactos/blob/master/win32ss/gdi/ntgdi/freetype.c
このソース、俺の担当なんだけど、ひまだったら
喧嘩上等で悪い所・直すべきところを全部指摘してくれ。頼むよ。
https://github.com/reactos/reactos/blob/master/win32ss/gdi/ntgdi/freetype.c
このソース、俺の担当なんだけど、ひまだったら
喧嘩上等で悪い所・直すべきところを全部指摘してくれ。頼むよ。
127デフォルトの名無しさん (アウウィフ FFeb-NsMu)
2018/10/14(日) 12:52:43.56ID:G4e8iFcgF やっぱwindowsは糞だな
128デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 13:31:35.13ID:p/Li638e0 >>126
書き換えた所はどこ?
書き換えた所はどこ?
129デフォルトの名無しさん (ワッチョイ 27d2-uJ+0)
2018/10/14(日) 13:57:45.50ID:m0LzoO8+0 頑張ろうと思ったんだが、暇つぶしでやるには長すぎて挫折した。すまん。
130デフォルトの名無しさん (ワッチョイ bfd5-KnhR)
2018/10/14(日) 13:58:41.27ID:b97yHnkE0 >>126
IntCharSetFromCodePage の for の中のひとつ目の if は削除して、for に入るまでに
if( uCodePage == 0 ) return DEFAULT_CHARSET;
をやる。
for に入るまでの if は 確率が高い順に並べる。
とか?
IntCharSetFromCodePage の for の中のひとつ目の if は削除して、for に入るまでに
if( uCodePage == 0 ) return DEFAULT_CHARSET;
をやる。
for に入るまでの if は 確率が高い順に並べる。
とか?
131デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 15:07:42.66ID:p/Li638e0 >>126
表面的になぞっただけで、意味は読んでいないから参考程度で。
L924-931、FW_*のenumに揃えられるのなら揃えた方がいい。あと、ベタで書くよりはループが良いかも。
L946関数他、InterLockを外部的に明示的に行っているけど、俺ならアクセス関数内に押し込む。
ただこれは以前揉めたから、他の流儀の奴もいるのかもしれない。
俺の考えとしては、enumやdefineする理由は、変更箇所を1ヶ所に留める(同期させずに済む)事だと考えているので、
外部的に明示的にInterLockをその都度行うのは、変更時に全ての場所を同期させる(同様に書き換える)必要があるという意味で悪手。
敢えてInterLockしていることを誇示したい等の他の理由がなければ、アクセス関数内に押し込む。
L2024,L2040,L2052,L2135、同じ事を4回書いてる。
おそらく全体的に低レベルまで全部触りに行く、ある意味Cに典型的なコードになっている。
嫌う人もいるとは思うが、俺ならこの4回をどうにか1つに纏めて抽象度を上げていく。
4つの*NameWを常に同時に使うものなら、普通はstructにする。
L2879とL2888で、FT_Done_GlyphとDPRINT1の順序が逆。
お互い干渉しないから問題なしなのだろうけど、可能なら順番は揃えた方がいい。
しかもL2926とL2934でも順番が逆なので、L2869-とL2923-ってコピペしてるだろこれ。
そういうのはマメにサブルーチンとして切り出すべし。でないと抽象度が上がらない。
L3567-L3581、同じ事を4回やってる。サブルーチンに切り出して xx=sub()の形で書くべし。
あと、リテラル(初期化構文)使えるのならリテラルで書いた方がすっきりすると思うが。
L5081-5112、悪いとは言わないが、どうにかならんのか?
失敗系の速度が大して必要ないなら、ReleaseAllResources()で if (NameInfo1!=0) ExFreePoolWithTagの様にして纏めるとか。
なおL5153、"WithTag"が無いバージョンを呼んでいるが大丈夫なのか?
可能であればL5162で関数切って2つの関数にした方がいいと思う。(リソース確保/失敗系と成功系を分ける)
L5889とかもそうだけど、おそらく全部のメンバを初期化してるだろ。だったら初期化構文使った方が見た目分かりやすい。
表面的になぞっただけで、意味は読んでいないから参考程度で。
L924-931、FW_*のenumに揃えられるのなら揃えた方がいい。あと、ベタで書くよりはループが良いかも。
L946関数他、InterLockを外部的に明示的に行っているけど、俺ならアクセス関数内に押し込む。
ただこれは以前揉めたから、他の流儀の奴もいるのかもしれない。
俺の考えとしては、enumやdefineする理由は、変更箇所を1ヶ所に留める(同期させずに済む)事だと考えているので、
外部的に明示的にInterLockをその都度行うのは、変更時に全ての場所を同期させる(同様に書き換える)必要があるという意味で悪手。
敢えてInterLockしていることを誇示したい等の他の理由がなければ、アクセス関数内に押し込む。
L2024,L2040,L2052,L2135、同じ事を4回書いてる。
おそらく全体的に低レベルまで全部触りに行く、ある意味Cに典型的なコードになっている。
嫌う人もいるとは思うが、俺ならこの4回をどうにか1つに纏めて抽象度を上げていく。
4つの*NameWを常に同時に使うものなら、普通はstructにする。
L2879とL2888で、FT_Done_GlyphとDPRINT1の順序が逆。
お互い干渉しないから問題なしなのだろうけど、可能なら順番は揃えた方がいい。
しかもL2926とL2934でも順番が逆なので、L2869-とL2923-ってコピペしてるだろこれ。
そういうのはマメにサブルーチンとして切り出すべし。でないと抽象度が上がらない。
L3567-L3581、同じ事を4回やってる。サブルーチンに切り出して xx=sub()の形で書くべし。
あと、リテラル(初期化構文)使えるのならリテラルで書いた方がすっきりすると思うが。
L5081-5112、悪いとは言わないが、どうにかならんのか?
失敗系の速度が大して必要ないなら、ReleaseAllResources()で if (NameInfo1!=0) ExFreePoolWithTagの様にして纏めるとか。
なおL5153、"WithTag"が無いバージョンを呼んでいるが大丈夫なのか?
可能であればL5162で関数切って2つの関数にした方がいいと思う。(リソース確保/失敗系と成功系を分ける)
L5889とかもそうだけど、おそらく全部のメンバを初期化してるだろ。だったら初期化構文使った方が見た目分かりやすい。
132デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 15:08:04.46ID:p/Li638e0 ただし、上記は「ソースを綺麗にする方法」であって、通常は速度は落ちるので注意。
酷い話、ベタで書きまくっている方が速いのも事実。
あと、既に言ったが、上記はなぞっただけであり、関数内しか見てないので注意のこと。
本当に問題なのは関数間であり、それはガチで時間をかけて読まないと分からないから、そこまではやる気無い。
ただ、この雰囲気なら、2割くらいの関数は整理(削除)出来るのではないかと思うけど。
自分でも気になっているところがあるのなら、それを先に言うべし。見るから。
酷い話、ベタで書きまくっている方が速いのも事実。
あと、既に言ったが、上記はなぞっただけであり、関数内しか見てないので注意のこと。
本当に問題なのは関数間であり、それはガチで時間をかけて読まないと分からないから、そこまではやる気無い。
ただ、この雰囲気なら、2割くらいの関数は整理(削除)出来るのではないかと思うけど。
自分でも気になっているところがあるのなら、それを先に言うべし。見るから。
133さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-iK5y)
2018/10/14(日) 15:31:36.33ID:7zcwA4Ik0 気になってることと言えば、TextOutでOPAQUEモードのときに背景を塗り潰さないといけないのだが、それを一個の長方形でいっぺんに出来ないかな。
134デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 15:35:42.20ID:p/Li638e0135デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 15:44:21.77ID:p/Li638e0 ちなみに、これって、実際にフォントをレンダリングしているんだよな?2次ベジエ等で。
なら、OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
再帰等の条件に描画情報を使っていてそれが出来ない場合、反転でAND取ってORすれば昔のPSETにはなる。
(フォントの黒部分にもAlpha値があるのなら全面的に計算するだけだから、これではなさそうだし)
なら、OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
再帰等の条件に描画情報を使っていてそれが出来ない場合、反転でAND取ってORすれば昔のPSETにはなる。
(フォントの黒部分にもAlpha値があるのなら全面的に計算するだけだから、これではなさそうだし)
136さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 15:45:29.84ID:7zcwA4Ik0 >>134
GreExtTextOutW関数のL5847...L5954です。
GreExtTextOutW関数のL5847...L5954です。
137さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 15:47:47.17ID:7zcwA4Ik0 >実際にフォントをレンダリングしているんだよな?2次ベジエ等で。
FreeTypeというフォントレンダリングライブラリでビットマップとアウトライン曲線を取得しています。
>OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
そうしてます。
FreeTypeというフォントレンダリングライブラリでビットマップとアウトライン曲線を取得しています。
>OPAQUEの場合は先に塗りつぶしておいた上に描いた方が楽だと思うけど。
そうしてます。
138さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 15:51:46.90ID:7zcwA4Ik0 >>130
それはないかな。すみません。
それはないかな。すみません。
139さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 16:02:11.24ID:7zcwA4Ik0140さまよえる蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 67b3-7Kxw)
2018/10/14(日) 16:16:37.97ID:7zcwA4Ik0 4つの*NameWの件、修正してみた。ありがとう。
https://github.com/reactos/reactos/pull/942
https://github.com/reactos/reactos/pull/942
141デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 16:28:37.53ID:p/Li638e0 >>137
> それを一個の長方形でいっぺんに出来ないかな。
L5853のfor文が気になっているのなら、多分このCountは文字数で、
英文の場合は文字種類間ごとにピッチを変えるからこうなっているのでは?(いわゆるプロポーショナルフォント)
1回の操作に纏めたければ、文字単位でビットマップを生成して重ねるのではなく、
あらかじめ全体のビットマップを作ってそこにレンダリングしていけばいいのだけど、
速度的には速くなりそうだけど、後々面倒だから文字単位にしているのではないかと。
ここを文字単位でしこしこやるのは、悪いことではないと俺は思うけど。
気になっているのは被る部分が2度レンダリングされるって事かな?
幅5pxで1px被ってたら20%高速化だから地味に大きいのも事実だけど。
書き換えたいのなら後述参照。
なお、本筋とは異なるが、L5885-5887, L5926, L5938は正常系でもDPRINTしてるが大丈夫なのか?
DPRINT自体がリリースビルドでは消される仕様なら問題ないが。
>>139
正直なところ、指摘は参考に留めて、必要ない限りあまりいじらない方が良いとは思う。
これは昔の「動いているコードを触るな」であり、今風の「積極的にリファクタしろ」ではないが、
リファクタはデグレードをガッツリ検出出来る環境があればこそであって、
例えばchromeとかはそれをガチガチにやっているから出来るのであって、
検証環境のサポート無しなら、バグだと分かったところだけ修正し、そのついでに書き換える程度の方がいいと思うよ。
それで、該当部分を書き換えたいのなら、俺なら以下の手順でやる。(自己でデグレードチェックをする)
1. 対象部分、5847-5954を関数に切り出す。
2. その関数と全く同じ出力を生成する新関数(書き換えて1回でレンダリングするもの、おそらく20%程高速)を作る。
3. 両方とも呼び出す形でデバッグビルドし、結果を常に比較する状態でしばらく動かす。
具体的には、旧関数出力と新関数出力のビットマップを全比較する。
フォントのレンダリングなんてものすごい回数行われるので、バグっているようなら大抵これで検出出来る。
高速化は結構すると思うから、書き換える意味はあるとも思うけど。やるなら頑張れ。
> それを一個の長方形でいっぺんに出来ないかな。
L5853のfor文が気になっているのなら、多分このCountは文字数で、
英文の場合は文字種類間ごとにピッチを変えるからこうなっているのでは?(いわゆるプロポーショナルフォント)
1回の操作に纏めたければ、文字単位でビットマップを生成して重ねるのではなく、
あらかじめ全体のビットマップを作ってそこにレンダリングしていけばいいのだけど、
速度的には速くなりそうだけど、後々面倒だから文字単位にしているのではないかと。
ここを文字単位でしこしこやるのは、悪いことではないと俺は思うけど。
気になっているのは被る部分が2度レンダリングされるって事かな?
幅5pxで1px被ってたら20%高速化だから地味に大きいのも事実だけど。
書き換えたいのなら後述参照。
なお、本筋とは異なるが、L5885-5887, L5926, L5938は正常系でもDPRINTしてるが大丈夫なのか?
DPRINT自体がリリースビルドでは消される仕様なら問題ないが。
>>139
正直なところ、指摘は参考に留めて、必要ない限りあまりいじらない方が良いとは思う。
これは昔の「動いているコードを触るな」であり、今風の「積極的にリファクタしろ」ではないが、
リファクタはデグレードをガッツリ検出出来る環境があればこそであって、
例えばchromeとかはそれをガチガチにやっているから出来るのであって、
検証環境のサポート無しなら、バグだと分かったところだけ修正し、そのついでに書き換える程度の方がいいと思うよ。
それで、該当部分を書き換えたいのなら、俺なら以下の手順でやる。(自己でデグレードチェックをする)
1. 対象部分、5847-5954を関数に切り出す。
2. その関数と全く同じ出力を生成する新関数(書き換えて1回でレンダリングするもの、おそらく20%程高速)を作る。
3. 両方とも呼び出す形でデバッグビルドし、結果を常に比較する状態でしばらく動かす。
具体的には、旧関数出力と新関数出力のビットマップを全比較する。
フォントのレンダリングなんてものすごい回数行われるので、バグっているようなら大抵これで検出出来る。
高速化は結構すると思うから、書き換える意味はあるとも思うけど。やるなら頑張れ。
142デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 19:15:26.67ID:p/Li638e0 >>139
はえーよ
>>140
第一段階としてはそれで良い。
(以下は改変後の行番号として)
ただ、オブジェクト指向的にはL2033-2036の中身をいちいち見せてNeededに足すのは悪手で、
可能なら AllLengthというプロパティを作りたいところ。
Cなら関数FONT_NAMES_get_all_length()とかで「中身を知らなくても全部の長さが分かる」様にして疎結合化する。
(後々fontNamesにメンバが追加されても struct FONT_NAMES の変更だけで済むようになる)
それで、L2125-L2141でご丁寧に全部Otm(の後ろ)にコピーしてるだろ。
これだと、多分、本来はOtm内に FONT_NAMES 構造体を持ち、そこに構造体のコピーで済むように書けるはず。
具体的には、
Otm->FontNames = FontNames; // --- (α)
みたいな。
はえーよ
>>140
第一段階としてはそれで良い。
(以下は改変後の行番号として)
ただ、オブジェクト指向的にはL2033-2036の中身をいちいち見せてNeededに足すのは悪手で、
可能なら AllLengthというプロパティを作りたいところ。
Cなら関数FONT_NAMES_get_all_length()とかで「中身を知らなくても全部の長さが分かる」様にして疎結合化する。
(後々fontNamesにメンバが追加されても struct FONT_NAMES の変更だけで済むようになる)
それで、L2125-L2141でご丁寧に全部Otm(の後ろ)にコピーしてるだろ。
これだと、多分、本来はOtm内に FONT_NAMES 構造体を持ち、そこに構造体のコピーで済むように書けるはず。
具体的には、
Otm->FontNames = FontNames; // --- (α)
みたいな。
143デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 19:15:52.58ID:p/Li638e0 ただこれ、データ埋め込みだから Otm->otmFamilyName等はオフセットで管理し、
不要なUNICODE_STRING構造体部分は破棄して文字列実体だけコピーするケチケチ作戦か?
なら、普通は文字列実体のコピー関数をメンバ関数として用意する。Cなら、
char* UNICODE_STRING_copy_string(UNICODE_STRING* ustr, char* Cp){ // --- (β)、一応thisを第1引数にした
wcscpy((WCHAR*) Cp, ustr.Buffer);
return Cp + ustr.Length + sizeof(WCHAR);
}
そしてL2124-2126を
Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm);
Cp = UNICODE_STRING_copy_string(FamilyNameW, Cp); // --- (γ)
として、実装をはがしていく。(疎結合化する)
これで UNICODE_STRING 内にメンバ Buffer と Length があることを知らなくてもコピー出来るようになった。
同様に、Otm内に直接FontNames(または文字列実体だけコピー済みのchar*)を持つようにして、
FontNamesと同じ型を使い回せるようにすれば、もっと記述は少なくて済むし、疎結合化していく。(α)
ただし、ここら辺がLinusが嫌う、C++が逆に結合していく部分であって、
コード上の静的コールグラフでは疎結合化するが、型を通して知識的に密結合してしまう、というところ。
具体的には、FontNamesで綺麗に書こうとすれば OUTLINETEXTMETRICW に FONT_NAMES を持たせるべきだが、
これをやると、OUTLINETEXTMETRICWを使う人は全員FONT_NAMES構造体を知っていけないといけなくなる。
今のところ FONT_NAMES 構造体はオレオレ構造体であり、これは避けるべきだ。
逆に、UNICODE_STRINGはおそらく全体で使われている構造体なので、
(β)の関数を用意したら他でも色々使い回せ、全体的に記述を減らせるはず。
だから、次の手としては(β)+(γ)で記述を減らすべきだ。
ただし、もし仮に、型 OUTLINETEXTMETRICW を使うときには常に FONT_NAMES 構造体を知っているべきだ、というのであれば、
(α)の方向に変更していった方が最終的には綺麗になる。
てゆーか、頭大文字でも変数なのかー、まあそういうルールならそれでいいが。
不要なUNICODE_STRING構造体部分は破棄して文字列実体だけコピーするケチケチ作戦か?
なら、普通は文字列実体のコピー関数をメンバ関数として用意する。Cなら、
char* UNICODE_STRING_copy_string(UNICODE_STRING* ustr, char* Cp){ // --- (β)、一応thisを第1引数にした
wcscpy((WCHAR*) Cp, ustr.Buffer);
return Cp + ustr.Length + sizeof(WCHAR);
}
そしてL2124-2126を
Otm->otmpFamilyName = (LPSTR)(Cp - (char*) Otm);
Cp = UNICODE_STRING_copy_string(FamilyNameW, Cp); // --- (γ)
として、実装をはがしていく。(疎結合化する)
これで UNICODE_STRING 内にメンバ Buffer と Length があることを知らなくてもコピー出来るようになった。
同様に、Otm内に直接FontNames(または文字列実体だけコピー済みのchar*)を持つようにして、
FontNamesと同じ型を使い回せるようにすれば、もっと記述は少なくて済むし、疎結合化していく。(α)
ただし、ここら辺がLinusが嫌う、C++が逆に結合していく部分であって、
コード上の静的コールグラフでは疎結合化するが、型を通して知識的に密結合してしまう、というところ。
具体的には、FontNamesで綺麗に書こうとすれば OUTLINETEXTMETRICW に FONT_NAMES を持たせるべきだが、
これをやると、OUTLINETEXTMETRICWを使う人は全員FONT_NAMES構造体を知っていけないといけなくなる。
今のところ FONT_NAMES 構造体はオレオレ構造体であり、これは避けるべきだ。
逆に、UNICODE_STRINGはおそらく全体で使われている構造体なので、
(β)の関数を用意したら他でも色々使い回せ、全体的に記述を減らせるはず。
だから、次の手としては(β)+(γ)で記述を減らすべきだ。
ただし、もし仮に、型 OUTLINETEXTMETRICW を使うときには常に FONT_NAMES 構造体を知っているべきだ、というのであれば、
(α)の方向に変更していった方が最終的には綺麗になる。
てゆーか、頭大文字でも変数なのかー、まあそういうルールならそれでいいが。
144デフォルトの名無しさん (ワッチョイ 674f-gma9)
2018/10/14(日) 19:38:11.68ID:p/Li638e0■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 【地震速報】青森県で震度6強 沿岸部に津波警報 ★6 [ぐれ★]
- 「日の丸にバツ印」掲げた大学生 あいまいな国旗損壊罪に「怖い」 The Mainichi [少考さん★]
- 【音楽】BARBEE BOYS・KONTAが事故で四肢麻痺を公表、新体制で活動は継続 [少考さん★]
- 【野球】野球の未来に危機感「マイナースポーツになる」 宮本慎也氏が開催…学童大会 [尺アジ★]
- 中国「捜索レーダー起動は各国の通常の手法」 火器管制用か回答せず [蚤の市★]
- 【訃報】声優・西村知道さん死去 「SLAM DUNK」安西先生役 9月に体調不良のため一時休業 [少考さん★]
- 三角形はカッコいい
- 【画像】大人気Vtuber宝鐘マリンさん、115円…
- ぺこーら、地震で同僚が次々配信を止めるなか強行し続けるので悪目立ちするwww [268244553]
- ロボット展に中国企業80社以上が出展。日本は逆転不可能かも
- 俺はヤンキーだから
- 【速報】高市早苗、起床 [779938112]
