2011-07-14 14 views
2

このコードを見つけたとき、私はCで文字列を学習しようとしていました。Strange C String Output

#include <stdio.h> 
int main(){ 
     char s[] = "Hello world"; 
     printf("%s" , s); 
     printf("%s" , &s); 
     return 0; 
} 

どちらも出力としてHello Worldを与えました。私の理解によると、この出力は最初のケースではOkです。どのように2番目のもののために働いていますか?どうか明らかにしてください。

+3

あなたの前の答えを受け入れるようにしなさい – Aravindhan

+1

それをする方法......私はSOの新しいですか? – Pritpal

+0

@Pritpal:それぞれの質問で受け入れる答えの横にあるチェックマークをクリックします。 – Puppy

答えて

1

ただ、それは価値があるかもしれないもののために、2つ目のバージョン:

printf("%s" , &s); 

は未定義の動作をし、唯一の事故によって動作しますしています。明示的にアドレスを取得すると、配列のアドレスが取得されています(これは問題ありません)が、printf 'の場合に必要な "charへのポインタ"型ではなく、 "配列の12文字へのポインタ" s%sの変換です。型が一致しないため、結果は未定義の動作です。

実際には、というだけで、という専門性があります。このコードは、私が気付いているCの実装ごとに問題なく動作します。

あなたは違いが存在することを証明したい場合、あなたはかなりかかわらず簡単にそれを行うことができます。例えば:最初のケースで

char string[] = "hello world"; 

printf("without &: %p, %p\n", (void *)string, (void *)(string+1)); 
printf("with &: %p, %p\n", (void *)&string, (void *)(&string+1)); 

stringは、第2のポインタは、最初より正確に一つ大きくなる最初の行のように、char型へのポインタに減衰します。 2行目では、文字の配列へのポインタに1を追加しています。追加すると、実際に配列のサイズが追加されます。私のマシン上でこれを実行すると、私はこのような結果を得る:

without &: 0038F96C, 0038F96D 
with &: 0038F96C, 0038F978 
2

s&sので、同じアドレスとを返します。このアドレスは、 "Hello world"の "H"が格納されている場所です。

配列の名前は、最初のエレメントのアドレスは、アレイのアドレスと同一である配列&
の最初のエレメントのアドレスに減衰
、ので。アレイのアドレスをとる

6

はそれの最初の要素のアドレスを取ることと同じです。配列の名前が使用されると、最初の要素のアドレスにも減衰します。したがって、式s&sは同じ結果になります。

+0

上記は整数配列に対しても保持されますか? – Pritpal

+0

@Pritpal:Yesは整数配列にも適用され、 'data type'には関係ありません。 –

4

sは配列の最初の項目のアドレスを返し、&sは配列自体のアドレスを返します。これらは同じです。一般的に

、あなたがより明確になりたい場合は、表現&s[0]も最初の項目のアドレスを返すために使用することができます。

-1

sは&s [0]と等価ですので、s [0]を指すポインタのアドレスではなく、s [0]のアドレスを渡しているので、2番目のケースではHellow worldを出力します。

は、ポインタの配列ではない名前です。あなたが技術的な取得したい場合

0

のcharの[]配列の最初の要素を指すcharecterポインタでのchar * sに似ているが、(それがのアドレスが含まれています最初の要素が格納されます)。 最初の文字のアドレスを格納して文字列を格納することもできます。実行時に、そのアドレスから文字を1つずつ取り出し、ヌル文字( '\ 0')に達するまで文字列を作成します。上記の例では 、%sは同じ値(開始文字のアドレス)を表します。 char s [10](固定長配列)を使用すると、すべてを理解できます。