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

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

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

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

Q&A

解決済

3回答

856閲覧

JIS X 3010:2003 6.5.16.1 単純代入 例3 制約違反

tails

総合スコア22

C

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

0グッド

0クリップ

投稿2020/06/14 02:24

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ページで確認できます。

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

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

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

guest

回答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 *
charconst char は適合する型ですが、
右オペランドの型修飾子 const を左オペランドは持っていないので制約違反。

ccp = &c; では、ccp の型が const char *で、&c の型が char *
const charchar は適合する型ですが、
右オペランドには型修飾子がないので制約違反になりません。

追記
最初の質問の 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
kazuma-s

総合スコア8224

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

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

tails

2020/06/16 00:29

なるほど! とても分かりやすかったです。 ありがとうございます。 ところで、 char と const char は、適合する型、ではなく、適合する型の修飾版又は非修飾版 ではないでしょうか。
guest

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

angel_p_57

総合スコア1681

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

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

tails

2020/06/16 00:31

kazuma-s さんの説明で分かりました。 ありがとうございました。 「適合する型の修飾版又は非修飾版へのポインタ」というところが、肝心でした!
guest

0

const char** にchar** を入れようとしています

#まあ、Cではワーニングが出る程度ですね

投稿2020/06/14 02:42

編集2020/06/14 02:44
y_waiwai

総合スコア88051

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

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

tails

2020/06/16 00:31

ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問