• ベストアンサー

配列変数のアドレス

C言語で、配列を宣言した場合、 char a[] = "hoge"; 変数aは初期化された配列の先頭番地を指しているのですが、この時、 変数aの中身も変数aのアドレス(&a)ともに上記の配列の先頭番地になっているようなのですが、 これによって、配列の変数aは読み取り専用で、書き換えられないということにしていると思っていいのでしょうか? ちなみに、 char *p = "fuga"; とした場合は、pと&pのアドレスは異なって、pの中身は書き換えられます。

質問者が選んだベストアンサー

  • ベストアンサー
  • wormhole
  • ベストアンサー率28% (1621/5656)
回答No.4

>コンパイラがそれを変数aが読み取り専用であることを判断するのに使っているのではないか? コンパイラはそんな事では判断していません。 コンパイラはaが配列として書かれているので書き換えできないようにしてるだけです。 >ちなみに、 >char *p = "fuga"; >とした場合は、pと&pのアドレスは異なって、pの中身は書き換えられます。 pはポインタ変数であって配列じゃないからです。

tmiyoshi
質問者

お礼

私が間違っていたのは、配列名を変数と同じように考えていたことです。 変数だとすると、中身が自分自身を指していて、その内容はa[0]とダブるので矛盾してますよね。

その他の回答 (3)

  • hashioogi
  • ベストアンサー率25% (102/404)
回答No.3

配列とポインタは本質的には違うということを理解すればいいのではないでしょうか。

回答No.2

No.1でWr5さんが書かれている様に、aは書き換え可能です ただaは配列ですので、宣言後 a="HOGE" 等といった配列を一度気置き換える代入は出来ません これは数字など他の配列を使う時と同様です a[0] = 'H'; a[1] = 'O'; a[2] = 'G'; a[3] = 'E'; 等で書き換え可能と確認出来ます

tmiyoshi
質問者

補足

aとa[0]、a[1]などは別物です。 a[0]は配列aの中身であり、書き換え可能ですが、変数(配列名)aは配列の先頭番地(&a[0])を指していて、それは書き換えられません。 私が知りたいのは、前にも書いたように調べてみると、aと&aのアドレスが同じになっているよう なので、コンパイラがそれを変数aが読み取り専用であることを判断するのに使っているのではないか? ということです。態々あ同じアドレスにしている意味を知りたいのです。

  • Wr5
  • ベストアンサー率53% (2177/4070)
回答No.1

char a[] = "hoge"; と char a[5] = {'h','o','g','e','\0'}; は等価だった筈です。 そんなワケで… >配列の変数aは読み取り専用で、書き換えられないということにしていると思っていいのでしょうか? 書き換え可能です。 単純に初期値が与えられているだけです。 # 初期値の元になる値がメモリ上のどこかにあるかも知れませんが…。 配列の先頭アドレスを別のアドレスに変更する。ということはできませんので念のため。 >ちなみに、 >char *p = "fuga"; >とした場合は、pと&pのアドレスは異なって、pの中身は書き換えられます。 &pはp自身のアドレスで、pの指している箇所はどこか別の(一般的に書き換え禁止の)"fuga"が指しているアドレス…でしょう。 で、「ポインタが指している場所」は変更可能でしょうが、今回の場合で「ポインタが指している先」は(一般的に)書き換え不可になっているかと。 というか、何が問題となっている(何をやりたい)のでしょう?

tmiyoshi
質問者

補足

言葉の使い方の問題かもしれませんが、 aには代入(別のアドレス)はできません。読み取り専用です。 aの指している先の内容は、文字列操作関数で書き換えられます。 聞きたいのは、コンパイラがどうやってaが読み取り専用であることを判断しているかということです。 aの中身のアドレスと&aのアドレスが等しいことで読み取り専用と判断しているのか? ということです。

