質問編集履歴

4

環境を更新した旨追記

2023/12/18 17:30

投稿

dameo
dameo

スコア943

test CHANGED
File without changes
test CHANGED
@@ -7,7 +7,7 @@
7
7
  - MSYS2-MINGW64使用(※)
8
8
  - MSVCのRuntimeを使用する
9
9
  - libstdc++を使用する
10
- - gccを使用する(現状12.2.0)
10
+ - gccを使用する(~~現状12.2.0~~ →13.2.0)
11
11
  - MSYS2などの環境に依存せず、作成したバイナリは単品で動作する
12
12
  - Windows 10以降はmustで、可能ならそれ以前でも正しく動作させたい
13
13
  - MSYS2環境のbashで動かす場合、環境変数LC_*/LANG/LANGUAGEは未設定とする(LC_CTYPE=ja_JP.UTF-8は可)
@@ -251,4 +251,6 @@
251
251
  普段使いしてる人の正しい日本語の扱い方を知りたい
252
252
 
253
253
  ### 補足情報(FW/ツールのバージョンなど)
254
- msys/msys2-runtime 3.4.6-2
254
+ msys/msys2-runtime ~~3.4.6-2~~ → 3.4.10-2
255
+
256
+ ※デバッグ用のシンボル情報が欲しくて最新バージョンに更新してビルドしました(2023/12/18)。

3

作業中にうっかりmsys2環境の更新をしてしまったので、ランタイムバージョンを変更(質問/回答内容の再現確認は実施済み)

2023/04/02 14:48

投稿

dameo
dameo

スコア943

test CHANGED
File without changes
test CHANGED
@@ -251,6 +251,4 @@
251
251
  普段使いしてる人の正しい日本語の扱い方を知りたい
252
252
 
253
253
  ### 補足情報(FW/ツールのバージョンなど)
254
- msys/msys2-runtime 3.3.6-5
254
+ msys/msys2-runtime 3.4.6-2
255
-
256
-

2

文字数制限を気にしつつ誤解のないように説明的文言を加筆した。

2023/04/01 19:34

投稿

dameo
dameo

スコア943

test CHANGED
File without changes
test CHANGED
@@ -4,15 +4,18 @@
4
4
 
5
5
  ### 前提
6
6
 
7
- - MSYS2-MINGW64使用
7
+ - MSYS2-MINGW64使用(※)
8
8
  - MSVCのRuntimeを使用する
9
9
  - libstdc++を使用する
10
10
  - gccを使用する(現状12.2.0)
11
11
  - MSYS2などの環境に依存せず、作成したバイナリは単品で動作する
12
12
  - Windows 10以降はmustで、可能ならそれ以前でも正しく動作させたい
13
13
  - MSYS2環境のbashで動かす場合、環境変数LC_*/LANG/LANGUAGEは未設定とする(LC_CTYPE=ja_JP.UTF-8は可)
14
-
14
+ - 端末(conhost/mintty/etc...)は何でもいいし、適宜設定は変更するものとするが、原則デフォルトの状態で動作すること
15
+ - 日本語Windowsの場合、システムロケールのコードページは932でも65002でもどちらでも動作するものする
16
+ - 紐付けられた端末があり、端末への出力が実際にある場合、端末のコードページには追従してもいいし、しなくてもいいが、システムロケールのコードページと端末のコードページのいずれかで入出力できていること
17
+
15
- 参考
18
+ 参考
16
19
  https://www.msys2.org/docs/environments/
17
20
 
18
21
  ### 質問
@@ -26,7 +29,7 @@
26
29
  ※ソースコードは次節参照
27
30
 
28
31
  #### (1) std::coutに出力するケース
29
- ビルドと実行(システムロケールはコードページ932でmsys環境(mintty)で実施)
32
+ ビルドと実行(システムロケールはコードページ932でmsys2環境(mintty)で実施)
30
33
  ```bash
31
34
  $ g++ -g -Wall -static hello.cpp -o hello
32
35
  $ env | grep LANG
@@ -37,6 +40,8 @@
37
40
 
38
41
  $
39
42
  ```
43
+ msys2環境のminttyの設定はja_JPのUTF-8にしようが、defaultのままにしようが、同じです。
44
+ 一言で言えば、この状態からcmd /c "dir"したときに日本語が化けないのと同様の、CP932→UTF-8の変換が「どこかで」かかっている文字の化け方をしています。
40
45
 
41
46
  #### (2) std::wcoutに出力するケース
42
47
  ```bash
@@ -45,6 +50,7 @@
45
50
 
46
51
  $
47
52
  ```
