C言語相談室(上級者専用)

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん (ワッチョイ 139f-Cjmv)2018/03/02(金) 22:48:03.65ID:2Cs+DkMh0
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

0382デフォルトの名無しさん (ワッチョイ 7f7b-bDB9)2019/05/21(火) 22:44:33.89ID:ff2E85uv0
>>381
そういうのは少しでも役に立つ可能性のある情報を書いてから言え
お前らゆとりはそこが駄目なんだよ

といっても聞かないし、聞かない理由も分かってきたので対策をするわけだ
なおさとりはゆとりとはちょっと違い、ゆとりよりはましになってる
ただ、いずれにしても「まともなネット」を見せないことには先に進まない
お前らもそれを見えば俺らがなんでゆとりに対して怒っているか分かると思うぜ

0383デフォルトの名無しさん (ワッチョイ 7f7b-bDB9)2019/05/21(火) 23:15:28.05ID:ff2E85uv0
>>373
さらについでに言うと

> LOGFONT.lfWidth、LOGFONT.lfEscapement、WorldTransformなど
> さまざまな変形があるため、本当に複雑なものになっている。
これも根本的にやり方を間違ってる。
普通はスーパーセットを整備してから、サブセットを使うんだよ。
いちいち別に整備しない。

例えば、回転と平行移動が必要なら、アフィン変換を準備して、回転または平行移動として使う。
勿論、速度面でオーバーヘッドは出るが、
究極に速いコードと構成が美しいコードはあまり両立しない。
アジャイルの場合は後者、つまりコードを優先しないと開発が破綻する。

様々な変形があると分かっているのなら、最初から全部対応出来る構成で行くんだよ。
それはコーディングする前にちゃんと考えないと駄目なんだ。
アジャイルは「一つずつやる」事ではない。
未来の仕様なんて分からないから、
「現在確定している仕様を全て満たすにはこれが最適」をひたすら繰り返してるだけだ。
Windows互換だと最初から分かってるのなら、
win32APIを全部眺めた上で最初から「最適構造」でコーディングするのが一番効率がよく、
これはまさにウォーターフォール設計そのものだ。
仕様が確定している以上、ウォーターフォールを選択しないのは間違いだが、
最終的にも糞どうでもいいAPIなんて実装する気がない、というのならアジャイルもありだ。
ただ、アジャイルならアジャイルなりの構成にしないと無理で、君のコードはそれが出来てない。

もっと上位のコーディング戦略がおかしいんだよ。
だからそれをまず直せといっている。
なおウォーターフォールの場合は「仕様変更はしない」という大前提なので
コードなんて汚かろうがコピペだらけであろうが全く問題ない。そして君のコードはこれだ。

0384蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/21(火) 23:32:13.04ID:MkUHRfEld
グリフの変形はfreetypeで行うことになってる。
変形は参照点を中心に考え、変形した後で平行移動しないといけない。
だから単なるアフィン変形では対応できない。

0385蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/21(火) 23:38:40.78ID:MkUHRfEld
ややこしいアフィン変形の合成の計算になると予想される。変換式はまだ確定していない。

0386蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/21(火) 23:40:43.72ID:MkUHRfEld

0387デフォルトの名無しさん (ワッチョイ 7f7b-bDB9)2019/05/22(水) 00:32:45.01ID:TVjFGGsu0
>>385
すまんがソースを見る気はない。
ただ、方向性を完全に間違ってて、

× ややこしい変換式を実装しきる
○ 単発の単純変換の組み合わせで対応する

なんだよ。>>378が方向性は合ってる。
ただ、ちゃんと実装すれば重ねがけにすらならず、単に、

A変換を必要なら行う
B変換を必要なら行う
C変換を必要なら行う

になって終わるはず。
合成変換を実装するのは最速チューニングであって、開発性重視のアジャイル向きコーディングではない。
この根本戦略が間違ってる。
アジャイルで行くなら、基本的にコードはシンプルに、単純に動く実装を積み重ねて、
必要なら速度チューニングする位で行かないと破綻する。

単純に言えば、まずは遅くていいからコード量が一番少ない実装を選べ、ということ。
(Cの場合は手抜き実装でも大してコード量が変わらないから分かりにくいかもしれないが)

0388デフォルトの名無しさん (ワッチョイ d069-pg4x)2019/05/22(水) 09:24:29.43ID:QBLOwo/G0
>>384
そのグリフ変形ってのは非線形写像で
元々直線のものが曲線に投影されるような写像なの?

アフィン変換は線形写像で
平行移動 拡大縮小 回転 せん断(平行四辺形) を表現できるんだけどさ

