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

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

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

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

Q&A

解決済

4回答

2521閲覧

!(否定)の処理の仕方が分かりません

Sota2021

総合スコア6

C

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

Linux

Linuxは、Unixをベースにして開発されたオペレーティングシステムです。日本では「リナックス」と呼ばれています。 主にWebサーバやDNSサーバ、イントラネットなどのサーバ用OSとして利用されています。 上位500のスーパーコンピュータの90%以上はLinuxを使用しています。 携帯端末用のプラットフォームAndroidは、Linuxカーネル上に構築されています。

Ubuntu

Ubuntuは、Debian GNU/Linuxを基盤としたフリーのオペレーティングシステムです。

コマンド

コマンドとは特定のタスクを行う為に、コンピュータープログラムへ提示する指示文です。多くの場合、コマンドはShellやcmdようなコマンドラインインターフェイスに対する指示文を指します。

0グッド

0クリップ

投稿2021/09/28 21:00

UbuntuでのTerminal画面です。
・1つ目のprintfまでのコマンドに関して
a%2 = 1 (15/2の余り1)と解釈したのですが、!の式が理解できません。調べると否定の意味を持つとあったのですが、具体的にそういう処理をしてc=1になったのか教えていただきたいです。
・2つ目のprintfまでのコマンドに関して
c = a>b = 2>5 これは偽なのでb++ の処理が行われ、a=2,b=6 が出力されることは分かるのですが、これも元々の c=15 から c=5になる過程がよくわかりません。
・3つ目のprintfまでのコマンドに関して
b = 4/3cc = 4/311 = 4/3 だと思うのですが、そのあとの a = b = !a の処理がよくわかりません。
質問が多くて申し訳ありません。どなたかご教授いただけると幸いです。イメージ説明

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

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

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

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

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

int32_t

2021/09/28 23:12

コードや実行結果は画像ではなくテキストとして書き込んでください。
fana

2021/09/29 02:04

そもそもこのコードは何なの? っていう… 本か何かの「次のコードでどんな結果が表示されるのか考えてみよう!」的な何かなのだとしたら, 考えるのに必要な文法の説明が事前にあるのではないかと思うのですが.
Sota2021

2021/09/29 06:03

テキストの方がよいですね、次回からそうします!
guest

回答4

0

ベストアンサー

「演算子」は、C言語においては「1~3個の値を処理して、1つの値を返す」ものです。

・1つ目のprintfまでのコマンドに関して

<略> !の式が理解できません。調べると否定の意味を持つとあった

プログラムをよく見てください。(a!=b)です。!ではなく、!=で一つの演算子です。!=は、演算子の左辺と右辺の値が異なればint型の1を、等しければ0を返します。もちろん、字面としては==との対比で「等しいことの否定」を意図はしているでしょうけれど。

2つ目
三項演算子は、その言葉のとおり3つの項を処理し、一つの値を返します。
a>b ? ++a : b++
まずa>bを調べ、
その値が真(0以外)であったら ++aを評価(計算を実行)して結果の値を
その値が偽(0)であったら b++を評価して結果の値を
返します。
aが2、bが5の場合であれば、
a>bは偽なので、
b++ (式の値としてはbを返した後、bの値を1増加する)
で、つまり(a>b ? ++a : b++)の値は5、これがCに代入され、
またbの値は6になっています。

3つ目
カンマ演算子は、,の左側の式、右側の式を順次評価し、右側の式の値を返す演算子です。
また、=は代入の演算子で、右辺の値を左辺の変数に代入するとともに、左辺に代入された値を返します(int a;に対してa=1.5などとすると式の値は1になる)。
b=4/3*c*c, a=b=!a
まずb=4/3ccを評価して4/3ccを計算して結果をbに代入します。
つぎにa=b=!aでは、=は右辺から先に処理されますから、まずb=!aで、!は(これは単独の!)否定の演算子、!に続く値が真(0以外)なら偽(0)を、偽なら真(1)を返し、これbに代入してその値を返します(真偽の判断のときには0以外を真としますが、返す値の真偽では1が真です。ときどき「0以外の不定の値を返す」と勘違いしている人もいます)。
aは2、これは0以外なので、!aは0、これをbに代入してb=!aは0を返し、a=(b=!a)で式全体も0を返しますが、これを受け取る人は誰もいないので捨てられておわり、です。結局aとbは0になって、cの値は変わらず、ですね。

