• ベストアンサー

Cポインタについて

super_kyoroの回答

  • ベストアンサー
回答No.2

キャストはコンパイラに「データの取得の仕方」を指示するために記述します。 「&変数」では、変数のアドレスを取得するという意味になりますが、この「変数」の宣言型がint型以外だった場合でも、(int *)というキャストを入れることでint型ポインタとして扱えるようになります。 例えばchar型の配列変数a[]があったとします。 これをint型ポインタの変数pに  p=(int*)&a[0]; などとしてやり、以降はp++などを使うことで順次アクセスを高速に行えるようなメリットがあります。(一例です。他にも構造体の先頭アドレスをchar型ポインタに入れてやり、バイト単位での順次アクセスに使ったりします) ただしこのようにポインタ型のキャストを使う場合、アライメントに注意する必要があります。  char型ポインタ→どのアドレスにもアクセス可  short型ポインタ→2の倍数アドレスにのみアクセス可  long型ポインタ→4の倍数アドレスにのみアクセス可 というように、データサイズによってアクセスできるアドレスに制限があります。 従って、char型配列変数をshort型ポインタやlong型ポインタにキャストするように、より大きなサイズのポインタにキャストする場合は正常に動作しない可能性が高くなり危険です。アドレスが明確にわかっている場合など、使用される場面は限定されると思います。

gogogo-n
質問者

お礼

すごくわかりやすく、納得のいく回答をありがとうございます。 ポインタにもキャストがあるんですね。 勉強になりました。 本当にありがとうございました。