0389デフォルトの名無しさん (ワッチョイ 987c-Q2B8)2019/05/22(水) 11:05:05.28ID:1OSMRbFi0
テンソルですね判りますω

0390蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/22(水) 18:34:00.49ID:PIPD7DKBd
バイトで疲れた
少し休む

0391デフォルトの名無しさん (ワッチョイ 6e7c-VA68)2019/05/22(水) 19:07:43.18ID:x0vcQb3n0
病院行っとけ

0392蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/22(水) 19:24:14.99ID:PIPD7DKBd
グリフというのはフォントの各文字の形状のこと。

アフィン変形行列で、ある点P(px, py)を中心に角度θ回転させるってどうやって書くんだっけ?

0393デフォルトの名無しさん (ワッチョイ 3f01-pg4x)2019/05/22(水) 19:31:44.58ID:Y0ViVk0D0
平行移動-px,-py → 回転(原点中心) → 平行移動px,py
これを合成するか記述するか

0394蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/22(水) 19:32:47.72ID:PIPD7DKBd
Win32のWorldTransformはアフィン行列を使っているから、アフィン変換で表せる。
座標変換は、ワールド座標からページ座標への変換、そしてページ座標からデバイス座標への変換の二つを合成して考えないといけない。
ややこしいのは座標変換とグリフ変形を両方考えないといけないこと。

0395蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ ce01-Q2ES)2019/05/22(水) 20:06:05.20ID:U51Avb/v0
https://github.com/reactos/reactos/blob/master/win32ss/gdi/ntgdi/freetype.c#L5796
freetype.cの5796行目。
FT_Set_Transform(face, &mat, NULL);
FT_Set_TransformにFT_Matrix matをセットすることでグリフを変形できる。
FreeTypeのFT_Matrix構造体には平行移動の成分はない。

5798行目から5871行目まで。テキストの変位(幅と高さ)を計算する。
背景を塗りつぶしたり、下線を描きたい場合は、変位を計算しなければならない。
テキストはグリフの並びであるから、全体の幅を求めたい場合はグリフを一つ一つスキャンするしかない。

5910行目から5948行目まで。必要に応じてvecs構造体に座標を格納する。
5950行目から5987行目まで。座標変換を行う。この辺に間違いがあるかもしれない。

0396蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ ce01-Q2ES)2019/05/22(水) 20:16:47.33ID:U51Avb/v0
「ワールド座標からページ座標への変換」、すなわち、
WorldTransformは、dc->pdcattr->mxWorldToPageで表せるが、
(dc->pdcattr->flXform & WORLD_XFORM_CHANGED)がセットされている場合は、
事前にDC_vUpdateWorldToDevice(dc);を呼んで更新しなければならない。
この変換は、グラフィックスモードがGM_ADVANCEDの場合のみ適用される。
GM_ADVANCEDの場合、グリフもこのような変形が適用される。

「ページ座標からワールド座標への変換」は、
DC_vGetPageToDevice(pdc, &mxPageToDevice);で
MATRIX mxPageToDeviceとして取得できる。

0397蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ ce01-Q2ES)2019/05/22(水) 20:25:44.38ID:U51Avb/v0
グリフは次のような変形が適用される。
1) lfWidth変形。lfWidthが非ゼロのとき、幅を調整する。
2) lfEscapement変形。テキストの傾きをつかさどる。lfEscapementが非ゼロのとき、参照点を中心としたグリフの回転を行う。
3) lfOrientation変形。GM_ADVANCEDの場合、lfEscapement変形に加えて1文字ごとの回転を引き起こす。今回は考えない。
4) WorldTransform変形。GM_ADVANCEDの場合、適用される。

0398蟻人間 ◆T6xkBnTXz7B0 (スフッ Sd94-nCkw)2019/05/22(水) 20:43:40.14ID:PIPD7DKBd
計算苦手だからMaximaでも使おうか

0399蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ ce01-Q2ES)2019/05/22(水) 21:47:56.58ID:U51Avb/v0
Maximaで行列。
file:///C:/Users/katahiromz/Desktop/maximaintro.pdf

0400デフォルトの名無しさん (アウアウエー Sa9f-LXSb)2019/05/23(木) 02:14:48.74ID:srO5/BaDa
アリって高校行ってないのか

