質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.35%

char配列に直接= " ";で代入出来ない理由

解決済

回答 4

投稿

  • 評価
  • クリップ 0
  • VIEW 2,982

score 15

前提・実現したいこと

char配列に直接= " ";で代入出来ない理由は何ででしょうか。

例)
char aaa[16];
aaa = "あいうえお";
// 変更不可能な左辺値

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+3

aaa = "あいうえお";

aaaというのは配列ですんでアドレスの代入はできません。

ってはなしだけど、言語仕様がそうなってるから、ということだと納得しときましょう


C言語で、
char aaa[16]="あいうえお";
がなんで行けるんだ!という方が説明しやすいです。
実はこれは代入という動作はしていません。コンパイル時に解釈を行い、aaaの領域に、文字データを割り当てている、ってことなんですね
つまりー、”あいうえお”のデータを持った領域を定義している、ということで、実行時にはコピー動作は行われてません。

#まあそりゃ実行時にコピー動作を行う処理系もないとは言えませんが

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

aaa = "あいうえお";
// 変更不可能な左辺値

コメントの通りです.aaaは、配列の名称。 Cの仕様に詳しい人からは、正確な説明があるかもしれませんが、char aaa[16] で宣言された 16byte領域の先頭アドレス(固定値)を示します。従って変更する事はできません。

まあ、似たもので char *bbb の bbbはポインタ(アドレスを入れる変数)なので、中身(アドレス)の変更は可能。そして、bbb[2]とかの表現も可能なので、紛らわしいですが。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

+2

C言語の文法で、aaaは配列先頭へのポインタと決まっています。

char aaa[16]; と宣言されたとき、sizeof(aaa)は、
ポインタのサイズである 4 や 8 ではなく、16 です。

"あいうえお" という文字列リテラルに対して、sizeof("あいうえお") は、
文字コードが Shift-JIS だと 11、UTF-8 だと 16 となります。
4 または 8 ではないので、"あいうえお" がアドレスだと主張できません。

ISO/IEC 9899:1999(E)

6.3.2.1 Lvalues, arrays, and function designators

  • An lvalue is an expression with an object type or an incomplete type other
    than void; if an lvalue does not designate an object when it is evaluated,
    the behavior is undefined. When an object is said to have a particular type,
    the type is specified by the lvalue used to designate the object. A modifiable
    lvalue is an lvalue that does not have array type, does not have an incomplete
    type, does not have a const-qualified type, and if it is a structure or union,
    does not have any member (including, recursively, any member or element of all
    contained aggregates or unions) with a const-qualified type.
  • Except when it is the operand of the sizeof operator, the unary & operator,
    the ++ operator, the -- operator, or the left operand of the . operator or an
    assignment operator, an lvalue that does not have array type is converted to
    the value stored in the designated object (and is no longer an lvalue). If the
    lvalue has qualified type, the value has the unqualified version of the type
    of the lvalue; otherwise, the value has the type of the lvalue. If the lvalue
    has an incomplete type and does not have array type, the behavior is undefined.
  • Except when it is the operand of the sizeof operator or the unary & operator,
    or is a string literal used to initialize an array, an expression that has
    type "array of type" is converted to an expression with type "pointer to type"
    that points to the initial element of the array object and is not an lvalue.
    If the array object has register storage class, the behavior is undefined

JIS X3010:2003(ISO/IEC 9899:1999)

6.3.2.1 左辺値,配列及び関数指示子

  • 左辺値(lvalue)は,オブジェクト型,又は void 以外の不完全型をもつ式とする。
    左辺値が評価されたときにオブジェクトを指し示していなければ,動作は未定義とする。
    オブジェクトがもつ型に言及する場合,その型とは,オブジェクトを指し示すために
    用いる左辺値によって指定される型とする。変更可能な左辺値(modifiable lvalue)
    とは,配列型をもたず,不完全型をもたず, const 修飾型をもたない左辺値とし,
    それが構造体又は共用体の場合,const 修飾型のメンバ(再帰的に包含されている
    すべての集成体又は共用体の任意のメンバ又は要素を含めて)をもたないものとする。
  • 左辺値が sizeof演算子,単項&演算子,++演算子若しくは--演算子のオペランド,
    又は,.演算子若しくは代入演算子の左側のオペランドである場合を除いて,配列型以
    外の左辺値は,指し示されたオブジェクトが格納する値に変換する(そして,それは
    もはや左辺値ではない。)。左辺値が修飾型をもつ場合,その値は左辺値の型の非修
    飾版をもつ。そうでない場合,その値は左辺値の型をもつ。左辺値が不完全型をもち,
    配列型以外の型をもつ場合,その動作は未定義とする。
  • 左辺値が sizeof 演算子のオペランド,単項&演算子のオペランド,又は文字配列を
    初期化するのに使われる文字列リテラルである場合を除いて,型“~型の配列”をもつ
    式は,型“~型へのポインタ”の式に型変換する。それは配列オブジェクトの先頭の
    要素を指し,左辺値ではない。配列オブジェクトがレジスタ記憶域クラスをもつ場合,
    その動作は未定義とする。

char aaa[16]; と宣言された aaa は配列型であり、オブジェクト型です。
したがって、式の中では左辺値として扱われます。
しかし、配列型をもつので、「変更可能な左辺値」ではありません。
これが、aaa = "あいうえお"; がエラーになる理由です。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/11 13:25

    おお、sizeof(aaa)は失念してました。ポインタではなく配列として扱われる例外ですね。

    引用によると、配列型については3番めのパラグラフに記載されていますね。
    ①sizeofのオペランド、②&演算子のオペランド、③文字配列を初期化する文字列リテラル、の3つを除いて配列型はポインタ型として処理されると記載されています。
    aaa="あいうえお";
    のaaaは明らかに3つの例外に該当しない(sizeofのオペランドでも&のオペランドでも文字列リテラルでもない)ので、ポインタとして処理されます。

    ところで、例外の③については良くわからんですが、話題から外れまくるので省略します。

    キャンセル

checkベストアンサー

+1

こんにちは。

C言語の文法で、aaaは配列先頭へのポインタと決まっています。
しかも、この場合そのポイント先を変更すると元々の16要素の配列と違う領域を指すことになるので混乱しやすいと思います。だからと思いますが、この場合のaaaのポイント先は変更できないと決まっているようです。
したがって、変更しようとすると「変更不可能」というエラーになります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2019/08/11 05:29

    そうでした。y_waiwaiさんが言うのも含め宣言をした後の配列名は配列の先頭ポインタを指すんでしたね。ありがとうございます。😃

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る