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

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

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

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

Q&A

解決済

3回答

490閲覧

C言語の規格(JIS X3010:2003)での疑問

tails

総合スコア22

C

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

1グッド

1クリップ

投稿2020/06/11 07:32

今やっていること

JIS X3010 : 2003 を読んでいます。

疑問

JIS X3010 : 2003 p.28 より引用

ビットフィールド以外のオブジェクト(unsigned char 型以外の型をもつ)に格納した値は、nをこの型のオブジェクトのバイト単位の大きさとして、n×CHAR_BIT個のビットで表す。この値をunsigned char [n]型のオブジェクトに(例えば, memcpy を用いて)コピーすることができる。コピーした結果のバイトの集合を, この値のオブジェクト表現(object representation)と呼ぶ。(中略)NaNを除き,同じオブジェクト表現をもつ二つの値の比較の結果は等しい。

このような記載から、オブジェクト表現(ビットの列)が同じであれば == 演算子の比較結果は1を返すと解釈したため、以下のプログラムの実行で(assertにかからなければ) equal が表示されるのではないかと考えましたが、そのようにはなりません。(equal は表示されず、finish で終了します)
私の解釈は、どのように間違えていますか。
よろしくお願いします。

該当のソースコード

C

1#include <assert.h> 2#include <memory.h> 3#include <stdio.h> 4 5#define SIZE sizeof(int) 6 7int main(void) { 8 static_assert((sizeof(int) == sizeof(float)), 9 "Required sizeof(int)==sizeof(float)"); 10 int i = 0b01000000010101010101010101010101; 11 // 0'10000000'10101010101010101010101 12 // 符号部'指数部'仮数部 13 float f; 14 15 // そのままコピー 16 memcpy(&f, &i, SIZE); 17 18 // 全然違う値であることを表示 19 printf("%d %f\n", i, f); 20 21 // ビット列は確かに同じであることをチェック 22 { 23 unsigned char rep_i[SIZE]; 24 unsigned char rep_f[SIZE]; 25 memcpy(rep_i, &i, SIZE); 26 memcpy(rep_f, &f, SIZE); 27 for (size_t index = 0; index < SIZE; ++index) { 28 assert(rep_i[index] == rep_f[index]); 29 } 30 } 31 32 // ビット列が同じ = オブジェクト表現が同じ なはずなのに? 33 if (f == i) { 34 puts("equal"); 35 } 36 37 puts("finish"); 38}
ozwk👍を押しています

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

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

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

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

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

guest

回答3

0

JIS X 3010:2003 (ISO/IEC 9899:1999)

6.3.1.8 通常の算術型変換  算術型のオペランドをもつ多くの演算子は,同じ方法でオペランドの型変換を 行い,結果の型を決める。型変換は,オペランドと結果の共通の実数型(common real type)を決めるために行う。与えられたオペランドに対し,それぞれの オペランドは,型領域を変えることなく,共通の実数型を対応する実数型とする 型に変換する。この規格で明示的に異なる規定を行わない限り,結果の対応する 実数型も,この共通の実数型とし,その型領域は,オペランドの型領域が一致 していればその型領域とし,一致していなければ複素数型とする。これを通常の 算術型変換(usual arithmetic conversion)と呼ぶ。 通常の算術型変換の規則は,次による。   まず,一方のオペランドの対応する実数型が long double ならば,他方の  オペランドを,型領域を変えることなく,変換後の型に対応する実数型が  long double となるように型変換する。   そうでない場合,一方のオペランドの対応する実数型が double ならば,  他方のオペランドを,型領域を変えることなく,変換後の型に対応する実数型が  double となるように型変換する(51)。   そうでない場合,一方のオペランドの対応する実数型が float ならば,他方の  オペランドを,型領域を変えることなく,変換後の型に対応する実数型が  float となるように型変換する。

最後の規則により、if (f == i) { の i は float に型変換されます。
型変換後のビットパターンは元の i のビットパターンとは異なります。
すなわち f のビットパターンとも異なります。

投稿2020/06/11 15:33

kazuma-s

総合スコア8224

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

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

tails

2020/06/12 04:06

こちらの説が正しいように思いました。
guest

0

ベストアンサー

オブジェクト表現は型に依存したものです。型が異なれば、同じビット列が意味する値は異なってきます。

投稿2020/06/11 08:04

maisumakun

総合スコア145184

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

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

maisumakun

2020/06/11 08:05

例えばfloatの側に「2.5」という値が入っていたとすれば、これはそもそもintの値域に存在しない値ですから、等しくなる余地がありません。
tails

2020/06/11 08:23

オブジェクト表現が型にも依存する、というのはどのあたりから読み取れますか? > コピーした結果のバイトの集合を, この値のオブジェクト表現と呼ぶ ということから、 (例えば) int型の値 1079334229 のオブジェクト表現は、{64,85,85} float型の値 3.3333333 のオブジェクト表現は、{64,85,85} となり、集合として等しい(正確には順序付きのバイト列としての等しさが必要だと思いますが)ので、「比較の結果は等しい」と考えましたが。 あるオブジェクト表現によってあらわされる"値"は型に依存するのは分かります。 「同じ型の同じオブジェクト表現をもつ二つの値の比較の結果は等しい」とあれば分かるのですが…
maisumakun

2020/06/11 08:25

「値」自体の定義として「オブジェクトが特定の型をもっていると解釈する場合のオブジェクトの内容の厳密な意味。」と与えられています。つまり、型から遊離した値は存在しません。
tails

2020/06/11 08:26

なるほど!! 納得しました。 ありがとうございました!
guest

0

NaNを除き,同じオブジェクト表現をもつ二つの値の比較の結果は等しい。

これがぽいんとです。
int とfloat は同じ表現ではありません

投稿2020/06/11 07:44

y_waiwai

総合スコア87774

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

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

y_waiwai

2020/06/11 12:03

うーん、 ・intとfloatは同じ表現である! ・イコールにならないのは他の原因である! どっちなんだろう。。
tails

2020/06/12 04:03

考え直してみると、やはりオブジェクト表現自体は型に依存しないと思いました。 バイト列 をオブジェクト表現とするということで良いかと思います。 「同じオブジェクト表現をもつ二つの値の比較」という表現が == 演算子のことを意味しているとすると、kazuma-s さんが仰っているように "通常の算術型変換" によってオブジェクト表現が変わって、等価でないとされるのかもしれません。 == 演算子自体が両オペランドに対して(複素数型は置いておいて)同じ型を要求する変換「通常の算術型変換」を事前に必要とするので、そのオブジェクト表現の比較においては、前提として「同じ型」があるのだと思いました。
y_waiwai

2020/06/12 06:59

そのオブジェクトの表現なんだから、オブジェクトの型やら属性でかわるもんでしょ。 わざわざそこには同じオブジェクト表現、と書いてあるんだからそこらへんは揃えないと比較はできないって話ですわな。 至極当たり前の話だとおもいますが。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問