53
+ これは端末以前に何も出力されていないことを示しています。(実際にパイプで繋いでも何も出ていません。)
48
54
 
49
55
  ### 該当のソースコード
50
56
 
@@ -93,7 +99,7 @@
93
99
  $
94
100
  ```
95
101
  iconvでシフトJISに変換出力してみたが、さらに文字化けするだけだった
96
- 変換は正しく実施されている
102
+ hexdumpの結果を見る限り変換は正しく実施されている
97
103
 
98
104
  #### (3) catを噛ませてみる
99
105
  ```bash
@@ -110,7 +116,8 @@
110
116
 
111
117
  $
112
118
  ```
113
- MSYS2のcatを噛ませると同じ内容でも正しく表示される
119
+ MSYS2のcatを噛ませると同じ内容(hexdumpの結果からUTF-8と分かる)でも「なぜか」正しく表示される
120
+ bash/minttyへの出力方法が./helloとcatで異なっていて、その区別から./helloだけCP932→UTF-8変換をかけられていると推測する。
114
121
 
115
122
  #### (4) cmdから見てみる
116
123
  ```cmd
@@ -131,7 +138,7 @@
131
138
  ```
132
139
  ※conhost.exe上のcmd.exe(minttyなどMSYS2環境ではなく、純粋なWindows環境)
133
140
 
134
- コマンドプロンプトからでも(3)の現象は同様に再現する。
141
+ コマンドプロンプトからでも(3)の現象は同様に再現する。また環境変数の影響でもなく、cmdは子プロセスに変換などの細工をしないので、helloは素直にUTF-8で出力していることが確定し、catが単体でUTF-8→CP932の変換をしているということが分かる。
135
142
 
136
143
  #### (5) 絵文字を出力させてみる
137
144
  ```bash
@@ -156,7 +163,7 @@
156
163
 
157
164
  $
158
165
  ```
159
- 絵文字を表示可能なことから、シフトJISで表示しようとしていないことが分かる。
166
+ 絵文字を表示可能なことから、シフトJISで表示しようとしていないことが分かる。さらに具体的に言えば、bashやcatがパイプからの読み込み時に変換をかけていないこと、受け取ったminttyも変換していないことが分かる。
160
167
 
161
168
  #### (6) リテラルをシフトJISとしてコンパイルさせる
162
169
  ```bash
@@ -227,17 +234,19 @@
227
234
  $
228
235
  ```
229
236
  システムロケールへの設定はできない→wcoutは使えない
230
- (https://stackoverflow.com/a/20181564)
237
+ (https://stackoverflow.com/a/20181564)
238
+ より正確にはwcoutは日本語の出力ができない。libstdc++がgnuモデル以外(今回はgeneralモデル)での変換を実装していないため。
231
239
 
232
240
  #### (9) 調べたことまとめ
233
241
  上記から、MINGW64で正しく日本語を扱うには、
234
242
  - wcoutを使わず、coutを使う
235
- - msvcrtかWindowsAPIか外部ライブラリなどを使って自分でエンコーディングを変換する
243
+ - msvcrtかWindowsAPIか外部ライブラリなどを使って自分でエンコーディングを(システムロケールのコードページか端末のコードページに)変換する
236
244
  - リテラルをマルチバイトの固定エンコーディングにする(シフトJISなど)とワイド文字経由のコードページ変換が2度必要になり、手間がかかるため、ワイド文字列のリテラルか、u8プレフィックス付きを使うべき(ただしC++20でchar型での扱いができなくなる)
237
245
  なのかと思う
238
246
 
239
247
  ただマルチバイト(cout)にすると、
240
248
  - 入出力時に変換が必要になり、わざわざマルチバイトにして出力した文字列をWin32側でまたワイド文字列に戻すなどの処理が入りそう
249
+ これはそもそもWriteConsoleWがワイド文字列を受け取れるから。
241
250
 
242
251
  普段使いしてる人の正しい日本語の扱い方を知りたい
243
252
 

1

一応minttyの設定も必要部分に記述した

2023/04/01 12:06

投稿

dameo
dameo

スコア943

test CHANGED
File without changes
test CHANGED
@@ -171,7 +171,7 @@
171
171
 
172
172
  $
173
173
  ```
174
- シフトJISとして出力されており、正しく表示されている。
174
+ シフトJISとして出力されており、正しく表示されている(minttyはロケールCの文字セットUTF-8)
175
175
 
176
176
  #### (7) 依存DLLを調べる
177
177
  ```bash