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

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

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

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

Q&A

解決済

1回答

1233閲覧

int a=-3のような変数の宣言の「-」は単項算術演算子-ですか?

abustoy

総合スコア12

C

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

0グッド

0クリップ

投稿2021/07/29 07:48

質問は下のソースコードにコメントに記述させていただきました。しかし、読みづらいのでここにも改めて記述いたします。

// この行のように、変数宣言の際の-は「単項算術演算子」ですか?それとも、別物ですか?

/* また、xとbの内部ビットは同じですか?(両方とも
11111111111111111111111111111101
ですか?)*/

/* xとbの内部ビットが同じ場合、コンピュータは
int b=-3;
という記述から、どういう順序でbの内部ビットを決めているのでしょうか?

// このことは今回の質問と直接関係ないのですが、上のxはunsigned int型なのに-3という負の値をもってます。このことに違和感を感じています。

該当のソースコード

c言語

1// 前提 私の処理系では「符号つき整数の内部表現は2の補数表現を使っている」とします。またsizeof(int)..4とします 2 3# include <stdio.h> 4 5int main(void) 6{ 7 unsigned int a=3; 8 unsigned int x; 9 x=-a; 10 // この行の-はaをオペランドにもつ「単項算術演算子」ですよね 11 12 /* 2の補数表現よりxの内部ビットは 13 11111111111111111111111111111101 14 である*/ 15 16 int b=-3; 17 // この行のように、変数宣言の際の-は「単項算術演算子」ですか?それとも、別物ですか? 18 19 /* また、xとbの内部ビットは同じですか?(両方とも 20 11111111111111111111111111111101 21 ですか?)*/ 22 23 /* xとbの内部ビットが同じ場合、コンピュータは 24 int b=-3; 25 という記述から、どういう順序でbの内部ビットを決めているのでしょうか? 26 私は、 27 no1 3という記述を、符号なし整数3と認識して、 28 00000000000000000000000000000011 29 というビット列を考える 30 no2 -を単項算術演算子(最初にかいた質問の記述の 31 ように別物かもしれませんが、同じく2の補数に変換する作用をして)と認識して、 32 11111111111111111111111111111101 33 というビット列をbの内部ビットとする 34 というように決めていると予想しました。*/ 35 36 37 // このことは今回の質問と直接関係ないのですが、上のxはunsigned int型なのに-3という負の値をもってます。このことに違和感を感じています。 38 39return 0; 40} 41

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

cygwinでgccコンパイラを使用しております

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

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

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

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

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

ockeghem

2021/07/29 07:59

ソースコードの出典を追記するべきだと思います。このままでは無断転載となり、著作権侵害になります。出典を明記することは、引用の要件を満たすために必要です。他の質問では明記されていますが、ここでもそれをすべきです。
abustoy

2021/07/29 08:07

ご指摘ありがとうございます。すみません、ソースコードはすべて自分で書いた(作成した)ものです。私のこの返答が見当違いでありましたら恐れ多いですがまたご指摘いただきたいです。
ockeghem

2021/07/29 08:17

別の質問に柴田望洋氏のソースを引用されていたので混同したようです。大変失礼しました。
abustoy

2021/07/29 08:29

いえ、閲覧してくださりありがとうございます。
guest

回答1

0

ベストアンサー

この行のように、変数宣言の際の-は「単項算術演算子」ですか?それとも、別物ですか?

はい、単項算術演算子です。C言語には負の整数リテラルはなく、-3は常に「整数の3に対して単項マイナスが適用されたもの」と解釈されます。

とbの内部ビットは同じですか?

(あくまで規約上は)C言語の負の数は「2の補数表現」以外に「1の補数表現」や「符号+絶対値表現」を採用しても構わないことになっています。そのような処理系では、当然ビット列として一致はしません。

投稿2021/07/29 07:55

maisumakun

総合スコア146018

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

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

maisumakun

2021/07/29 07:57 編集

> 上のxはunsigned int型なのに-3という負の値をもってます。 持っていません。unsignedに代入した時点で、「最大値+1」を法とした剰余を取る処理が行われます(こちらは負数の処理体系によらず同じ動作となることが保証されています)。
maisumakun

2021/07/29 08:05

> どういう順序でbの内部ビットを決めているのでしょうか? それを何のために理解する必要があるのでしょうか?把握すべき理由によって、検討すべき箇所は異なってきます。 Cコンパイラは結果さえ同じであればかなりの範囲で最適化が許されていますので、「どこでも使われないbという変数がまるごと消滅した」となっている可能性も大いにありえます。
abustoy

2021/07/29 08:21