0401蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-6B7C)2019/05/23(木) 03:46:25.63ID:Kz6b19yN0
#include <windows.h>
#include <stdio.h>
int main(void)
{
XFORM x1 = { 0, 1, 1, 0, 5, 6 }, x2 = { 1, 2, 3, 4, 3, 4 }, x3;
HDC hDC = CreateCompatibleDC(NULL);
SetGraphicsMode(hDC, GM_ADVANCED);
SetWorldTransform(hDC, &x1);
ModifyWorldTransform(hDC, &x2, MWT_LEFTMULTIPLY);
GetWorldTransform(hDC, &x3);
// 0.000000, 1.000000, 1.000000, 0.000000, 9.000000, 9.000000
printf("%f, %f, %f, %f, %f, %f\n",
x3.eM11, x3.eM12, x3.eM21, x3.eM22, x3.eDx, x3.eDy);
return 0;
}

0402蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-6B7C)2019/05/23(木) 03:49:52.57ID:Kz6b19yN0
# Maxima (Shift+Enterで実行)
X1:matrix([0,1,0],[1,0,0],[5,6,1]);
X2:matrix([1,2,0],[3,4,0],[3,4,1]);
display(X2 . X1);

おっけー、結果が一致する。

0403蟻人間 ◆T6xkBnTXz7B0 (スフッ Sdff-uiLC)2019/05/23(木) 04:07:47.90ID:RE0bqy1Md
Win32のWorldTransformは
XFORM構造体により
matrix([eM11, eM12, 0], [eM21, eM22, 0],[eDx, eDy, 1]);
と表せるアフィン変換であることがわかった。
次はある点を中心とした回転を調べてみよう。

0404蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-6B7C)2019/05/23(木) 04:52:55.60ID:Kz6b19yN0
M1:matrix([1, 0, 0], [0, 1, 0], [-px, -py, 1]);
R1:matrix([cos(t), sin(t), 0], [-sin(t), cos(t), 0], [0, 0, 1]);
M2:matrix([1, 0, 0], [0, 1, 0], [px, py, 1]);
display(M2 . R1 . M1);

これでいいのかな?

0405蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-6B7C)2019/05/23(木) 08:19:12.97ID:Kz6b19yN0
/* Maxima */
M1: matrix([1, 0, 0], [0, 1, 0], [-px, -py, 1]);
T1: matrix([width_ratio, 0, 0], [0, 1, 0], [0, 0, 1]);
R1: matrix([cos(t), sin(t), 0], [-sin(t), cos(t), 0], [0, 0, 1]);
M2: matrix([1, 0, 0], [0, 1, 0], [px, py, 1]);
M2 . R1 . T1 . M1;

これにWorldTransform行列を掛け合わせたものがグリフ変形行列になるんジャマイカ?
次は座標変換行列を考えてみよーー。

0406蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-6B7C)2019/05/23(木) 08:59:35.30ID:Kz6b19yN0
あ、一つ忘れたことがあった。

TextAlign (TA_*)でTA_BASELINE以外が設定されているときは、グリフの位置をずらす必要があった。5908行目から5931行目までを参照。これまたややこし。

ここでは、「16.16形式固定小数点数」というのが使われていて、整数値が16ビット左シフトされているので注意。

0407蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2701-uiLC)2019/05/23(木) 09:07:22.03ID:Kz6b19yN0
TA_BASELINE以外では、テキストの位置がずれ、参照点と回転中心がずれる。

0408デフォルトの名無しさん (ワッチョイ bfca-BKZ9)2019/05/23(木) 10:47:45.80ID:Wqs4//Er0
最初から計算方法を確かめてから作ればよかったってことだな

0409蟻人間 ◆T6xkBnTXz7B0 (スフッ Sdff-uiLC)2019/05/23(木) 15:32:13.39ID:RE0bqy1Md
。。。このテディベア、しゃべるぞ? 音声認識機能が搭載?

0410デフォルトの名無しさん (ワッチョイ e77b-0Ssz)2019/05/23(木) 17:53:35.45ID:KaSwUSI90
テディベアかと思ったら毛皮で偽装したAIスピーカーだった、というお話。
独り言のつもりで喋った内容がネット経由で全世界に晒しプレイ。

そう言えばさまよえなくなったの?

0411デフォルトの名無しさん (ワッチョイ ff7c-wLN0)2019/05/23(木) 19:14:22.24ID:KLPLdAni0
おしゃべりみーちゃん

0412蟻人間 ◆T6xkBnTXz7B0 (スフッ Sdff-uiLC)2019/05/23(木) 20:12:22.06ID:RE0bqy1Md
https://github.com/reactos/reactos/pull/1573
うまくいきそう。ありがとう、テディベア。

