

Shift_JISには(いわゆる半角の)バックスラッシュ記号は存在せず、  
ASCIIにおいてバックスラッシュの割り当てられたコード位置に円記号が存在します。  
Shift_JISでエンコードされたソースコードに対応したC/C++コンパイラは、  
私の知る限りいずれもこの円記号をバックスラッシュと同一視して解釈しますが、  
これは規格に適合した動作でしょうか。

例えば `"¥n"` とあった場合、これは「円記号とn」として解釈されるべきであって、  
ラインフィードとして解釈するのは規格上正しくないのではないかと疑問に思いました。  
規格に合致させるのであれば、バックスラッシュが存在しないShift_JISにおいては、  
代替としてトライグラフ `??/` のシーケンスのみがバックスラッシュとして解釈されるのが  
正しいのではないのでしょうか。

それともISOやJISなどの規格で、ASCIIのバックスラッシュと同一のコード位置にある記号は  
バックスラッシュとして解釈する、というような規定でも存在するのでしょうか。  
コンパイラの実装や慣例ではなく、規格を厳密に解釈した場合の回答を頂きたいです。


CC BY-SA 3.0
2016-09-28T08:47:31.583
29213
2016-10-01T11:25:17.947
18953
question
c++ c
Shift_JISに対応したコンパイラが円記号をバックスラッシュとみなすのは規格に適合していますか


厳密なShift_JIS (JISX0208 Appendix 1)
では符号位置0x20-0x7fの範囲はJISX0201と同一であるはずで、その符号位置0x5cの文字はU+00a5ですから、U+005cと解釈してはいけないはずです。

トリックは「コンパイラの実装や慣例」の方ではなく「Shift_JISでエンコードされたソース」という呼び方の方にあります。通称「Shift_JISでエンコードされたソース」は、JISX0208
Appendix 1ではなくIANA Windows-31J (Microsoft CP932)
を意味することがほとんどです。Windows-31Jでは7ビット符号範囲はASCIIと一致することになっており、[符号位置0x5cはU+005cと解釈されます](http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP932.TXT)。(歴史的経緯から、フォントだけ円記号になってるんですが)


CC BY-SA 3.0
2016-09-28T09:39:24.387
29216
2016-09-28T09:39:24.387
5258
29213
answer


C++の規格上、物理的なソースコードファイルはまず96種類の文字(basic source character
set)のみを使用した論理的なソースに変換されることになっています。そしてこの変換は実装定義とされています。

ですので規格上はどちらでも問題ありません。


CC BY-SA 3.0
2016-09-28T09:46:18.993
29217
2016-09-28T09:46:18.993
5750
29213
answer


> Shift_JISでエンコードされたソースコードに対応したC/C++コンパイラは、  
>  私の知る限りいずれもこの円記号をバックスラッシュと同一視して解釈しますが、

ソースファイルの文字コードを指定していないのではないでしょうか？  
超有名なGCCではちゃんと(?)円記号と解釈されているようで、バックスラッシュを意図した個所でコンパイルエラーになります。

[code]

    #include <stdio.h>
    
    int main()
    {
        printf("表が怖い\n能が震える\n");
        return 0;
    }
    
[/code]

CP932：

[code]

    # gcc -Wall -finput-charset=cp932 charset.c
    
    # ./a.exe
    表が怖い
    能が震える
    
[/code]

Shift_JIS：

[code]

    # gcc -Wall -finput-charset=shift_jis charset.c
    /usr/include/sys/features.h:38:4: エラー: expected identifier or ‘(’ before numeric constant
      ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
        ^
    In file included from /usr/include/sys/config.h:5:0,
                     from /usr/include/_ansi.h:16,
                     from /usr/include/stdio.h:29,
                     from charset.c:1:
    （以降エラーメッセージが続く）
    
[/code]

エラー箇所：

[code]

    #  define __GNUC_PREREQ(maj, min) \
        ((__GNUC__ << 16) + __GNUC_MINOR__ >= ((maj) << 16) + (min))
    
[/code]

* * *

（追記）  
`printf()`の動作を確認するために`<stdio.h>`のインクルードをやめてみました。

[code]

    //#include <stdio.h>
    int printf(const char *format, ...);
    
    int main()
    {
        printf("表が怖い\n能が震える\n");
        printf("表が怖い??/n能が震える??/n");
        return 0;
    }
    
[/code]

[code]

    # gcc -Wall -finput-charset=shift_jis -trigraphs charset.c
    charset.c: 関数 ‘main’ 内:
    charset.c:7:22: 警告: トライグラフ ??/ は \ に変換されました [-Wtrigraphs]
      printf(" \   |  ??/n \   k    ??/n");
     ^
    charset.c:7:39: 警告: トライグラフ ??/ は \ に変換されました [-Wtrigraphs]
    
    # ./a.exe 
    表が怖い¥n能が震える¥n表が怖い
    能が震える
    
[/code]


CC BY-SA 3.0
2016-09-29T14:46:36.367
29251
2016-09-30T13:54:08.293
2016-09-30T13:54:08.293
7291
7291
29213
answer


[c](/questions/tagged/c "'c' のタグが付いた質問を表示") 言語規格書の日本語版 JIS X 3010:2003 および JIS
X 3010-1993 の  
5.2 環境考慮事項 5.2.1 文字集合 の [参考] に下記の文言があります。

> この規格で規定する基本文字集合の中の２つの要素＼と～は JIS X0201 では,  
>  それぞれ￥（円記号）と￣（オーバーライン）に置き換える。

(投稿者による注意書き：原文中は俗にいう半角ですが投稿の際の混乱を回避する目的で全角で記入）

というわけで ISO/IEC 9899 のレベルでは認められていなくても JIS X 3010 は認めている、  
と考えて差し支えないかと。

[c++](/questions/tagged/c%2b%2b "'c++' のタグが付いた質問を表示") 言語規格書 JIS X 3014:2003 の
2.2 文字集合 には同等の文言はなかったです。  
他の版は入手していないので、もしかしたら他の版には何かあるかもしれません。

C++03 の設計理念 [C89 の上位互換を厳守] からすると  
言語仕様書に明記がなくても、上記内容を C++ で期待しても問題ない  
とオイラ個人的にはそう思います。


CC BY-SA 3.0
2016-10-01T11:25:17.947
29282
2016-10-01T11:25:17.947
8589
29213
answer