投稿2021/09/28 23:16

編集2021/09/29 13:13
thkana

総合スコア7703

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

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

dodox86

2021/09/28 23:37

> 独立した!があるわけではありません。 いえ、論理否定の演算子として!が独立して使えます。 https://docs.microsoft.com/ja-jp/cpp/c-language/unary-arithmetic-operators?view=msvc-160 ドラフトですが: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf > 6.5.3.3 Unary arithmetic operators > The result of the logical negation operator ! is 0 if the value of its operand compares > unequal to 0, 1 if the value of its operand compares equal to 0. The result has type int. > The expression !E is equivalent to (0==E).
thkana

2021/09/28 23:48

「そのプログラムに書かれているのは、!=であって!じゃないよ」という話をしたかったのですが文章が良くなかったですね。 (指摘のように読めるかなとも思ったけど論理否定は3つめで登場してるしわかるかな、と甘えてしまいました) ちょっと直しましょう。
dodox86

2021/09/28 23:55

ああ、やはり。thkanaさんの回答にしては何かおかしいと思いました。(コメントも実は少し躊躇したのです)
thkana

2021/09/29 00:00

いえいえ、「よりよい回答」とすることができましたので。御指摘ありがとうございました。
dodox86

2021/09/29 00:07

ご回答に対する指摘ではありません: 問題自体、論理演算の結果を整数として扱い続けているところが気になりますね。偽(false)=0はまだ良いとして、評価結果が真(true)=1を前提としているとしたら初学者の誤解を招きそうです。コンパイラ実装依存、でしょうか。
thkana

2021/09/29 00:20

> 論理演算の結果を整数として扱い続けているところが気になりますね それは問題ないのでは? 軟弱にJISX3010で見みすが 6.5.3.3 単項算術演算子 より --- 論理否定演算子!の結果は,そのオペランドの値が0と比較して等しくない場合0とし,等しい場合1とする。結果の型は,intとする。 --- 網羅的にチェックはしていませんが、他の比較・論理演算子も同様の定義(int型の1/0を返す)になっています。実装依存の余地はないと思います。
dodox86

2021/09/29 01:02

Zuishinさん、thkanaさん、レスをいただきどうもありがとうございます。 ご指摘のとおりですね。知らなかったか、完全に失念しておりました。 (レスを受けて思いましたが、、teratailの過去回答でその話題が挙がった気がします) JISX3010のご提示もありがとうございます。頭に焼き付けておきます。何かに使えそう。
otn

2021/09/29 03:23

カンマ演算子は、代入演算子より結合度が低い(優先順位が低い)ので、3つめの説明は間違ってます。 今回はbがカンマの後で上書きされるので、たまたま同じ結果ですが。
Sota2021

2021/09/29 06:04

すごくわかりやすかったです!皆さんご指摘・ご回答ありがとうございました!
thkana

2021/09/29 13:08

otnさん 修正しました。 間違えておいていうのもナンですが、考え方を間違えたら違う答えが出る設問にすればいいのに...などと思ってしまう問題ですね。
guest

0

C言語としては、論理型ってのはなく、論理値ってのは、ぶっちゃけ整数の0(偽)か1(真)です
そういうことでその計算式を見ればわかるかと

#んで、整数の0は偽、それ以外は真と判断されます

投稿2021/09/28 22:02

y_waiwai

総合スコア88042

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

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

Sota2021

2021/09/29 06:04