関連するQ&A

  • C++とインラインアセンブラでのポインタ値が違う

    C言語で取得した配列変数の先頭ポインターとインラインアセンブラで取得したポインターが異なる現象が起きました。 2個のソースファイルを持つ下記プログラムで、pointer1とpointer2が異なる原因を教えてください。 ただし、提示のソースはあくまで、見本で実際には多くの変数やコードを記述しています。 開発環境はWin7(64bit)、VC++2010無償版です。 main.cpp #include <windows.h> int *disp; int *pointer1; int *pointer2; int data[8]; void disp_sub(); int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) { _asm{ mov disp,offset disp_top call disp_sub jmp pgm_end disp_top: lea eax,data mov pointer1,eax } pointer2=&data[0]; if(pointer1 != pointer2)Beep(3000,1000); _asm ret pgm_end: return 0; } sub.cpp extern int *disp; void disp_sub() { _asm{ call disp } }

  • C言語のポインタについて教えてください。

    C言語のポインタについて教えてください。 ・pointer1.c  int main(){   int a;   int *p;   p = &a;     a = 123;   printf("%d", *p);   return 0;  } ・pointer2.c   int main(){ int a[100]; int *p; p = &a[0]; int i; for(i = 0; i < 100; i++) a[i] = i; for(i = 0; i < 100; i++) printf("%d", *p++); return 0; } と二つのソースコードがあるとき、pointer2.cの「p = &a[0]」をpointer1.cのように「p = &a」と書けないのはなぜですか?  また、「&a」は動かすことのできなく、「aを指し示す*p」は動かすことができる変数のようなもの、という認識に誤りはないでしょうか?  宜しくお願いします。

  • C言語の配列とポインタについて

    C言語の配列とポインタについてわからないことがあります。 以下のソース例は、10個の値の平均値を求めるプログラムです。 コメントを挟んだ部分が疑問点です。 【ソース例】 #include <stdio.h> int getaverage(int *data); int main(void) { int average,array[10] = {15,78,98,15,98,85,17,35,42,15}; average = getaverage(array); printf("%d\n",average); return 0; } int getaverage(int *data) { int i,average = 0; for (i = 0;i < 10;i++) { average += data[i]; /*ポインタ変数なのに? */ } return average / 10; } 【実行例】 49 このdata[i]はポインタ変数であり、 配列arrayの i 番目の要素であるarray[i]の"アドレス" が代入されているはずだと思うのですが、 なぜ通常の整数変数であるaverageと数値計算が出来、正しい結果が出たのでしょうか? あたかもdata[i]には、 array[i]の"アドレス"ではなく、 array[i]の"メモリの中身"が代入されているようです。 どういうことでしょうか? 回答よろしくお願いします。

  • 【なぜポインタを使うのか】

    私は、ポインタのメリット・デメリットを以下のように考えています。 ◆メリット メモリを多く確保しなければならないオブジェクトについて、コピー処理を行うことなく省メモリでインタフェースできる。 ◆デメリット ・関数内でしか使用しない非ポインタのローカル変数に比べ、  アクセス可能な場所が多くなってしまい、色んな箇所から値が変更されうる。(影響範囲の限定がしずらい) ・可読性が低くなる。(若いエンジニアはCの経験者は少なくっていくと思われるため、保守コストが若干割高になる) そのため、よっぽどメモリを多く使うようなオブジェクトでなければ、 (もしくは速度を重視する必要があるプログラムでなければ) 値渡しにしても良いのではと考えています。 しかし、度々目にするソースは、何でもかんでもポインタで処理しているものも多々見受けられます。 特に、int型のようなメモリを大量に使用しないものでも、ポインタで変数宣言しているケースもよく見ます。 なぜなのでしょうか? (熟練のC言語プログラマが、昔ながらの記述を踏襲しているというのはあるのかなと考えていますが)

  • C言語初心者です。ポインタについて教えて下さい。

    ポインタの宣言で次のように宣言します。 int *p1,p2; p1はポインタですが、p2はポインタになるのでしょうか。 それとも普通のp2という変数になるのでしょうか。 友人との間で意見が分かれています。

  • C言語のポインタについて

    C言語のポインタ(配列もポインタに含まれるのか?)について質問です。 係数を行列形式で表される状態方程式などの2変数以上の方程式を解くプログラムにおいてよくポインタや配列が使われているのですが、なぜポインタや配列を使うのでしょうか?利点など詳しく教えていただけませんでしょうか。。。 どなたか分かる方よろしくお願いします(*_*)

  • ポインタ変数とポインタのポインタ

    ポインタ変数の宣言 char *a[]; をしたとき僕の中では a[0],a[1]...という、ある文字列A,B,C...の最初のアドレスを指すポインタが、配列になっているものを宣言していると理解していました。 しかしこの次に、ポインタのポインタが出てきました。僕はこれを、 ある変数を指し示すアドレスのアドレスである、と理解しました。 この2つは1つめはいくつかのアドレスを指し示すもの、2つ目は1つのアドレスを指し示すものであるとして、僕の中で異なったものであると理解していましたが、参考書「C標準コースウェア」によると プログラムにおいて、関数でポインタ配列を受け取るときchar *p[]はchar **pとしてもよい と書かれており、またその実例として、 (9-5) #include <stdio.h> void disp (char *p[],int n){ int i; for (i= 1;i<n;i++){ printf("%s\n",p[i]); } } int main(void){ char *girl[] = {"Arica","Candy","Lisa"}; disp (girl,sizeof(girl)/sizeof(girl[0])); return 0; } というプログラムが書かれていました。 ここで一気に訳が分からなくなりました。 char *girl[] = {"Arica","Candy","Lisa"}; と宣言されているため、 girl[0]はAricaという文字列の最初のアドレスを指すポインタ、 *girl[0]はAricaという文字列を直接指し示していると解釈しています。 girlは{"Arica","Candy","Lisa"}という文字列の配列の最初のアドレスを指し示していると考えました。 sizeof(girl)を使った時に不思議なのですが、 girlはどのように配列の終わりを理解しているのでしょうか? (配列の要素数を渡していない点が不思議です。) また、 disp側が受け取ったのは*girl[]であり、いくつかのポインタの配列ですが、渡したものはgirlという要素数がないポインタ1つだけです。 そして最初の疑問が出てくるわけですが、*p[]を**pと書きかえてみると、 文字列のアドレスを示すgirlという名の1つのポインタを渡すと、pという名のポインタのポインタで受け取るというのも、よくわからなくなっています。 おそらくポインタ配列に対する理解がどこかでずれているようですが、自分でどこがわからないのかわからなくなっています。 どうかご教授ください。

  • int型のポインタ

    int型のようなメモリを大量に使用しないものでも、ポインタで変数宣言しているのをよく見かけますが、 なぜでしょうか? 私はCに慣れていないため、int型くらいのサイズだったら、なるべくならポインタを使わないで書いてもらった方が可読性が良いので、ポインタにするメリットがあまり感じられません。

  • ポインタのポインタが引数にある関数の使い方。

    ポインタのポインタが引数にある関数の使い方。 現在、このポインタのポインタが引数にある関数の動きがわからず困っています。 int test(int ** head) { int * pTail = (int *)*head; pTail = pTail + 1; } もし、この関数を呼び出して使用した場合どのような動きをするのでしょうか? int * comm_msg; これをグローバルポインタ変数として宣言させて、 test((void **)&comm_msg); このように呼び出したとした場合とさせていただきます。

  • ポインタのアドレスの不変的な性質?

    最近奇妙な現象?に遭遇しました。 理解している人には笑われるかもしれませんが・・・・ ソースを以下に示します。 #include <stdio.h> void function(int *pointer); void main(){ int sample=3; int *pointer; pointer=&sample; function(pointer); printf("%d\n", *pointer); } void function(int *pointer){ int temp=9; pointer = &temp; } 今上のソースとは別のプログラムを作成中で、上のような状態になっています。関数にポインタのアドレスを渡し、関数の中でアドレスを書き換えて表示を違うものにしようと考えました。 上の表示結果は3になります。なぜなのでしょう? そして目的を達したいため、上のように関数内でのアドレスの書き換えが呼び出し側に反映されるようにすることができないでしょうか? 分かる方はよろしくお願いします。