Cコードと同じ:</p>
#include<stdio.h>
int main(void) {
char c = '\97';
printf("%d",c);
return 0;
}
結果は ですが55
、計算方法がわかりません。「\」の後に 8 進数または 16 進数が続くことはわかっていますが、これ97
は 16 進数ですか?
\
は 8 進エスケープ シーケンスですが9
、有効な 8 進数字ではないため、8 進として解釈する代わりに、複数文字の定数 a\9
および1
実装定義の値である a として解釈されます。警告フラグがない場合gcc
、デフォルトで次の警告が表示されます。
warning: unknown escape sequence: '\9' [enabled by default]
warning: multi-character character constant [-Wmultichar]
warning: overflow in implicit constant conversion [-Woverflow]
C99ドラフト標準のセクション6.4.4.4
文字定数の段落10には、次のように記載されています(強調鉱山):
整数文字定数の型は int です。1 バイト実行文字にマップされる単一の文字を含む整数文字定数の値は、整数として解釈されるマップされた文字の表現の数値です。 複数の文字 (「ab」など) を含む整数文字定数の値、またはシングルバイト実行文字にマップされない文字またはエスケープ シーケンスを含む整数文字定数の値は、実装定義です。
たとえば、実装はここgcc
に文書化されており、次のとおりです。
コンパイラは、複数文字の文字定数を一度に 1 文字ずつ評価し、前の値をターゲット文字あたりのビット数だけ左にシフトしてから、ターゲットの幅に切り捨てられた新しい文字のビットパターンで or-ing します。キャラクター。最終的なビットパターンには int 型が与えられるため、単一の文字が署名されているかどうかに関係なく、署名されています (バージョン 3.1 以前の GCC からのわずかな変更)。ターゲット int に収まるよりも多くの文字が定数にある場合、コンパイラは警告を発行し、余分な先行文字は無視されます。
たとえば、8 ビット文字のターゲットの 'ab' は、'(int) ((unsigned char) 'a' * 256 + (unsigned char) 'b')' として解釈され、'\234a' は次のように解釈されます。 '(int) ((unsigned char) '\234' * 256 + (unsigned char) 'a')'.
私が知る限り、これは次のように解釈されています。
char c = ((unsigned char)'\71')*256 + '7' ;
toの変換は明らかではありませんが、これは上記の複数文字定数の実装55
と一致しています。\9
\71
編集
後で、実際に起こっているの\
は がドロップされていることであることに気付きました\9 -> 9
。
c = ((unsigned char)'9')*256 + '7' ;
これはより合理的に見えますが、それでも恣意的であり、なぜこれが単純なエラーではないのか明確ではありません。
アップデート
The Annotated C++ Reference Manualを読むと、 Classic Cおよび以前のバージョンの C++ では、文字に続くバックスラッシュがスケープ シーケンスとして定義されていない場合、文字の数値と等しいことがわかります。アーム部2.5.2
:
これは、Classic C および C++ の初期のバージョンによる解釈とは異なります。この解釈では、ソース文字セット内の文字が続くブラックスラッシュのシーケンスの値は、エスケープ シーケンスとして定義されていない場合、その文字の数値と等しくなります。 . たとえば、'\q' は 'q' と等しくなります。
\9 は有効なエスケープではないため、コンパイラはこれを無視し、ASCII '7' は 55 になります。
私はこの動作に依存しません。おそらく未定義です。しかし、それが55の由来です。
編集:Shafikは、未定義ではなく、実装定義であると指摘しています。参照については、彼の回答を参照してください。
まず第一に、あなたのタイトルと一致するので、あなたのコードはこれを読むべきだと思います。
#include<stdio.h>
int main(void) {
char c = '\97';
printf("%d",c);
return 0;
}
\9
は有効ではないので、文字が実際には 7 であると仮定しましょう7
。
あなたが何を望んでいたかはわかりませんが、\97
そうではありません...
\9
は有効なエスケープ シーケンスではないため、通常の文字に戻る可能性があり9
ます。
'97'
これは、未定義の実装定義 (Shafik Yaghmour の回答を参照) の動作 (2 文字は 1 文字に収まらない ...)と同じことを意味します。
今後このようなことを避けるには、コンパイラの警告を増やすことを検討してください。たとえば、 の最小値gcc
は です-Wall -Wextra -pedantic
。