0413デフォルトの名無しさん (ブーイモ MMcb-wr5r)2019/05/23(木) 21:08:28.55ID:fA4TGJutM
行列の基礎も知らずに上級者とか

0414蟻人間 ◆T6xkBnTXz7B0 (スフッ Sdff-uiLC)2019/05/23(木) 22:01:08.56ID:RE0bqy1Md
予定より早く終わった
河豚刺身を頂くか

0415デフォルトの名無しさん (ワッチョイ 277b-vAXu)2019/05/23(木) 22:34:27.34ID:n706agj50
>>392
マジレスすると、そんなところで引っかかってる時点で止めた方がいい。
アフィン変換=一次変換+平行移動であり、
ゆとり以前は高校数学の範囲で、国立大理系レベルなら全員知ってるか、すぐに理解出来る。


>>394
× 二つを合成して考えないといけない。
○ 二つを並べて書け。

どうしても嫌なら2つを順に呼び出す関数でラップして1つに見せかけろ。
根本的に考え方を間違ってる。


>>400
まじでこれ。
腕前以前に、仕様を理解出来ない奴がコーディングしてもろくな物にはならない。
そもそもどういう順番でどの変換をかけるべきなのか理解出来てない。
動かして試さないと分からないようなら、最終的にもバグは取りきれないと思う。
動いているように見えるとしたら、今あるテストパターンで引っかからないだけ。


蟻に必要なのは、プログラミング技術ではなくて、高校数学だ。
或いはここを読んでいるど初心者についても言えるが、
高校レベルならプログラミングではなく学校の勉強、特に数学と物理に集中した方がいい。
20代前半で起業する気なら高校生以前からプログラミングをしてないと無理だが、
起業する気なし、または起業するにしても30代以降なら、プログラミングは大学生からでも十分間に合う。

0416デフォルトの名無しさん (ワッチョイ ff7c-eVvB)2019/05/23(木) 23:32:17.48ID:PljKu8LZ0
射精してそう

0417蟻人間 ◆T6xkBnTXz7B0 (スフッ Sdff-uiLC)2019/05/24(金) 18:25:55.35ID:g/VWM3H0d
matWorld.xy = -matWorld.xy;
matWorld.yx = -matWorld.yx;
の辺りで何かおかしいと思ったら、座標系の扱いに既存のバグがあるようだ。調査に時間がかかる。

0418蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2301-1cge)2019/06/03(月) 21:16:57.42ID:ot1fFUFW0
https://jira.reactos.org/browse/CORE-16020
やり直しになりました。アルゴを再考します。

0419蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ 2301-1cge)2019/06/03(月) 21:45:21.69ID:ot1fFUFW0
そして始まるデスマーチ。。。

0420蟻人間 ◆T6xkBnTXz7B0 (ワッチョイ c301-JiLg)2019/07/04(木) 16:03:16.38ID:5KPM8ZzF0
https://github.com/reactos/reactos/pull/1708
IntExtTextOutZeroAngleW関数を直さないといけない。
バウンディングボックスがおかしい。

0421蟻人間 ◆T6xkBnTXz7B0 (スププ Sd1f-dIxF)2019/07/04(木) 20:57:20.52ID:FzZdbDF3d
ダン。テストにgo!

0422デフォルトの名無しさん (アウアウウー Sacf-Im8i)2020/07/07(火) 19:15:29.77ID:/zFzmDrza
gotoキャンペーン

0423デフォルトの名無しさん (ワッチョイ 9f7b-uKxv)2020/08/23(日) 15:49:17.24ID:Y43WfYiq0
お前らこれどう見る?(Cの話ではないが)
> 正しい共通化とは、「同じものを共通化すること」であり「同じようなものを共通化すること」ではない。
https://xtech.nikkei.com/it/atcl/column/17/031300081/041000005/?P=2

俺はこの筆者が間違いだと思うが。
俺は後者も積極的に共通化して、というよりは積極的に「共通ルーチンを使うように」コーディングし、
結果的に「殆ど同じ事をやっているルーチン」の濫造を防いで行数を減らす=コードの規模を抑えることの方が重要だと見ている。
つまり、この失敗ケースで最初に目指した物の方が近い。

