なたで日記

いろいろな思ったこと書きますヽ(^▽^ゞ) by natade

C言語のアドレス演算子の不思議

leave a comment »

前々から、C言語のポインタで不思議だったこと。

最適化C 言語 より
http://www.imit.chiba-u.ac.jp/new-system/sr/man_hitachi_c/MAN/3000/03C3100D/C310057.HTM
>単項&演算子をアドレス演算子といい,&の後に続くオペランドのポインタ(アドレス)を表します。
>(3) 記述例
>int a , *p ;
>p = &a ;
>    解説
>        &aはaのアドレスを表し,ポインタpにaのアドレスを代入する式です。

こういうのを見て、アドレス演算子をつければ、
その変数のアドレスが分かるって理解しちゃうと不思議なことが起きます。

例えば、

#include
main() {
    int target;
    int x = &target + 1;
    int y = ⌖y += 1;
    printf("x = %d\ny = %d\n",x,y);
}

のようなコード。xとyが同じ値になりません。

友人に色々教えてもらい分かったことなのですが、
数値とアドレスは違うもの。&をつけるとポインタ型になる。」ということ。
考えれば、普通は変数にアドレス演算子をつけたものは、ポインタ型にエラーなく代入してますよね。
つまり、アドレスの型は、ポインタ型なのです。

なお、ポインタ型同士の加算は出来ないです。

&target + &targetエラー

実際の計算的には
int x = &target + n; → int x = (int)&target + sizeof(target) * n;
X型のポインタ型に、数値を加算する場合に、自動でsizeof(X)を数値に掛け算してくれます。
数値ではなく、ポインタ型の場合はエラー。

HSPをやっていると、varptr函数でアドレスが分かるのですが、

アドレス演算子は、それと同じようなものだと思っていたわけですが、こんな違いがあったのですね。
あとあと、教科書やサイトとかで、ポインタ型を%pではなく整数型を表示させる%dで表示するもんだから、
なんか、「アドレスと整数は同じなんだ。アドレスって数値だし納得!」みたいな錯覚するというか。

後で調べたのですが、ポインタに関して、
苦しんで覚えるC言語アドレスを記憶する変数 がつっこんだところまで解説していて分かりやすいです。

まあそれはおいておいて、友人が書いたサンプル。

main() {
    int x = 1,y[] = {0,100};
    printf("%d\n",x[y]);
}

という書き方のほうが驚いた。
y[2] が *(y+2) に対応しているから、こういう書き方できるそうです。
C言語は奥が深いです。

いろいろ教えてくださって、ありがとうございます。m(_ _)m

ポインタ型同士の加算・ポインタ型に数値の掛算・割算はエラー

#include
main() {
    int* target;
    target = (int *)1 + (int *)2;
    target = (int *)1 * 1;
    target = (int *)1 / 1;
}

以上のことが分かると、次のようなネタコードが書けます。

ビットシフト無しで1バイトずつ取り出す。(1回の加算と1回のビット論理和)

#include
#define GET(T,N) ((int)*((char*)(&T)+(int)(N)))
main() {
    int i,target = 0×11223344;
    for(i=0;i

加算のみで5の倍数を表示する(3回の加算)

#include
#define GET(T,N) (int)((T*)0+(int)(N))
main() {
    int X = 8;
    printf("%d\n",GET(long,X)+GET(char,X));
}
広告

Written by なたで

2009年10月26日 @ 00:53

カテゴリー: program

Tagged with , ,

コメントをどうぞ(承認された後に公開されます。メールアドレスの記入は自由ですが、記入した場合でも一般公開されることはありません)

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。