関連するQ&A

  • c言語の配列の先頭アドレスが偶数アドレスとなる理由について

    c言語の配列の先頭アドレスが偶数アドレスとなる理由について 下記のように実行結果をで見ると、配列Sの先頭アドレスと配列Cの先頭アドレス共に偶数アドレスなる理由を教えて頂きたい。 /*list0105*/ #include <stdio.h> main() { char na=1; char nb=1; char c[2] ={1,2}; char s[3] = {1,2,3}; char nc=1; char nd=1; printf("%p\n",&na); printf("%p\n",&nb); printf("%p %p \n", &c[0],&c[1] ); printf("%p %p %p \n", &s[0],&s[1] ,&s[2] ); printf("%p\n",&nc); printf("%p\n",&nd); } 実行結果 0xbffff8cf 0xbffff8ce 0xbffff8cc 0xbffff8cd ← c配列 0xbffff8b0 0xbffff8b1 0xbffff8b2 ← S配列 0xbffff8af 0xbffff8ae

  • 配列を作った場合は、その結果は何に反映されるのですか?

    Linux上でC言語のプログラムを作るとして。。。 例えば unsigned char hoge[10]; という変数を宣言した場合と unsigned char hoge[]20]; という変数を宣言した場合とでは 生成モジュールのバイトすうは10バイトちがうのでしょうか? 配列を宣言した場合には、コンパイル時に領域確保されるとどこかのHPで見た記憶があるのですが、それが正しければ上に書いたように生成モジュールのバイト数が10バイト変るのかな・・・ また、その生成モジュールを実行した場合の使用メモリ量は(top,vmstat等で監視した場合)は、そういう差ってでてくるのでしょうか? 宜しくお願いいたします。

  • ポインタ変数を変数に渡す方法

    (int * 型)ポインタ変数に代入されたアドレスを、(普通の)int 型変数に代入したいのですが、どのようにするのが正しいのでしょうか。 想定しているケースは、与えられたメモリ番地に対して、アドレスオフセットを加えるなどの操作を施して「補正アドレス」を生成し、メモリアクセスを行う、というような特殊な操作を実現するような場合です。 ※ メモリ番地がポインタ宣言で与えられる、という制約があります。 以下サンプルプログラムを書きました。組み込み系のプログラムを記述していますが、これで正しいでしょうか。 unsigned int *p, *p1; // ポインタ変数宣言 unsigned int value; p= (unsigned int *)0x00001F00; // メモリの0x1F00番地 value = p; // <-- ここが心配 value |= 0xCC << 16; // 与えられたアドレスから value &= 0x4 << 12; // 「補正アドレス」生成 p1 = (unsigned int *)value; *p1 = 0xA5A5_A5A5; // 「補正アドレス」にA5A5... をライト C言語初心者で、いろいろなサイトを見てみたのですが、説明されているページが見つからず質問させていただきました。どうぞよろしくお願いします。

  • 連想配列の配列の使い方

    C言語でいうところの構造体の配列(要素は"hoge"と"fuga"のみ)を perlで表現する場合、連想配列の配列にするのが一般的でしょうか? 以下の様なソースコードなのですが、perlらしさが失われている気がします。 perlらしく書くとしたらどう書くのが良いでしょうか? [ソース] @list; #この配列の要素に連想配列を入れる sub input{ #list.txtの中にはhogeとfugaの値がカンマ区切りで記入されている open(IN, "list.txt");  $i = 0; while ($xx = <IN>) { ($list[$i]{"hoge"}, $list[$i]{"fuga"}) = split /,/, $xx; $i++; } close(IN); } sub output{ for($i = 0; $i <= $#list; $i++){ print $list[$i]{"hoge"}, $list[$i]{"fuga"}; } }

    • ベストアンサー
    • Perl
  • 先頭アドレスとは何ですか?

    Cの勉強をするため、Cの勉強用のホームページを読んでいたのですが その中に 「“int a[10];”というふうに配列を宣言した場合、配列名“a”はその配列の先頭アドレスになります」 という一文がありました。これが理解できません。 「アドレス」はメモリ内の、変数が記憶されている場所のことですよね。 先頭アドレスの「先頭」とは一体何に対して「先頭」なのでしょうか。 「一番前」という意味でしょうか。なら何の中で一番前なのでしょう? さらにそのホームページでは 「配列名“a”を式の中に書くと、普通は配列の先頭要素を指すポインタになります」 と言いなおしていましたが、これもよくわかりません。 「先頭要素」とは? 一体何に対する先頭なのでしょう?要素の先頭とは何を指すのかがいまいちピンときません。 初心者にありがちなお恥ずかしい質問ではありますが、ご教授いただければ幸いです。

  • C言語で、他の関数で配列を書き換えられないようにしたい

    下のCのプログラムでは、func関数は配列aの先頭要素へのポインタを返します。 main関数の側では配列aの中身を表示します。 しかし、main関数のfor文の中の★の部分をコメントアウトせずに入れると、この配列の中身が書き換わってしまいます。  私はfunc関数以外では、この配列の中身をいじられたくないのです。  なんとかfunc関数を工夫して作成して、func関数以外では、配列の中身が変わらないようにしたいのですが、どうすればよいでしょうか。    とは言ったものの、多分できないだろうなあ、という気がします。  できないならばできないでも仕方ないのですが、確信が持てないのです。 条件があります。 funcでは表示は行なわない。 配列aの中身を表示できるように、funcから呼び出し元へ、aのアドレスまたはaの先頭要素のアドレスがわかるような情報を返す。 #include <stdio.h> char *func(int i) { static char a[]="AAAA"; a[i]='z'; return a; } int main(void) { int i; for(i=0; i<4; i++) { char *p=func(i); /* p[i]='X'; ★配列の中身を書き換えてしまう。 */ puts(p); } return 0; }

  • 配列や連想配列について

    言語一般の配列や連想配列について 最近どういう解釈をしていいのか わからなくなってしまいました。 仮にPerlで話をさせてもらいますと、 連想配列%FORMがあるとき、 個々の要素にアクセスする場合 例えば$FORM{'name'}などと記述しますが、 この$FORM{'name'}を みなさんはどのように解釈しているでしょうか? $FORM{' '}にキー nameを 代入しているようなイメージで、 「連想配列%FORMからキー'name'の値を取得する」 という考え方でしょうか? わたしは最近、 $FORM{'name'}はそれ自体が一つの変数という 考え方が出来るのではないかという気がしているのですが、 連想配列の実装から考えると この考え方は正しいのでしょうか? 以前、配列について同様の質問を したことがあります。 例えばC言語でint a[100]と宣言した場合は、 連続的なアドレスに確保されるため、 a[2]はaという名前のアドレスから a + 2 番目の場所という意味になるが、 言語によっては不連続なアドレスに 確保されるため、a[2]は一つの変数名として 考える必要がある・・ との回答でした。 ならば連想配列の場合も もし不連続なアドレスに確保されるならば、 $FORM{'name'} は一つの変数名と 考えたほうが正しいのではないかと 思ったからです。 連想配列の内部的な処理がどうなっているのか 教えて頂きたいです。 よろしくお願いします。

    • ベストアンサー
    • Perl
  • ポインタの配列について

    はじめまして。 基本的な質問で恐縮ですが、質問があります。 例えば、char *name[] = {"Alice","Ben","Chris","Diana","Elmo"} のようなポインタの配列を宣言・初期化したとき、配列nameの各要素の 中身には、初期化子として与えた、文字列の先頭アドレスが 格納されているという解釈でよろしいのでしょうか?つまり、 *(name+1)やname[1]は、「文字列Benの先頭アドレスを指す」という意 味でよろしいのでしょうか?また、このとき、(name+1)というように *をつけないときは、「文字列Benの先頭アドレスを格納したメモリの 先頭アドレス」というような解釈でよろしいのでしょうか? どうかご教授お願いします。

  • method宣言に変数等を使って可変に宣言できるか

    method宣言時にmethod名に変数を利用して宣言する事はできるのでしょうか? ↓こんなような感じで $fuga = "test"; public function {$fuga}hoge() {  .... }

    • 締切済み
    • PHP
  • verilogで配列の任意の8bitを取り出す方法

    配列の中の任意の8bitを取り出すのに、  hoge[fuga:fuga + 8] と書きましたが、エラーになってしまいました。 配列の添え字には、変数は記述できないのでしょうか? とすると、他にどの様な書き方があるのでしょうか? 教えてください。よろしくお願いします。 (verilog初心者です)

専門家に質問してみよう