• ベストアンサー

ポインタと配列の法則

ポインタと配列の法則がまだ、理解していません。 char *test1[] = { "あいうえお", "かきくけこ" }; と char test2[][20] = { "あいうえお", "かきくけこ" }; は、どちらも正しいでしょうか? 下は、sizeof(test[0])とすると20となりますが、上はなりません。 メモリの格納されている状態など知りたいです。 CではPHPのような var_dump関数は無いのでしょうか?

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

  • ベストアンサー
  • noocyte
  • ベストアンサー率58% (171/291)
回答No.4

下の図は,ひらがな1文字が2バイトの場合です (シフトJISまたはEUC-JP). レイアウトが崩れているので,テキストエディタにコピーして固定幅フォントでご覧ください. test1   ┌───┐    ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ [0]│ ・─┼───→┤ あ │ い │ う │ え │ お │\0│   ├───┤    └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘ [1]│ ・─┼──┐ ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐   └───┘  └→┤ か │ き │ く │ け │ こ │\0│            └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘   │   │   ├←┬→┤     ↑ sizeof(test1[0]) test2   ┌─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┬─┐ [0]│ あ │ い │ う │ え │ お │\0│ │ │ │ │ │ │ │ │ │   ├─┼─┬─┼─┬─┼─┬─┼─┬─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┼─┤ [1]│ か │ き │ く │ け │ こ │\0│ │ │ │ │ │ │ │ │ │   └─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┴─┘    0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19   ├←─────────────────────────────────────→┤                   sizeof(test1[0])

全文を見る
すると、全ての回答が全文表示されます。

その他の回答 (4)

  • zwi
  • ベストアンサー率56% (730/1282)
回答No.5

実際に試して見ましょう。cygwinのgccで試しました。 int main() { char *test1[] = { "あいうえお", "かきくけこ" }; char test2[][20] = { "あいうえお", "かきくけこ" }; printf( "%p\n", test1 ); printf( "%p\n", test1[0] ); printf( "%p\n", test1[1] ); printf( "%s\n", test1[0] ); printf( "%s\n", test1[1] ); printf( "-----------------\n"); printf( "%p\n", test2 ); printf( "%p\n", test2[0] ); printf( "%p\n", test2[1] ); printf( "%s\n", test2[0] ); printf( "%s\n", test2[1] ); printf( "-----------------\n"); } このプログラムの実行結果は、 0x22ccb8 0x402000 0x40200b あいうえお かきくけこ ----------------- 0x22cc80 0x22cc80 0x22cc94 あいうえお かきくけこ ----------------- となります。 見て分かるとおり、test1では実際にポインタで「あいうえお」と「かきくけこ」のポインタを保持していますが、test2ではポインタとして文字列のポインタを持っていません。 コンパイラがtest2もポインタ風に処理していますが、実際にはポインタを保持していません。 ですので、 test2[0] = test1[1]; test2[1] = test1[0]; なんてことをするとコンパイラに怒られて、エラーになります。代入すべきポインタ配列が無いですから。 でも、 test1[0] = test2[1]; test1[1] = test2[0]; printf( "%p\n", test1 ); printf( "%p\n", test1[0] ); printf( "%p\n", test1[1] ); printf( "%s\n", test1[0] ); printf( "%s\n", test1[1] ); printf( "-----------------\n"); とすると実行結果は、 0x22ccb8 0x22cc94 0x22cc80 かきくけこ あいうえお ----------------- となり無事代入されています。参照するときは文法上破綻の無いようにコンパイラがポインタとして扱っていると言うことです。

全文を見る
すると、全ての回答が全文表示されます。
  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.3
全文を見る
すると、全ての回答が全文表示されます。
  • mikaemi
  • ベストアンサー率50% (33/65)
回答No.2

上は sizeof test[0] == 4 くらいですかね?どちらも正しいと思います。 絵が書けないと説明しづらいですね^^; 以下のURLの「4.2 ポインタ配列」を参考までに。 http://oshiete1.goo.ne.jp/kotaeru_reply.php3?q=3306532 var_dump のような専用のものは用意されてなくて、自分でそういう関数を書かないといけないと思います(たぶん、簡単に書けます^^)。

全文を見る
すると、全ての回答が全文表示されます。
  • Willyt
  • ベストアンサー率25% (2858/11131)
回答No.1