「同じ物を共通化する」ではコードは減らない。「ほぼ同じだがちょっと違う」が大量発生してしまう。
だから最初から「同様のルーチンが必要」と分かっていればそれなりに緩く作って汎用性にするし、
当初それが分からない場合は当然「専用(=非汎用)ルーチン」となっているが、
仕様変更で同様の物を追加で書く際に、それと纏めて無理にでも共通化する。
結果的に俺はそれで上手く行っている。(つもり)
なお俺も以前はこの作者と同様、「まず自由(つまり局所最適化)に組んで、その後共通部分を共通化」だった。
ただそれだとコードの依存性はそれぞれ別のルーチンを使うので当然減るのだが、
結果的に「ほぼ同じだがちょっと違う」だけのルーチンがやたら出来て、その後の長期的保守性が著しく落ちる。
というか、長期的保守性って結局のところ、「もう一度読み直すのにかかる時間」でしかないから、
結局は「コードの読みやすさ」*「コードの量」であり、同じようなルーチンが山ほどあるのは悪だと気づいた。

違いはおそらく、開発フロー、つまりウォーターフォールとアジャイルの違い、また、
昔のテスト方式へのこだわり(=一文字でも変更した部分は全部テストやり直し)から来ていると思う。
共通ルーチンがなければ、追加機能で仕様変更した際、追加部分にしか変更が影響しないので当然デグレードの危険は低くなる。
ただしそれだと無駄にコードが膨らんでいくだけで、割と早い段階で破綻すると気づいた。
とはいえ上記の俺の「上手く行っている」ははっきり言ってテストはほぼやってないので、
テストについて問題があるのは事実だが。

0424デフォルトの名無しさん (アウウィフ FF63-fHWV)2020/08/23(日) 15:56:52.71ID:Exm+Pt+ZF
コボちゃんの発想だよな

>>423
誤) 汎用性にする
正) 汎用にする

0426デフォルトの名無しさん (ワッチョイ 9f7b-uKxv)2020/08/23(日) 16:56:04.30ID:Y43WfYiq0
>>424
なるほど、コボラーか。
日本IBMだからVBかと思っていた。

となると当初の「共通化」思想はJava組か?
で、コボラー老害がJavaの若者(というほど若くもないだろうが)を揶揄した記事かな?
これならありがちな状況ではある。

しかし俺が思うに「保守性」の向上なら「共通化」の方が正解で、
「同じ『ような』ものは共通化しない」方針は デグレード回避>>>保守性 の時に取るべき選択であり、
「保守性」向上を目指す際に取るのは間違いだと思う。(保守性は明確に落ちるから)

0427デフォルトの名無しさん (アウウィフ FF63-fHWV)2020/08/23(日) 17:18:21.25ID:Exm+Pt+ZF

0428デフォルトの名無しさん (ワッチョイ 9f7b-uKxv)2020/08/23(日) 18:01:07.29ID:Y43WfYiq0
>>427
コピペしてるなw

俺だったらコピペせずに、表示形式とデータ、つまりCでいうprintfレベルの関数を作って共通化、
本体からはまずはそれ(printf)を直接呼ぶ。
ただし本体から呼ぶ箇所が2箇所以上になってしまう場合は、
(=出来るだけ1箇所で済むように纏めるが、それでも2箇所以上になってしまう場合は)
一々フォーマット渡すとそのフォーマット部分をコピペすることになるのがウザイから、ラップ関数を作ってそれを呼ぶ。
この結果、動画でやってるのと上位レベルのコードは同じになるから、動画の方法でもそんなにクリティカルではない。
(後から掃除する時に難しい修正は必要ない。とはいえどうせやるなら最初から綺麗に書いとけ、だが)
まあ、入門用の動画なのだろうからいいのでは?

ただまあ、それ以前に、ゲームエンジンならスコア表示なんて当たり前にやるのだから、
もうちょっとましな方法もあるようにも思うが。Unityは全然知らんけど。
一々自前で書くのではなくて、普通にバインディグ出来ても不思議ではないが。
(そもそもC#ならproperty使えるから自前でバインディングするのも楽勝だが)

0429デフォルトの名無しさん (ワッチョイ ff7c-F02t)2020/08/24(月) 10:08:27.21ID:5+nAALyq0
現場猫:ヨシ!
監督猫:ヨシ!
検収猫:ヨシ!

0430デフォルトの名無しさん (ワッチョイ 1f2c-3Lde)2020/08/24(月) 10:29:42.31ID:seWRIuQk0
Ruby on Rails が、デザインパターンの宝庫

0431デフォルトの名無しさん (ワッチョイ 9f01-IEoI)2020/08/24(月) 12:57:21.18ID:I647ZAoC0
「同じ」とは、つまりどういうことなのか?

0432デフォルトの名無しさん (ワッチョイ d602-lsHo)2020/09/29(火) 10:27:06.11ID:FBp2gwm40
rect/margin

■ このスレッドは過去ログ倉庫に格納されています