ご回答ありがとうございます。> 上のxはunsigned int型なのに-3という負の値をもってます。へのご回答について確認させてください。 私の使っているようなint型が4バイト(32bit)の処理系ではunsignd int型の最大値が4294967295(=2^32 - 1)(これがご回答の中の最大値ですよね)なので、4294967295+1=4294967296を法とした剰余 である「4294967293」がxの持つ値である、という理解で正しいですか?
maisumakun

2021/07/29 08:25 編集

はい、そのとおりです。 2の補数であれば、同じ幅の符号付き整数からの変換は「ビットパターンをそのままunsignedとして再解釈したもの」と同じになります。
abustoy

2021/07/29 08:28

続きです。私が「xはunsigned int型なのに-3という負の値をもってます。」と考えたのは、下のようにprintf関数の変換指定子で%dを指定してxを引数に持たせると、-3が画面に表示されたからです。 printf("%d",x); 変換指定子の理解ができていないのだと思いますので、よければ変換指定子の意味についても教えていただきたいです。
maisumakun

2021/07/29 08:30

> printf関数の変換指定子で%dを指定してxを引数に持たせると、-3が画面に表示されたからです。 型と一致しない変換指定子を書いた場合の動作は未定義です。 (現実的には、intとunsignedでは幅が同じなので、unsignedのビットパターンを「intと再解釈して」出力する形になるかとは思います)
abustoy

2021/07/29 09:00

17:30のご回答に対して 「型と一致しない変換指定子を書いた場合の動作は未定義」であることを教えていただけて本当に良かったです。これでxが-3を持っていないことがしっかり理解できました。 > どういう順序でbの内部ビットを決めているのでしょうか? へのご回答についてです。 知りたい理由は改めて考えると、わかりませんでした(少なくとも言葉にできなかったです)ので忘れてください。
abustoy

2021/07/29 09:17

ここまで丁寧に長く質問に答えてくださりありがとうございます。 > 上のxはunsigned int型なのに-3という負の値をもってます。 へのご回答と この行のように、変数宣言の際の-は「単項算術演算子」ですか?それとも、別物ですか? へのご回答は理解いたしました。 他のご回答について新たな疑問が出てきましたので、一度整理したものをまたteratailに投稿いたします。その際また、助けていただけるのであれば、幸いです。 ここまでありがとうございました。
SaitoAtsushi

2021/07/29 15:24

> 「最大値+1」を法とした剰余を取る処理が行われます 言語仕様をあらためて確認してみたところこの規則は型変換後の型が符号無し整数であるときのものです。 単項演算子 - が unsigned int を受け取ったときには unsigned int が返されるだけなので、ここに型変換は介在していません。 演算の結果が演算の結果の型で表現できないときの値は未定義というのが言語仕様に対して厳密な解釈ではないでしょうか? つまり例にあてはめると x の値について言語仕様による保証はなく、質問者が意図している結果を導くには x=-(long long int)a; とでも書くのが妥当なように思われます。
abustoy

2021/07/29 15:42

SaitoAtsushi様 ご回答ありがとうございます。「この規則は型変換後の型が符号無し整数であるときのものです。」について、例えば int a=-3; unsigned int b=(unsigned int)a; という記述の時に「「最大値+1」を法とした剰余を取る処理」が行われるということですよね。 言語仕様というのは、どこで確認できるのでしょうか?宜しければリンク等あれば、教えていただきませんか?全然みつけられなくて…
SaitoAtsushi

2021/07/29 16:33

国際的に公的なものは ISO/IEC 9899 として定められていて日本円でいうと二万数千円で購入することができます。 https://www.iso.org/standard/74528.html ただ結構な高額ですから言語ユーザーの誰もがこれを買うことは当然期待できませんし、規格として承認される直前の草案 (ドラフト) は無料で利用できるようになっているので、これを参照している人が多いと思います。 (わずかなミススペルなどの修正を除けば内容自体はおおよそ最終的な規格と差はないようです。) http://www.open-std.org/jtc1/sc22/wg14/www/projects 日本産業規格としても JISX3010 が定められていてこちらは日本語なので読むのが楽なのですが ISO の規格の改定に追従できていないので最新仕様を見るには適切ではないかもしれません。
SaitoAtsushi

2021/07/29 16:52

すいません、もっとよく確認したところ別のところにちゃんと記述がありました。 項目 6.2.5 の規則が適用されるので質問の例の場合にもちゃんと保証があります。
abustoy

2021/07/30 02:12

わざわざお調べいただいてありがとうございます。jisx3010の方も検索するといくつか翻訳しているサイトが見つかりました。教えていただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問