配列のアドレスに対する加算について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
へっくす

配列のアドレスに対する加算について

#1

投稿記事 by へっくす » 11年前

夜分に失礼します.
C言語の勉強をしているものです.
アドレスの勉強中にふと疑問に思ったことがあったので,
テスト用にプログラムを作成しました.
以下のプログラムを実行した結果になります.

char:h,hex(68),address:6f16db23,
char:o,hex(6f),address:6f16db24,
char:g,hex(67),address:6f16db25,
char:e,hex(65),address:6f16db26,
char:,hex(0),address:6f16db27,
val: 123,address:6f16db18,
val: 456,address:6f16db1c,
size:8
size:1
size:8
size:4

配列の先頭アドレスに1を加算した結果がchar配列とint配列で違いがでました.
char1つ1バイト,int1つ4バイトなのでこのような結果になるとは思うのですが,
それぞれアドレスに1ずつ加算しているにも関わらず,なぜ違いがでるのでしょうか?
6f16db18に1を加算したら6f16db19になるのではないかと思います.

コード:

#include<stdio.h>

int main(void) {

  char hoge[5] = "hoge";
  int baz[2] = {123,456};
  int i;

  for(i = 0; i < 5; i++) {
    printf("char:%1c,hex(%x),address:%x,\n", *(hoge + i), *(hoge + i), hoge + i);
  }

  for(i = 0; i < 2; i++) {
    printf("val:%4d,address:%x,\n", *(baz + i), baz + i);
  }

  printf("size:%d\n", sizeof(char*));
  printf("size:%d\n", sizeof(char));

  printf("size:%d\n", sizeof(int*));
  printf("size:%d\n", sizeof(int));

  return 0;
}

アバター
へにっくす
記事: 634
登録日時: 12年前
住所: 東京都

Re: 配列のアドレスに対する加算について

#2

投稿記事 by へにっくす » 11年前

へっくす さんが書きました:char1つ1バイト,int1つ4バイトなのでこのような結果になるとは思うのですが,
・・・答えでてるじゃん 笑

配列の場合、連続した領域だから、
charの配列だったらcharのサイズ×配列の数、
intの配列だったらintのサイズ×配列の数ぶん
メモリを確保してることになります
だから一つ増やすたびにアドレスはそのサイズ分増えるのです。
このことは
*(p + i)

p
と置き換えることが可能なことからも分かるのでは?
written by へにっくす

へっくす

Re: 配列のアドレスに対する加算について

#3

投稿記事 by へっくす » 11年前

*(p + i)とpは一緒ですね笑
何がなんでも1バイトずつ進めるとしたら*(p | 1)とすると良いのでしょうか?
コンパイルしてないので,なにも言えませんが
へにっくす さんが書きました:
へっくす さんが書きました:char1つ1バイト,int1つ4バイトなのでこのような結果になるとは思うのですが,

・・・答えでてるじゃん 笑

配列の場合、連続した領域だから、
charの配列だったらcharのサイズ×配列の数、
intの配列だったらintのサイズ×配列の数ぶん
メモリを確保してることになります
だから一つ増やすたびにアドレスはそのサイズ分増えるのです。
このことは
*(p + i)

p
と置き換えることが可能なことからも分かるのでは?

nil
記事: 428
登録日時: 12年前

Re: 配列のアドレスに対する加算について

#4

投稿記事 by nil » 11年前

pをcharポインタへキャストすればいいかと

コード:

*((char*)p+i)

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列のアドレスに対する加算について

#5

投稿記事 by みけCAT » 11年前

へっくす さんが書きました:何がなんでも1バイトずつ進めるとしたら*(p | 1)とすると良いのでしょうか?
pの値が奇数だとうまくいかないと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

へっくす

Re: 配列のアドレスに対する加算について

#6

投稿記事 by へっくす » 11年前

お返事ありがとうございます.
涼雅 さんが書きました:pをcharポインタへキャストすればいいかと

コード:

