以下のようなプログラムを書きました。
C
1#include <stdio.h> 2 3void main() 4{ 5 char test[16] = {0}; 6 printf("%p\n", test); //① 7 printf("%p\n", &test); //② 8}
私の予想では①と②は、型がそれぞれ(char*)と(char**)なので、違うものが表示されると思っていたのですが、同じ値が出力されます。
そもそもコンパイルが通るのが不思議なくらいなのですが、なぜこのようなことになるのでしょうか?
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答4件
0
言語仕様です、と言ってしまえばそれまでですが…。
配列は[]を省略すると、先頭アドレスを指します。
&配列変数名
は、変数のアドレスを指します。なのでchar型ポインタになります。
恐らく[]を省略した場合にアドレスを指すというのがあるので、&配列変数名
としたときにchar**
になると誤解するのではと思います。
ちなみにchar**
となるのは、char*p;などの場合です。
c
1char a[10]; 2// 下記全て同じ意味 3char *pa = a; 4char *pa = &a; 5char *pa = &a[0]; 6 7char *p; 8char **pp = &p;
投稿2017/04/24 00:15
総合スコア16998
0
ベストアンサー
c
1#include <stdio.h> 2#include <stdint.h> 3int main() 4{ 5 uint32_t test[16] = {0}; 6 printf("%p\n", test); // p 7 printf("%p\n", test+1); // p + 0x4 8 printf("%p\n", &test); // p 9 printf("%p\n", (&test)+1); // p + 0x40 10 //printf("%p\n", &(test+1)); // エラー 11}
test <- 先頭要素のアドレス
&(test) <- 配列全体を一つのデータとしてみたときのアドレス
投稿2017/04/24 00:13
総合スコア13521
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
静的にとられた領域なのでメモリ上同じアドレスになると思います、動的に取れば異なります。
c
1#include <stdio.h> 2#include <stdlib.h> 3 4char test[16] = "ABCDE"; 5void main(void) { 6 printf("%p\n", test); 7 printf("%p\n", &test); 8 9 char *s; 10 s = (char *)malloc(16); 11 printf("%p\n", s); 12 printf("%p\n", &s); 13 14 free(s); 15}
投稿2017/04/24 00:29
編集2017/04/24 00:43総合スコア4070
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
#コンパイルが通る理由
printfの文字列の右側の要素にたいした型チェックがないからです。
printfは一番左側で渡された文字列を解析し、右側の引数が何かを判別し動作する関数です。
渡された値で決定するのではなく、文字列内の%
から続くパラメータを見て初めて変数の存在を判別します。
この値が正しい場所を指していればint型で渡そうが例えば文字列を渡すことはできます。
C
1char *str = "test"; 2unsigned long value = (unsigned long)str; 3 4printf("%s\n", value); // unsingned longだが"test"が表示される 5printf("%p\n", str); 6printf("%p\n", value);
※上記でulong
を使っているのは、アドレスが符号無しでないと格納できないからです。
%p
でも%d
でもなんでも同じです。
printfはvoid*の解釈を文字列から推測するだけです。
%p
の値が同じものを2つ渡せば、当然同じ値になります。
#配列test[]のtestと&testを渡した結果が同じ理由
アドレスが何のアドレスなのか考えてみてください。
メモリがどこに確保されているのか、深く考えてみてください。
C
1char array[] = "test"; 2 3array // array変数のアドレス 4&array // array変数のアドレス 5 6 7char *textp = "test"; 8 9textp // test文字列のアドレス 10&textp // text変数のアドレス
array
と&array
がさす場所が同じなのは自明です。
配列型のアンパサンドが無い場合の先頭アドレスを示す動作が、ポインタとかぶっているだけです。
配列型変数は、内容の先頭アドレスと、変数のアドレスそのものが同じです。
よく考えてみれば自然な仕組みです。
一方、textポインタは配列ではありませんから、別の文字列のある場所を指しているポインタ変数です。
ポインタ変数そのものと文字列の場所が異なります。
だからtextp
と&textp
の値は変わります。
あるノートに大事なことが書いてあるとします。
配列はノートそのものです。
どこに書いてあるかという記憶がポインタです。
ノートを見れば大事なことが読める。
読み方は同じです。
ノートのアドレスはノートそのものです。
情報の位置とノートの位置は常に同じです。
どこに書いてあるかという記憶のアドレスは脳にあります。
投稿2017/04/24 02:06
編集2017/04/24 02:10総合スコア1591
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/04/24 05:09
2017/04/24 07:09
2017/04/24 08:52 編集
2017/04/24 22:34
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。