JIS X 3010:2003 6.5.16.1
の例3.に、
C
1const char **cpp; 2char *p; 3const char c = 'A'; 4 5cpp = &p; // 制約違反 6*cpp = &c; // 正しい 7*p = 0; // 正しい
として制約違反のコードが載っていますが、制約違反とされている行がなぜ制約違反なのかが分かりません。
どの制約に、どのように違反しているのか教えて下さい。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答3件
0
ベストアンサー
JIS X3010:2003 (ISO/IEC9899:1999)
6.5.16.1 単純代入
制約 次のいずれかの条件が成立しなければならない(93)。
- 左オペランドの型が算術型の修飾版又は非修飾版であり,
かつ右オペランドの型が算術型である。 - 左オペランドの型が右オペランドの型に適合する構造体型
又は共用体型の修飾版又は非修飾版である。 - 両オペランドが適合する型の修飾版又は非修飾版へのポインタであり,かつ左
オペランドで指される型が右オペランドで指される型の型修飾子をすべてもつ。 - 一方のオペランドがオブジェクト型又は不完全型へのポインタであり,
かつ他方が void の修飾版又は非修飾版へのポインタである。さらに,左オペ
ランドで指される型が,右オペランドで指される型の型修飾子をすべてもつ。 - 左オペランドがポインタであり,かつ右オペランドが空ポインタ定数である。
- 左オペランドの型が_Bool 型であり,かつ右オペランドがポインタである。
意味規則 単純代入(simple assignment) (=) は,右オペランドの値を代入式の
型に型変換し,左オペランドで指し示されるオブジェクトに格納されている値を
この値で置き換える。
オブジェクトに格納されている値を,何らかの形でそのオブジェクトの記憶域に
重なる他のオブジェクトを通してアクセスする場合,重なりは完全に一致して
いなければならない。さらに,二つのオブジェクトの型は,適合する型の修飾版
又は非修飾版でなければならない。そうでない場合,動作は未定義とする。
cpp = &p; では、cpp の型が const char **
で、&p の型が char **
。
const char *
と char *
は適合しない型なので制約違反。
逆を考えてみましょう。
C
1 char **pp; 2 const char *cp; 3 pp = &cp; // 制約違反
pp = &cp; では、pp の型が char **
で、&cp の型が const char **
。
char *
と const char *
は適合しない型なので制約違反。
疑問に思ったのは次の例と混同しているからではないでしょうか?
C
1 char *cp; 2 const char cc = 'A'; 3 const char *ccp; 4 char c = 'B'; 5 6 cp = &cc; // [char *] = [const char *] 制約違反 7 ccp = &c; // [const char *] = [char *] 正しい
cp = &cc; では、cp の型が char *
で、&cc の型が const char *
。
char
と const char
は適合する型ですが、
右オペランドの型修飾子 const を左オペランドは持っていないので制約違反。
ccp = &c; では、ccp の型が const char *
で、&c の型が char *
。
const char
と char
は適合する型ですが、
右オペランドには型修飾子がないので制約違反になりません。
追記
最初の質問の cpp = &p;
を制約違反にしないと次のような不具合が発生します。
C
1#include <stdio.h> 2 3int main(void) 4{ 5 const char **cpp; 6 char *p; 7 const char c = 'A'; 8 9 cpp = &p; // [const char **] = [char **] 制約違反でないとすると 10 *cpp = &c; // [const char *] = [const char *] 正しい 11 *p = 'B'; // [char] = [int] 正しい 12 printf("c = '%c'\n", c); // const char である c が変更されてしまう 13}
追記2
char と const char は、適合する型、ではなく、適合する型の修飾版又は非修飾版 ではないでしょうか。
おっしゃる通りですね。const char
は、char
の修飾版です。
さらに、補足説明させていただきますと、
「const char *
と char *
は適合しない型なので制約違反。」と書いたところは、
char *
の修飾版は、char *const
であって、const char *
ではない、
ということによります。
また、「*p = 'B'; // [char] = [int] 正しい」と書きましたが、
C では、'B' は char ではなく、int です。
代入演算子の左オペランドの char も右オペランドの int も算術型です。
算術型の代入には適合する型という制約がありません。
意味規則で、「右オペランドの値を代入式の値に型変換し」とあるので
適合する型になり「正しい」という結論になります。
投稿2020/06/14 14:13
編集2020/06/16 01:05総合スコア8224
0
const T *cp; T v; cp=&v;
が大丈夫なので const char **cpp; char *p; cpp=&p;
も大丈夫に見えてしまうかも知れませんが、
T const *cp; T v; cp=&v;
が大丈夫、という形で認識していれば、
char *const *cpp; char *p; cpp=&p;
は大丈夫 (T
の部分をchar *
に置き換える )char const **cpp; char *p; cpp=&p;
は形が違う
と見ることができます。
※それはそれとして、const char **cpp; const char *cp; cpp=&cp;
はもちろん大丈夫です。
投稿2020/06/14 07:31
総合スコア1681
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
const char** にchar** を入れようとしています
#まあ、Cではワーニングが出る程度ですね
投稿2020/06/14 02:42
編集2020/06/14 02:44総合スコア88051
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/06/16 00:29