前者も後者も20バイトの領域が確保されることには代わりはないのですが、前者は頭だけしかアドレス指定をできないのですが、後者はバイト毎のアドレスを指定できるとう違いがあるのです。物理的な格納の仕方は全く同じです。  つまり値を変えようとしたとき、前者は一つでも換えようとすると、全キャラクターを指定しなければならないのに対し、 Array の場合は1バイト(実際には2バイト)毎に値を変えられます。

全文を見る
すると、全ての回答が全文表示されます。

関連するQ&A

  • ポインタ配列の動的確保

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #include<stdio.h> #include<stdlib.h> #define kensu 3 main() { char abc[kensu+1]={'A','B','C','\0'}; char *ptr[kensu]; int i; printf("3つの整数を入力して下さい。\n"); for(i=0;i<kensu;i++){ ptr[i]=(char*)malloc(sizeof(char)*10); if(ptr[i]==NULL){ printf("メモリの取得に失敗しました"); exit(1); } printf("整数%c:",abc[i]); fgets(ptr[i],10,stdin); if(ptr[i][strlen(ptr[i])-1]=='\n') ptr[i][strlen(ptr[i])-1]='\0'; } for(i=0;i<kensu;i++) free(ptr[i]); } ちゃんと動いているようです。 しかし、ポインタ配列の動的確保をネットで調べてみると、ポインタのポインタ(?)を使って、下記のように2度mallocしています。 #include <stdio.h> #include <stdlib.h> #define N 3 int main(void) { char** arr; int i,j; arr = (char**)malloc(N * sizeof(char*)); /* ポインタ配列を確保 */ /* 配列の要素それぞれにつき、メモリ領域を確保 */ for(i=0;i<N;i++) arr[i] = (char*)malloc(N * sizeof(char));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • C言語の配列のサイズ

    二次元配列、三次元配列のサイズが知りたいです。 unsigned char test1[100]; は sizeof( test1 )で100ですが、 unsigned char test1[100][30]; はどのように書いたら100または、30なのか知りたいです。 unsigned char test1[100][30][5]; これも100,30,5のサイズをそれぞれ得る方法が知りたいです。 因みに以下のような数値なし[]を見たことがあるのですが どういう意味でしょうか? unsigned char test1[][30]; サイズを理解していないのは、ポインタを理解していないと同じことでしょうか?今更ながら自分自身が不安です。

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

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

  • ポインタと二次元配列

    ポインタを習ったんですが、二次元配列を指定する場合はどのようにすればいいのでしょうか? また、別関数でそのポインタを呼びたいのですが。 (例) main関数 char retsu[2][2] = {{2,4},{6,8}}; char *ptr; next関数 上記でいくと「main関数内のchar retsuの二次元配列を*ptrで指定」、「next関数でmain関数で指定した*ptr(retsu[2][2])を参照したい」 という事をしたいのですが、教えて下さい。

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

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

  • 2次元配列の動的確保

    ある画像を読み込むため、その画像を格納できる幅、高さを持った配列を動的に確保しようと考えています。 幅をxsize、高さをysizeで次のように記述しました。 unsigned char **src; int i; src = (unsigned char**)malloc(sizeof(unsigned char*) * ysize); src[0] = (unsigned char*)malloc(sizeof(unsigned char) * xsize * ysize); for(i=1; i<ysize; i++) src[i] = (src[0] + i * xsize); わざわざポインタのポインタを使用したのは、動的に確保した配列を2次元的なアクセスをしたかったためです。 画像の読み込み時は fread(src[0], sizeof(unsigned char), xsize * ysize, fp); としています。 上に記述したソースは問題なく動作しました。 しかし、上の場合だと全ての配列を連続して確保することができません。つまりsrcでmallocを一回、src[0]でmallocを一回使っているため、ポインタの配列の直後に配列を確保する保障がありません。そこでいっぺんに確保することを考えました。 unsigned char **src; int i; src = (unsigned char **)malloc(sizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize); for(i=0; i<ysize; i++) src[i] = (unsigned char *)(src + sizeof(unsigned char *) * ysize + i * xsize); このように組み上げ、読み込み時は上のfreadと同様に記述したところエラーが出てしまいました。 やはり一行目のmallocで無理やりsizeof(unsigned char *) * ysize + sizeof(unsigned char) * xsize * ysize分確保するのは失敗だったのでしょうか?

  • 配列の動的確保

    No.847223 reallocについて No.847300 ポインタについて と質問させてもらい、御回答をいただき、理解した(つもりな)のですが、以下のことが実現できなくこまっております。 (以前の質問はこれを実現するために質問しました。) まず配列array[1][20]を用意します(つまり文字列最高20字格納できる要素数1個の配列を用意)。 そして動的にこの配列のサイズを変更して、なにか文字列を入力する毎に、代入するスペースを逐次確保したいわけです。(メモリが溢れない限りスペースを確保しまくる) そこでcallocやreallocの記述の仕方に困っています。 まず、callocについて char array[1][20]; char *pn, *pn2; pn = (char *)calloc(sizeof(array)/sizeof(char),sizeof(char)); このボイドポインタをキャストする部分にchar* と char** のどちらを使えばいいか、です。 そしてreallocについて、 if( (pn2 = (char *)realloc(pn, sizeof(array)*cnt)) == NULL ){ printf("メモリの確保失敗!\n"); exit(0); } pn=pn2; strcpy(pn[cnt],input); 【ただし、cntは毎回1づつ増加する。】 【inputはchar型の配列で、なんらかの文字列がはいっている。】 としているのですが、これもキャストの仕方がわかりませんし、strcpyで、セグメンテーションフォルトになります。構造体を使ったリスト形式も考えたのですが、reallocの使いかたを覚えたいのであえてこの形式で実現しようとしています。 結局どうしたいかというと、realloc部をforループさせて、cntを1ずつ増加させ、 pn[1][20] つぎは pn[2][20] つぎは pn[3][20] とどんどん増やしていきたいわけデス。 すこしわかりにくい説明だとおもいますが、不明点や、言い回しがオカシイ箇所があればご指摘下さい。

  • ポインタ配列

    "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'; }

  • 配列とポインタと同時に使用する宣言について

    配列とポインタを同時に使用した場合、どのように確保されるのかイマイチ理解しきれていません。 例えば、 char *pointer[10]; と宣言した場合、 pointer[0]="ABC" pointer[1]="DEF" ・・・・ のようにポインタ型を配列で管理する、という風に認識しています。 一方で char (*pointer)[10] とした場合、どのように確保されるのでしょうか?

  • メモリとポインタと配列と

    malloc()を使用して可変の変数を作り加工。 後々に参照するためにポインタの配列に格納したいと考えております。 malloc()を行った後は必ずfree()にてメモリを開放せねばなりませんが、開放するとポインタの配列に格納した値も消えてしまいます。 だからといって開放せずにいるとメモリリークが起きてしまいます。 この様な場合はどのようにすればよろしいのでしょうか? 大体以下のような処理を考えております。 ご教授願えれば幸いです。 ****************************************   char *p[100];   for(int i=0;i<100;i++) {     char *word1 = "あいう";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     int size = strlen(word1) + 1;     char *memo1 = (char *)malloc(size);     if (memo1 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     strcpy(memo1, word1);          //・     //・ *memo1 を利用した処理。     //・     char *word2 = "abc";// ここでは固定文字を代入しているが、実際には何桁の文字列が入るかは不明。     size = strlen(word1) + 1 + strlen(word2) +1;     char *memo2 = (char *)malloc(size);     if (memo2 == NULL) {       printf("メモリを割り当てられません\n");       exit(1);     }     memset(memo2, 0x00, size); //初期化     strcpy(memo2, word2);     strcat(memo2, "\t");     strcat(memo2, memo1);     p[i] = NULL;     p[i] = memo2;     free(memo2);     free(memo1);   } **************************************** 宜しくお願いします。

このQ&Aのポイント
  • 短期バイトしか経験のない状況は就活に不利なのでしょうか。企業側には、短期=飽き性→職を転々とする、というイメージを持たれてしまうのでしょうか。
  • 人事の方はバイトの経験をどれくらい選考上考慮にいれているのでしょうか。この際、バイト経験はアピールしない方が良いのでしょうか。
  • 短期バイト経験の影響やアピール方法についてお答えします。短期バイトしか経験のない状況が就活にどのような影響を与えるのか、企業側がどのようなイメージを持つのかについて解説します。また、人事の方がバイトの経験をどれくらい選考上考慮にいれるのか、バイト経験のアピール方法をご紹介します。
回答を見る