なるほど、ご回答ありがとうございました!
kazuma-s

2021/09/29 07:47

C99から論理型が追加されました。 _Bool というキーワードがあり、_Bool型のオブジェクトを宣言できます。 規格書を見てください。
y_waiwai

2021/09/29 07:53

で、それはintとは互換はないんでしょうか。 そのまま代入するときにエラーが出る、ってならいいんですが。
Zuishin

2021/09/29 08:01

https://www.wdic.org/w/TECH/_Bool _Bool には 0 か 1 しか入りません。これを int と互換性があるというなら、double と int も互換性があるということになってしまいます。 互換性はともかく、0 か 1 しか入らない論理型が C99(20 年以上前の規格)から新設されているので、 > C言語としては、論理型ってのはなく、 というのは誤りと言えます。
y_waiwai

2021/09/29 08:03

まあ、早い話が新しい整数型として_Boolが新設されたって話ですね
guest

0

int a=15, b=15, c=15;
c = (a%2) + (a!=b);

c = (aを2で割った余り) + (a!=b ならば 1, さもなくば 0) なので
c = 1 + 0
c = 1

int a=2, b=5, c=15;
c = a>b ? ++a : b++;

c = (a>b ならば ++a, さもなくば b++); なので
c = b++;
c = b; b = b+1;

int a=2, b=15, c=1;
b = 4/3cc; a=b=!a;

b = 4/3/cc; a = (b= !a);
b = 4/3/c
c; a = (b= (a が 0 ならば 1, さもなくば 0)); なので
b = 4/311; a = (b= 0);
※ 代入式 b = 0 の値はその右辺と等しく 0

投稿2021/09/28 21:39

episteme

総合スコア16612

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

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

thkana

2021/09/28 23:32

> b = 4/3*c*c; a=b=!a; 真ん中が;じゃなくて,なのが「出題」としてはミソなのではないでしょうか。
fana

2021/09/29 01:59

; でも , でも結果が変わらないなら,何も考えられていないような気もします. ( , とすることに意味があるなら,何かしら ; の場合とは結果が変わる記述にするんじゃないかな?と)
guest

0

a%2 = 1 (15/2の余り1)と解釈したのですが、!の式が理解できません。

!の式は否定を意味します。if(a != b)のようにするとaとbの値が違う時のみ中に入るという式になります。得られる数字は0か1なので、今回の式では0が返却され、%2の答えである1がそのまま答えになっています。

c=15 から c=5になる過程がよくわかりません。

C言語の仕様で++aa++の処理には下記のような明確な違いがあります。

  • 前に++をつけることは、処理した後に+=1が実行される
  • 後に++をつけることは、処理する前に+=1が実行される

今回の場合三項演算子の式が処理にあたるので、元のbの数字がcに入るような式になっています。

そのあとの a = b = !a の処理がよくわかりません。

int型のaを否定している、つまりTrueかFalseの答えになります。
int型の場合1以外は全部False扱いになっていたはずなので、False(0)が入っているのかと思われます。

※全体的にこのプログラムは私自身、あまり見たことない書き方です。実務でやると怒られるのでやめましょう。

投稿2021/09/28 21:26

stdio

総合スコア3307

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

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

Zuishin

2021/09/28 21:35

> int型の場合1以外は全部False扱いになっていたはずなので、False(0)が入っているのかと思われます。 a が 2 の場合、!a は何になりますか?
thkana

2021/09/28 23:19

プリ/ポストインクリメントも逆じゃない?
dodox86

2021/09/28 23:40

> int型の場合1以外は全部False扱いになっていたはずなので、False(0)が入っているのかと思われます。 他回答者さんの回答にもありますが、そうではなく、0が偽(False)で、非0が真(True)ですね。C言語自体の仕様としてそうです。 #define FALSE 0 #define TRUE 1 のようなマクロがあったりするので、それとの混同でしょうか。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問