• ベストアンサー

C言語の基礎的な質問---文字配列の初期化

terra5の回答

  • ベストアンサー
  • terra5
  • ベストアンサー率34% (574/1662)
回答No.3

>この記述は、配列とは別のところに初期値で埋まった領域(質問でいう"ABC")がある、という意味に思えてしまいます。 実行のする度に値が設定されるわけですから、配列と同じ並び順でない可能性はあっても、必ずなんらかの形でどこかに存在します。 >これも、文字列定数の領域(この場合は"ABCD")が配列の領域とは別にあるように読めてしまいます。 これもその通りでしょう。 >配列strとは別のところにある"ABC"という領域の内容を、コピーして設定する、 >ということでしょうか。 基本的にはその通りでしょう。 やろうと思えば"A B C "というところから一つおきにコピーする実装も可能でしょうけど(笑) また、(イ)と(ロ)はコンパイラ上では同じ扱いだったと思いますし、kaicheさんが書いたやり方は、実質的にコピーと同じですね。 初期化のために代入する値が結局はどこかに必要ですから。 ただ、"ABC"と連続して格納されている領域があるかないかは、実装よるでしょうから、 どちらの場合も連続領域におかないようにするコンパイラの作成は可能でしょう。 ただ、通常は効率上そういう実装はまず無いと思いますが。 ただ、この違いも使う上ではどうでもいいことですけど。 あと、気になるのは、領域というのをどういう意味で考えているかどうかですね. もし、私が考えているものより、狭い意味で使っているなら、説明も変えないといけないでしょう。 あ、私もコンパイラの実装まではやったことはありませんが、Cのコンパイル結果をアセンブラレベルで見たこととか,OSのメモリ管理とかの知識はそれなりにあります。

noname#1357
質問者

補足

ということはこういうことですね。 (文字配列の初期化に関して) 配列とは別のところに初期化子があり、配列の領域を確保するときにそれをコピーしている。 初期化子がどこかになければ配列を初期化することは出来ない。 しかし、それは char *str="ABC"; (ハ) の"ABC"とは異なり、初期化子がどう並んでいるかはわからない。 どう並んでいてもそれを直接触ることは出来ないので関係ない。 つまり >この違いも使う上ではどうでもいいことですけど。 ということですね。 char str[ ]="ABC"; (イ) と char str[ ]={'A', 'B', 'C', '\0'}; (ロ) はまったく同じ意味だ。 他方、(ハ)は'A', 'B', 'C'がどこかにあるという点では同じでも、 ぜんぜん意味合いが異なる。

