• ベストアンサー

ポインタ

long ToLittleEndian(char *a,long bytesize){ long i; char lb; char hb; long lsize; lsize=bytesize/2; for (i=0;i<lsize;i++){ hb=*(a++); lb=*(a--); *(a++)=lb; *(a++)=hb; } return 0; } ポインタのアドレスがはみだすとどうなるのでしょうか? 上記のようなコードの場合、最後の処理でポインタaが1バイト分はみ出してしまいますが、 存在しないアドレスを参照しようとするとエラーになるかと思いますが ポインタを動かすだけだと問題ないのでしょうか? 処理系やコンパイラに依るのでしょうか。 初心者ですがよろしくお願いします。

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

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.1

>ポインタを動かすだけだと問題ないのでしょうか? ポインタが指し示す内容を参照しなければ平気です。 NULLポインタがいい例だと思います。 char * p; char * q; char c; p = NULL; q = p; /*これはOK*/ c = *p; /*これはNG*/

sha-girl
質問者

お礼

的確なご回答ありがとうございます。

その他の回答 (2)

  • a-kuma
  • ベストアンサー率50% (1122/2211)
回答No.3

ポインタを動かしただけでは何も問題が起きない、というのは先の回答の通りです。 因みに、質問に出された関数はビッグエンディアンをリトルエンディアンに変える 関数のようですが、これでは2バイトの領域だけにしか通用しません。 例えば、0x01020304 という4バイトの整数のメモリイメージは以下のようになります。 ←低     高→ ┌─┬─┬─┬─┐ │01│02│03│04│ビッグエンディアン └─┴─┴─┴─┘ ┌─┬─┬─┬─┐ │04│03│02│01│リトルエンディアン └─┴─┴─┴─┘ 隣り合ったバイトを交換するだけでは(普通は)駄目です。 ビッグエンディアンでもリトルエンディアンでもない処理系もあったような 気もします。そのような系を相手にしているのであれば、この回答は気にせず 読み飛ばしてください。

sha-girl
質問者

お礼

勉強になります。 4バイトについては考えていませんでした。 ご回答ありがとうございました。

  • osamuy
  • ベストアンサー率42% (1231/2878)
回答No.2

実際に、そのポインタで、メモリにアクセスしないかぎり、エラーにならないです。 でなかったら、例えば、NULLを入れただけで、エラーになってしまいますよね。 もちろん、そういったレンジチェックを行う処理系もあるかもしれませんが、普通はそこまでやってないと思います。

sha-girl
質問者

お礼

参考になりました。 ご回答ありがとうございます。

