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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

8898閲覧

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

B.E.

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2019/08/10 14:38

前提・実現したいこと

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

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

yohhoy👍を押しています

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

aaa = "あいうえお";

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

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


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

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

投稿2019/08/10 14:43

編集2019/08/10 14:52
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

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 00:00

kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2019/08/11 04:25

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

0

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

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

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

投稿2019/08/10 14:46

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

こんにちは。

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

投稿2019/08/10 14:48

Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

B.E.

2019/08/10 20:29

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問