• ベストアンサー

配列とポインタの関係

配列とポインタについてです。 char *p_str="HAPPY";と char p_str[10]={'H','A','P','P','Y'}; は同じことでしょうか?

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

  • ベストアンサー
  • hegemon
  • ベストアンサー率72% (21/29)
回答No.2

C/C++での文字列は、最後に終端をあらわす'\0'が付きます。 なので、メモリ上の配置が同じレイアウトになるのは下記のように書いた場合です。 char p_str[10]={'H','A','P','P','Y','\0'}; しかし、この場合も実際に生成されるコードは違う場合があります。 char *p_str="HAPPY"; この場合の"HAPPY"はリテラル文字列と呼ばれ、処理系によっては書き込みが禁止されたメモリ領域に配置されます。 一方、配列のほうは普通の変数と同じ形式で配置され、書き換えが可能です。

tomo_ko_n
質問者

お礼

ありがとうございます。 リテラル調べてみます。

その他の回答 (1)

回答No.1

違います。

関連するQ&A

  • 配列とポインタ

    配列とポインタの違いを教えて下さい。 後 char str[100]; と const char *strはどこが違いますか?

  • ポインタ配列

    "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() { char x[3]; char *y; x[0]='a'; x[1]='b'; x[2]='\0'; y="abc"; printf("xの値は%s\n",x); printf("yの値は%s\n",y); } 通常の配列宣言では、このままだと文字列をまとめて 代入できないのに対して、ポインタ変数ならまとめて代入することができるのは何故ですか?そういう仕組みだと言われてしまえば、それまでなんですが・・・

  • char配列のポインタ消去

    char配列のポインタ消去 こんにちは。C++初心者で、現在ポインタと配列の関係を勉強しています。 以下のコードついて質問があります。 #include <stdio.h> extern void main () { char* str = "hello world."; printf(str); delete str; } コンパイルはうまくのですが、 いつもプログラムが正常に終了できません。 deleteをコメントアウトすると正常に終了します。 理由がわかる方いらっしゃるでしょうか。

  • C言語の型と配列

    char* str[10]={"a","b"}; char* str2="c"; としたときにstr=str2とすると 型が合わないといったエラーが出ます。 でもstrって結局はポインタの配列の先頭要素のアドレスですよね。 ポインタにポインタを入れているので通るのかなと思ったんですけど、 配列で宣言するとポインタにも型がつくのでしょうか? この例だと strは char * を10個持つ配列をさすポインタ  で、 str2はchar *をさすポインタ みたいなかんじです。 質問の意味がわかりにくいですが、ご指摘をいただければ補足しますので よろしくお願いします。

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

    ポインタの配列の動的確保について教えてください。 入力した数値をポインタ配列に入れるプログラムです。 下記のように書いてみました。(見づらくてごめんなさい) #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));   ・・・ ポインタの配列を宣言して、配列の各要素に動的確保するのと ポインタのポインタを宣言し、ポインタ配列を動的確保して、再度配列の要素に動的確保するのとでは、何か違いがあるのでしょうか? ポインタのポインタを宣言し、ポインタ配列を確保する必要性が良く分かっていないのです。 ネット等で調べて見たのですが、理解力がないのかよく分かりませんでした。 どうか教えてください。

  • 2次元配列とポインタ

    char str1[][6]={"one","two","three","four","five"}; char *pt1; pt1 = str1; //(1) 上記の記述では(1)で型エラーが発生します。 ここを pt1 = *str1; //(2) と変更するとOKになるのですが、 (1)にすれば配列名だけでstr1先頭のアドレスがポインタpt1にセット されると思うのですが、なぜダメなのでしょうか?

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

    下のコードについて2つ質問があります。 (1) char *p; p = str; ならわかるのですが、なぜ型が違う char *p = str; のような代入がOKなのでしょうか。文字列をコピーするときの   *p = *str; と比較して、とても違和感があります。  str は引数で受けた文字列の先頭アドレス。 (2)   char *str;   str = " 1 23 4 5"; と   char str[] = " 1 23 4 5"; との違いがよくわかりません。 #include <stdio.h> #include <ctype.h> void TrimSpace(char *str) {   char *p = str;        // (1)型が違うのになぜこんな代入をするのか?      while (*str != '\0') {     if ( !isspace(*str) ) {       *p = *str;      // この代入は自然       p++;     }     str++;   }   *p = '\0'; } int main(void) {      //char *str;   //str = " 1 23 4 5";     (2)これでは空白を詰めた後の文字列が表示されないのはなぜか?      char str[] = " 1 23 4 5"; //これで OK   printf("空白を詰める前:\"%s\"\n", str);   TrimSpace(str);   printf("空白を詰めた後:\"%s\"\n", str);   return 0; }

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

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

  • ポインタ配列

    ポインタ配列によるひとつのプログラムを組もうと思っています。 で、以下のようなプログラムを作ってみました。 1:#include<stdio.h> 2:#define NUM 5 3:main(void){ 4: char *str[NUM]; 5: int i; 6: for(i=0;i<NUM;i++){ 7: printf("string --->"); 8: scanf("%s",str[i]); 9: } 10: for(i=0;i<NUM;i++){ 11: printf("str[%d] --> %c\n",i,str[i]); 12: } 13:} これなのですが、8行目のscanf文でコンパイルエラーではなく、実行エラーが出ます。どのようにすれば動くようになるのでしょうか? 入力する文字は、9文字以下を想定しています。

専門家に質問してみよう