*((char*)p+i)
charのポインタとしてキャストすることで1byteずつ増やすコードという理解でよろしいでしょうか?

そこで,下記のようなプログラムを作って確認してみました.
intのポインタとしてcharのポインタをキャストしました.
なので,期待する出力としては

コード:

6154ab10,a
6154ab14,e // <-aの4byte先の値
という結果を期待しました.
#アドレスは適当
ですが,実際には

コード:

6154ab10,a
6154ab20,   // <-期待するアドレスと違う!
このような結果になりました.
intのポインタとしてキャストしているにも関わらず,
なぜこのような結果になるのでしょうか?

コード:

#include<stdio.h>

int main(void) {

  int baz[2] = {123,456};
  char hoge[] = "abcdefg";
  int i;

  // increment
  for(i = 0; i < 7; i++) {
    printf("%x,%c\n", hoge + i, *(hoge + i));
  }

  printf("----------------------------------------\n");

  for(i = 0; i < 7; i += 4) {
    printf("%x,%c\n", (int*)hoge + i, *((int*)hoge + i));
  }

  return 0;
}

へっくす

Re: 配列のアドレスに対する加算について

#7

投稿記事 by へっくす » 11年前

みけCAT さんが書きました:
へっくす さんが書きました:何がなんでも1バイトずつ進めるとしたら*(p | 1)とすると良いのでしょうか?
pの値が奇数だとうまくいかないと思います。
勉強不足で申し訳ありません.
どうして奇数だとうまくいかないのでしょうか?

へっくす

Re: 配列のアドレスに対する加算について

#8

投稿記事 by へっくす » 11年前

No.6の投稿間違ってますね・・・・

コード:

  for(i = 0; i < 7; i += 1) {
    printf("%x,%c\n", (int*)hoge + i, *((int*)hoge + i));
  }
こうでした.
お騒がせして申し訳ありません.

nil
記事: 428
登録日時: 12年前

Re: 配列のアドレスに対する加算について

#9

投稿記事 by nil » 11年前

訂正された時の出力はどうなっていますか?

へっくす

Re: 配列のアドレスに対する加算について

#10

投稿記事 by へっくす » 11年前

このようになりました.

コード:

64c8ab10,a
64c8ab14,e
64c8ab18,{
64c8ab1c,##
           64c8ab20,
64c8ab24,
64c8ab28,A
余計な部分が出てますが,intのポインタとしてキャストすることで
1を足す=アドレスから4バイト先のアドレスを指す
ということを確認できました.
涼雅 さんが書きました:訂正された時の出力はどうなっていますか?

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 配列のアドレスに対する加算について

#11

投稿記事 by みけCAT » 11年前

へっくす さんが書きました:
みけCAT さんが書きました:
へっくす さんが書きました:何がなんでも1バイトずつ進めるとしたら*(p | 1)とすると良いのでしょうか?
pの値が奇数だとうまくいかないと思います。
勉強不足で申し訳ありません.
どうして奇数だとうまくいかないのでしょうか?
|はビットOR演算子であり、 (p | 1)はpの一番下のビットを1にした数になります。
pが奇数の場合、一番下のビットは最初から1なので、p == p | 1となります。

コード:

#include <stdio.h>
 
int main(void) {
        int a=12345;
        printf("%08x\n",a);
        printf("%08x\n",a | 1);
        a=12346;
        printf("%08x\n",a);
        printf("%08x\n",a | 1);
        return 0;
}
http://ideone.com/rHI8R

ちなみに、(gccでは)ポインタに対し|演算子は使えませんでした。

コード:

#include <stdio.h>
 
int main(void) {
        int a=1;
        int* p=&a;
        printf("%p\n",p);
        printf("%p\n",p | 1);
        return 0;
}
http://ideone.com/fT6ZJ
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

へっくす

Re: 配列のアドレスに対する加算について

#12

投稿記事 by へっくす » 11年前

お返事ありがとうございます.
確かに奇数だとうまくいきませんね・・・

閉鎖

“C言語何でも質問掲示板” へ戻る