次のコードでは、動作は未定義ですか?このCスニペットの出力を理解できません
#include<stdio.h>
int main()
{
printf(7+"%c","sundaram");
}
その「aram」を印刷しています。方法を理解できません。
次のコードでは、動作は未定義ですか?このCスニペットの出力を理解できません
#include<stdio.h>
int main()
{
printf(7+"%c","sundaram");
}
その「aram」を印刷しています。方法を理解できません。
式7+"%c"
は、配列内の要素または配列の末尾を1つ指していないため、振る舞いはは未定義です。詳細はオンラインのC言語標準n1256,§ 6.5.6 ¶ 8を参照してください。偶然
あなたの文字列がそのように(架空の開始アドレスを使用して)のようにメモリにレイアウトされています
Address 0x00 0x01 0x02 0x03
------- ----------------------
0x00008000 '%' 'c' 0 's'
0x00008004 'u' 'n' 'd' 'a'
0x00008008 'r' 'a' 'm' 0
「%cが」0x00008000から始まり、「sundaramは」0x000080003から始まります。もし
printf(7+"%c", "sundaram");
を呼び出すとき
配列式「%cが」char *
にタイプchar [3]
から変換され、その値は、配列、または0x00008000の最初の要素のアドレスです。したがって、式7+"%c"
は、7 + 0x00008000または0x00008007と評価されます。 0x00008007で始まる文字列は "aram"です。
"アラムが" NO変換指定子を含まないので、(0x00008003と評価 "sundaram")は、第2の引数は、評価が、それ以外(§ 7.19.6.1、¶ 2)は無視されます。
動作が定義されていないため、のいずれかの結果が得られます。この特定の結果は、異なるコンパイラで、または異なるコンパイラ設定で発生することが保証されていません。
これは未定義の動作です。
Cの文字列リテラルは、事前初期化されたメモリのブロックへのポインタです。
偶然にも、2つの文字列リテラルが隣接するメモリブロックを占有します。
7
を最初のリテラルへのポインタに追加すると、次のリテラルの途中を指します。
あなたのプログラムのデータは、このようにメモリ上に配置されている:
%c\0sundaram\0 | | "%c" --^ | 7 + "%c" ------^
したがって、あなたは同じ文字列("adam", "sundadam")
なし書式指定子に二つのポインタでprintf
を呼び出してしまいます。
動作は未定義です。 "%c \ 0sundaram \ 0"のようにメモリ内にデータが配置され、 "sundaram"文字列の一部をフォーマット文字列引数として取得するだけです(フォーマット文字列のフォーマット指定子がない場合printf引数は無視されます)。
ありがとうございました。しかし、 "%c"を書式指定子として考慮しないのはなぜですか? "%c"を表示する必要がある場合、7を0に置き換えると警告が出力され、出力には何も表示されません。 – Daud
'%c' '%c'が表示されます。 –
@Duad: '"%c "'ではなく '' adam ''へのポインタを渡しています。 – SLaks