関連するQ&A

  • ポインタについて

    #include<stdio.h> int main(void){ int i; char *pt = "Hello World"; char a[11]; pt = &a; for(i=0;i<=11;i++){ printf("%c %x\n",pt,&a[i]); pt++; } return(0); } H abcd80(←アドレス) E abcd81(←アドレス) のように表示したいんですが、アドレスだけうまくできてHELLO WORLD のほうがうまく表示できません。 夏休みの間ブランク空けたんでポインタ全て抜けてしまったみたいです^^;  よろしくおねがいします。

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

    ポインタ変数の宣言 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という名のポインタのポインタで受け取るというのも、よくわからなくなっています。 おそらくポインタ配列に対する理解がどこかでずれているようですが、自分でどこがわからないのかわからなくなっています。 どうかご教授ください。

  • ポインタ配列

    "one","two","three","four","five","six","seven","eight","nine","ten" のポインタ配列の文字列を、ASCIIコード順に並べ変えようと思ったのですが、 もうどこが間違っているかさえわからないぐらいになってしまいました。 まだまだはじめたばかりなもので、わからないことだらけなんで、 できるだけわかりやすい説明おねがいします。 関数の引数に問題があるのじゃないかと思ったのですが、 何かいいアドバイスありましたら、お願いします。 #include <stdio.h> /* 関数のプロトタイプ宣言 */ int strmp(char *,char *); void cpy(char *,char *); int main (void) { /* ポインタ配列の定義 */ char *x[10]={"oneee","twooo","three","fourr","fivee","sixxx","seven","eight","ninee","tennn"}; /* ポインタのポインタの定義 */ char **pp=x; char k[100]; char *p=k; int i,t,a,b,c,d; a=0; /* ポインタ配列を自作関数を使って、ASCIIコードの大きいほうからに並び替える */ for(i=0;i<9;i++) { for(t=1;t<10;t++) { a=strmp(*(pp+i),*(pp+t)); if(a<0) { cpy(p,*(pp+i) ); cpy(*(pp+i),*(pp+t) ); cpy(*(pp+t),p); } } } for(i=0;i<10;i++) { printf("%s ,",x[i]); } printf("\n"); return 0; } /* 文字の比較をする関数 */ int strmp(char *x,char *y) { int i; for(i=0;*(x+i)==*(y+i);i++) { if( *(x+i)=='\0') { return 0; } } return *(x+i)-*(y+i); } /* 文字をコピーする関数 */ void cpy(char *a,char *b) { int i; for(i=0;*(b+i)!='\0';i++) { *(a+i)=*(b+i); } *(a+i)='\0'; }

  • ポインタ配列のアドレスについて

    #include <stdio.h> int main() { int i; char *ary[] = { "a" , "b" , "c" }; for(i=0; i<3; i++) printf("%u\n" , &ary[i]); return 0; } /*実行結果 6618616 6618620 6618624 */ 上記のプログラムを実行したときポインタ配列*aryがchar型だろうがdouble型だろうがアドレスが4つとびになるのですがなぜなんでしょう?アドレスを求めるプログラム自体が間違っているのでしょうか?

  • ポインタのポインタについて

    VisualC++2008 の、Windowsフォームアプリケーションを使用しています。 自作クラスの中に組み込む線形リスト的なものを、後で移動したりする場合実体のコピーをしなくて済むよう 今、「アドレス」を格納する配列を作りたいです。 しかし、ポインタのポインタに対して色々実験してみたのですが どうもあと一歩ぐらいのところで手が届きません フォームのイベントで、試しに以下のように書いてみると Text = ""; char *a[8], b =7 ,*c = new char[7], i =7; while (i) { c[i] = --i; a[i] = &c[i]; } a[7] = &b; while (i<8) Text += *(*a+i++); delete c; これを実行したとき フォームのTextが 「01234567」 となってほしいのですが 「0123456-3」 となってしまいます。 試してみたのですが その直後にbを調べると、やはりちゃんと7になっており また a[7] と &b をifおよび==を用いて比較してみても 同じになっています。 なお、この-3というのはどうも、解放処理の後でそこにアクセスした場合はこの場合 「-35」 となり、確保中の時に代入してないアドレスにアクセスすると 「-3」 となるような感じです。 このような、連続していないアドレスへの参照を配列化しておいて取り出す事は出来ないのでしょうか?

  • C言語 ポインタ型引数の呼び出しについて2

    C言語 ポインタ型引数の呼び出しについて2 以前質問した関数ですが、ネットを検索していたら同じような引数の関数を見つけました。 多分これを参考にしたのではないかと思います。 char* GetCSV(char** pBuf) { char *p = *pBuf,*q = p; if (!p) return p; if (*p == '"') { *p++ = 0; do ++q; while (*q && *q != '"'); if (*q == '"') *q++ = 0; } if ((*pBuf = strpbrk(q,",")) != 0) *(*pBuf)++ = 0; return p; } 当方がやりたい処理はVB6でCSVをリードして処理しているのですが、処理速度が遅いため I/OをしているところをCに変更して処理速度が向上するか確認したいのです。 他にも色々調べたのですがstrtokを使って処理されている方が多いようなのですが、 "1,,2,3"と言うデータの場合に"1" "2" "3"と返ってくるようで、 私のほしい値としては"1" "" "2" "3"というように返ってきてほしいのです。 上記のGetCSVでは"1" "" "2" "3"に返ってくるようです。 何とか動くようにと下の関数をかぶして実行して見たところ結果は正しかったのですが どうもメモリリークをしているように思います(タスクマネージャーのメモリ使用量は増えていく) int split(char *ary[], char *s) {   int len = 0;   int lsize = 0; char *strBuff[BUF_SIZE]; *strBuff = strdup(s); lsize = strlen(*strBuff); for (len = 0; len < lsize; len++) { if ((ary[len] = GetCSV(strBuff)) == NULL) break; } free(*strBuff); return len; } strdupの後メモリを開放しているつもりなのですが問題あるのでしょうか? C言語をあまりしたことがないので詳し方ご教示願えないでしょうか?宜しくお願いします。

  • 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」は動かすことができる変数のようなもの、という認識に誤りはないでしょうか?  宜しくお願いします。

  • ポインタのポインタの必要性

    書物によるとポインタのポインタの使用例として「ポインタの配列」はポインタを使ってアクセスすることができます。」[*]とありますが、どうしてポインタのポインタが必要なのかがいまいちピンと来ません。 どういう場合なのかを知りたく思っています。 [*]サンプルスクリプト ===================================================== char *mnthp[3] = {/* ポインタの配列の宣言 */ "January", "February", "March" }; char **p1;/* 「ポインタのポインタ」の宣言 */ int i, j; p1=mnthp;/* 「ポインタのポインタ」にポインタの配列 */ /* の先頭番地を設定 */ /***** 例1 *****/ for (i = 0; i < 3; i++) {/* 「ポインタのポインタ」の値を変えずに */ printf("%s\n", *(p1 + i));/* 相対的に文字列を出力 */ } ==> このようなことをしなくとも printf("%s", mnthp[i]); で値を参照出来ると思われる。 ===================================================== [*] http://www9.plala.or.jp/sgwr-t/c/sec10-4.html 宜しくお願い致します。

  • 関数のポインタ

    char* check(int a,int b,int c) { return(\"yes\"); とした場合char* checkは何を表しているのでしょうか。 また、 char *str_copy(char d[], char s[]) { char *t=d; while(*d++ = *s++) ; return t; とした場合との違いはあるのでしょうか。 ポインタを返すときに*をつけると教わったのですがいまいち理解できなかったのですがどのような処理が行われているのでしょうか、お願いします。

  • ポインタで、実装メモリの先頭から100バイト分参照してみたい

    いつもお世話になります。 Cの質問です。 ポインタの勉強中なのですが、ポインタを用いて、実装メモリの先頭から100バイト分を参照してみたい、と思いました。 先輩が言うには「メモリの先頭領域にはメモリのメーカーとか、文字コードが順番に入ってるよ」とのことなのですが、どうにもプログラムが作れません。 mallocでは、どうやら「コンパイル時にメモリ領域を確保する」らしく、指定したメモリ位置(つまりアドレス0)からxxバイト分確保することはできないようです。 私が試しに書いてみたソースは以下になります。 #include<stdio.h> #include<stdlib.h> int main(void){ int i; char *p; p = (char*)malloc(sizeof(char) * 100); for (i=0;i<100;i++){ printf("%c",*p); p++; } return (0); } アドバイスでもかまいませんので、ご指導いただけたらと思います。 よろしくお願いいたします。

専門家に質問してみよう