関連するQ&A

  • C言語の配列について質問です。

    配列の添え字に別の配列を指定するような以下の処理について 質問です。 #include <stdio.h> int main(void) {    int k = 0;    int kn = 0;    char str[256];    char key[] = "ABCD";    kn = strlen(key);    for(k=0; k<kn-1; k++) {    str[key[k]] = kn-k-1;    } } 上記についてですが、for文の中で "str[key[k]]"とありますが、 ループ処理にともなって配列str[] の添え字は、str[A], str[B], str[C] となるのでしょうか?? その場合、結果的に配列str[]の各要素にはどのような値が格納され るのでしょうか? そもそも、配列の添え字に対して別の配列を指定した場合の動きが よくわかりません。 どなたか教えて頂けますか??

  • C言語のint型の配列が分かりません

    #include<stdio.h> int main(void) { int str[ ]={0,1,2} printf("%s\n", str); return 0; } というプログラムをC言語でつくってみましたが動きません.(012と表示されて欲しかったのですが) int str[ ]={1,2,3}の部分をchar str[ ]={'0','1','2'}とすれば動きます. そこで質問なのですが, printf("~%s~", (配列名));  はchar型の配列にしか適応できないのですか? ※追記 puts関数の定義は int puts (const char *str); であるそうなので char型の仮引数にはchar型のアドレスを渡さなければいけません. ではprintf関数の定義は一体どんなものなのですか?

  • C言語の型と配列

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

  • C言語:小文字を大文字に変換する関数を作成

    C言語超初心者です。学校の課題で次のような問題が出されました。 ・問題・ 次に挙げる縛りに沿い、以下の関数とメイン関数を作り、処理結果を画面に作成しなさい。 char *tst(char *str) ・strの中の文字列も小文字を大文字に変換し、変換した文字列が格納されているchar *に返す。 ・引数strの中の文字列は受け取った状態で手を加えない。 ・関数内でmalloc関数を使用し、領域を確保して大文字に変換した文字列を格納しreturnでポインタを返す。 ・malloc関数を使用する。 ---------------------------------------------------------------------------------- 大文字に変換するには while(*str != '\0') { if(*str >= 'a' && *str <= 'z') { *str -= 'a'- 'A'; } ++str; } というのは分かったのですがここから何をすするか全く分かりません。初心者なのでなるべく分かりやすく教えてもらえると有難いです。 お願いします。

  • C言語

    以下のC言語のプログラムを教えてください。 お願いします。 (1)標準入力から文字列(2 文字以上)を入力し,文字数を計上すると共に,入力された文字列の逆順に入れ替える処理を実現してください.なお,以下の要件を満たしたプログラムを作成してください. ・ 入力された文字列は,char 型の配列(要素数50)で受け取ること ・ 文字数を計上するcount 関数(引数:配列のアドレス,戻り値:文字数)を定義 し,main 関数より呼び出すこと ・ 文字列を逆順に入れ替えるreverse 関数(引数:配列のアドレス,戻り値:無し) を定義し,main 関数より呼び出すこと ・ 標準出力の処理は,main 関数で記述すること 【プロトタイプ宣言】 int count(char *str); void reverse(char *str); 【実行結果】 文字列を入力してください(2 文字以上) apple 文字数 = 5 入れ換え前 apple 入れ換え後 elppa (2)char 型の配列(要素数50)を2 つ宣言し,標準入力から2 つの文字列を入力してください.そして,格納した字列を入れ替える関数(swapstr 関数)を作成し,入れ替え前と入れ替え後の配列内の値(文字列)を配列名とともに標準出力するプログラムを作成してください. 【プロトタイプ宣言】 void swapstr(char *str1, char *str2); 【実行結果】 2 つの文字列を入力してください apple strawberry 入れ換え前 配列str1 = apple 配列str2 = strawberry 入れ換え後 配列str1 = strawberry 配列str2 = apple

  • 二次元配列による文字列の配列の受渡しについての質問です。

    二次元配列による文字列の配列の受渡しについての質問です。 #include <stdio.h> void print_pname(char str[][5], int n) { int i, j; for (i = 0; i < n; i++) { printf("str[%d] = \"", i); for (j = 0; str[i][j] != '\0'; j++) putchar(str[i][j]); printf("\"\n"); } } int main(void) { char ary[][5] = {"Lisp", "C", "Ada"}; print_pname(ary, sizeof(ary) / sizeof(ary[0])); return 0; } 上のプログラム中の関数print_pnameの引数char str[][5]についてですが char (*str)[5](配列のポインタ)と変更した場合にwarningが多数発生します。 これはどうしてでしょうか? また、上のプログラムを配列のポインタを使って変更することは可能でしょうか? 以上、よろしくお願いします。

  • C言語の文字列で

    基本的なことですがよろしくお願いします。 文字列の配列を作る時 文字を個々に配列にする場合配列の大きさを\0を合わせた5にすると思います str[5] = {'a','b','c','d','\0'} 疑問に思ったのは文字列で初期化する場合は\0はコンパイル時に自動で付加と説明を受けましたが、初期化時には配列の大きさは文字列の長さだけで良いのでしょうか? str[4] = "abcd" 解らなければ多く取ればいいよと言われればそれまでですが、for文で回転させる時は'\0'はどうなっちゃうんでしょうか

  • 文字列strの中から文字cを探すプログラム(C言語)がわからない

    文字列strの中から文字cを探すプログラム(C言語)がわからない 柴田望洋さんの「[新版]明解C言語」という本の演習11-2なんですがどうしてもわかりません。間違いは無いと思うのにコンパイルすると警告を吐かれます。 僕が書いたプログラムを載せます。 /* 文字列strの中に、文字cが含まれていれば(複数ある場合は、最も先頭側とする)、 その文字へのポインタを返し、含まれていなければNULLを返す関数 char *str_chr(const char *str, int c) {} を作成せよ。 */ #include<stdio.h> char *str_chr(const char *str, int c){ while(*str){ if(*str==c) return str; str++; }     return NULL; } int main(){ char *str; char c; scanf("%s",str); scanf(" %c",c);     printf("%d",str_chr(str,c)); return 0; } コンパイラは「関数str_chrのif分の中のreturn strの型変換に問題がある」と言っているんです。 型変換はしるつもりは無いのにコンパイラはなぜそのように認識するのでしょうか。 またネット答えを探しましたがどうやらこのreturn strの部分はreturn (char*)strが正解のようです。意味がわかりません。strはポインタなのになぜまたわざわざchar型に変換しているのですか?といか(char*)の意味が根本的にわかりません。 質問ばかりですみません。初心者でポインタがどうにも理解できないんです。 誰か詳しい人教えてください。 お願いします。

  • c言語のmalloc関数、またrealloc関数

    c言語のmalloc関数は確保するメモリの領域を、配列としてのみしか処理出来ないのですか。 つまり、malloc関数で確保したメモリの領域を変数、また多次元配列、また構造体としては処理出来ないのでしょうか。 c言語のrealloc関数は以前の確保したメモリの領域から、確保し直したメモリの領域の場所が変わるかもしれないという事ですが、この場合の場所が変わるという意味は、メモリの領域のアドレスが変わるという事でしょうか。 また、以前の確保したメモリの領域に代入していたデータが使用出来なくなるという事でしょうか。

  • C言語 初期化について

    はじめまして。 C言語を学習しております。 【初期化】の意味について混乱しております。 今まで、【初期化】とは下記のような繰り返しのある文に初期値(数え始めの値、下記の例では1)を代入することだと思っていました。 for (i = 1;i <= 10;i++) { printf("メッセージ\n"); } しかし、勉強が進むにつれ、下記のように様々な場面で【初期化】という言葉が出てきたことで、【初期化】の意味がわからなくなりました。 ●【文字変数の配列の初期化】の例 char str[6] = {'M','A','R','I','O'}; ●文字列リテラルを用いた【文字列の初期化】の例。 #include <stdio.h> int main(void) { char str[] = "MARIO"; printf("%s\n",str); return 0; } ●【配列の初期化】の説明 型名 配列名[要素数]={0番の数値,1番の数値,2番の数値,・・・}; ●【配列を初期化】して表示する例 #include <stdio.h> #include <stdio.h> int main(void) { int array[10] = {42,79,13}; printf("array[0] = %d\n",array[0]); printf("array[1] = %d\n",array[1]); printf("array[2] = %d\n",array[2]); printf("array[3] = %d\n",array[3]); printf("array[4] = %d\n",array[4]); return 0; } ●for文の説明 for (初期化;条件式;更新) { 繰り返す文; } 初期化とは、カウント変数の初期化を行うための文です。 ここに書かれた式は、最初に1回だけ実行されます。 【初期化】とは、場面場面で意味が変わるのでしょうか。 どの場面に通じる【初期化】の本来の意味を教えてください。 よろしくお願い致します。