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

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

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

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

3215閲覧

サンプルプログラムの内部の動作で知りたい点があります

tada_tadaa

総合スコア111

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2016/04/17 08:11

編集2016/04/17 08:16

お世話になっております。
現在「独習C++」という本を読んでいるのですが、サンプルプログラムで知りたい点が
あったので質問することにしました。
↓サンプルプログラム

c++

1#include <iostream> 2using namespace std; 3 4int rotate(int i); 5long rotate(long i); 6 7int main() 8{ 9 int a; 10 long b; 11 12 a = 0x8000; 13 b = 8; 14 cout << rotate(a); 15 cout << "\n"; 16 cout << rotate(b); 17 18 return 0; 19} 20 21int rotate(int i) 22{ 23 int x; 24 25 if(i & 0x8000) x = 1; 26 else x = 0; 27 28 i = i << 1; 29 i += x; 30 31 return i; 32} 33 34long rotate(long i) 35{ 36 int x; 37 38 if(i & 0x80000000) x = 1; 39 else x = 0; 40 41 i = i << 1; 42 i += x; 43 44 return i; 45}

if(i & 0x8000) x = 1; の部分ですが、変数i と16進数8000をAND演算子?の&で
比較していますが、これは内部の処理は
i 1000 0000 0000 0000
16進数の数 1000 0000 0000 0000
ANDの結果 1000 0000 0000 0000
になってるという理解で正しいのでしょうか?

またif(i & 0x80000000) x = 1;の部分は
i 0000 0000 0000 0000 0000 0000 0000 1000
16進数の数 1000 0000 0000 0000 0000 0000 0000 0000
ANDの結果 0000 0000 0000 0000 0000 0000 0000 0000
になってるという理解で正しいのでしょうか?

なんだか頭がこんがらがってすっきりさせたいです。
お手数をおかけしますがよろしくお願いいたします。

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

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

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

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

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

guest

回答2

0

動作の解説は既に他の回答にあるとおりと思います。
質問文にあるコードを書き換えて、ビットがずれていく様子がわかりやすくなるようにしてみました。

a.cpp

c++

1#include <iostream> 2#include <iomanip> 3 4using namespace std; 5 6int rotate(int i); 7long rotate(long i); 8 9int main() 10{ 11 int a; 12 long b; 13 14 a = 1; 15 b = 1; 16 for (int i = 1; i <= 64; i++) { 17 a = rotate(a); 18 b = rotate(b); 19 cout << "x" << setw(8) << setfill('0') << hex << a << ", " << setw(12) << setfill(' ') << dec << a << ", "; 20 cout << "x" << setw(16) << setfill('0') << hex << b << ", " << setw(20) << setfill(' ') << dec << b << endl; 21 } 22 return 0; 23} 24 25// int は 4 バイト 26int rotate(int i) { 27 int msb = 0; // 一番左のビット 28 if (i & 0x80000000) { 29 msb = 1; 30 } 31 return (i << 1) + msb; 32} 33 34// int は 8 バイト 35long rotate(long i) { 36 int msb = 0; // 一番左のビット 37 if (i & 0x8000000000000000) { 38 msb = 1; 39 } 40 return (i << 1) + msb; 41}

実行結果

$ g++ a.cpp $ ./a.out

イメージ説明
イメージ説明

投稿2016/04/17 10:45

katoy

総合スコア22324

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

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

tada_tadaa

2016/04/17 11:43

回答ありがとうございます。 katoyさんが示してくださった回答を参考にして僕なりにプログラム文を作成しました。 まだ学習していない部分で間違いも多々あると思いますが、このプログラム文によって 2進数でビットがずれてゆく様子が分かるようになりました。 #include <iostream> #include <iomanip> #include <bitset> using namespace std; int rotate(int i); long rotate(long i); int main() { int a; long b; a = 1; b = 1; for (int i = 1; i <= 64; i++) { a = rotate(a); b = rotate(b); cout << "x" << setw(8) << setfill('0') << hex << a << ", " << setw(12) << setfill(' ') << dec << a << ", "; std::cout << setw(40) << setfill('0') << static_cast<std::bitset<40> >(a) << endl; //cout << "x" << setw(16) << setfill('0') << hex << b << ", " << setw(20) << setfill(' ') << dec << b << endl; } return 0; } // int は 4 バイト int rotate(int i) { int msb = 0; // 一番左のビット if (i & 0x80000000) { msb = 1; } return (i << 1) + msb; } // int は 8 バイト long rotate(long i) { int msb = 0; // 一番左のビット if (i & 0x8000000000000000) { msb = 1; } return (i << 1) + msb; } また、2進数表示の部分で32ビット目までしか数字の1が移動しないので、僕のint型は 32ビットであろうことがわかるのではないでしょうか。
guest

0

ベストアンサー

こんにちは。

その通りです。
aはint型なので、int rotate(int i);が呼ばれます。
bはlog型なので、long rotate(long i);が呼ばれます。
この仕組はオーバーロードという仕組みです。
そして、それぞれを2進数で表現するとおっしゃる通りの表現となります。


【余談ですが】
符号ビットの振る舞いの問題があり思わぬ動作になりがちですから、符号付き整数を「ローテート」することはあまりないです。

また、int型が2バイト、log型が4バイトについても、同じく処理系依存です。最近はint型が4バイトの処理系の方が身近に多いと思います。

お使いの参考書はコンパイラを指定していますでしょうか?
たったこれだけのコードで複数のコンパイラに依存する機能を使っているので、コンパイラを指定していないとするとちょっと危険な参考書かも知れません。

投稿2016/04/17 08:42

Chironian

総合スコア23272

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

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

tada_tadaa

2016/04/17 09:18

回答ありがとうございます。 >また、int型が2バイト、log型が4バイトについても、同じく処理系依存です。最近はint型が4バイトの処理系の方が身近に多いと思います。 実は僕が余計に頭がこんがらがったのは、本では「回転(ローテート)はシフトと似てい ますが、シフトにより一端から外れた文字をもう一端から入れる点が異なります」と書い てあるので、あれ?左にシフトして、はみでた分は右に入るから、数字は小さくなるので は?と思ったのですが、実行結果は 65537 16 で 0x8000(10進数で32768)を左にシフトしつつ右に1が入っているのでおかしいなーと思って たのでした。つまりこれは僕のコンピュータシステムで、int型が2バイトではなくそれ以上ある から、左にシフトしたときに一番左の1が消えずに、なおかついちばん右に1が入ったというこ とでしょうか。 >お使いの参考書はコンパイラを指定していますでしょうか? 付録としてBorland C++ Compiler 5.5がCDに入ってますが、このコンパイラを推奨はしてると 思いますが、指定はしていないのではないかと。。よくわかりません。 僕が持ってる本は第3版で、初版は1994年となってます。原著は昔、外国の方が書かれて、それ を日本の方が何度も修正と追加を繰り返したものかもしれません。
Chironian

2016/04/17 09:41

> つまりこれは僕のコンピュータシステムで、int型が2バイトではなくそれ以上あるから、左にシフトしたときに一番左の1が消えずに、なおかついちばん右に1が入ったということでしょうか。 正にその通りです。正確な理解です。 処理系依存コードが使われている時の落とし穴にハマってしまったということです。 やはり「危険な」参考書ということかと。今回はtada_tadaさんが気がつかれたからまだ良いと思いますが、全てのケースで問題が顕在化するとは限らないですし。 > Borland C++ Compiler 5.5 懐かしいです。大昔(20年近く前?)に少しだけ使ったことあります。このコンパイラのint型のバイト数を覚えていませんが、非常に古いコンパイラの1つですのでもしかするとint型が2バイトかも知れませんね。 しかし、このコンパイラを未だにダウンロードできるんですね。かなり驚きです。 https://www.embarcadero.com/jp/free-tools 今はもう、新しいC++規格に対応した無償で使えるコンパイラが多数ある(clang, gcc, msvcなど)ので有用性はかなり薄れてしまいましたね。
tada_tadaa

2016/04/17 10:27

コメントありがとうございます。 この本を読み終えたら、時間とお金が許せば他の本も読んでみたいと思っているところです。 オライリージャパンの「C++実践プログラミング」なんか良さそうだなぁと思います。 しかし、PHPやJavaScriptも勉強したいですしね。C++でオブジェクト指向とは何かを理解した いというのもC++を勉強する理由の一つです。あとは、Windowsのアプリケーションとか作って みたいし、LinuxはC言語で書かれているようなので、システムの理解に役立つかと。 やはりC++は押さえておきたい言語のようだと思います。ちょっと欲張りすぎのような気もしま すが。。
Chironian

2016/04/17 10:49

全体をざっくり把握できたら、後は実践あるのみですよ。 特にC++はむちゃくちゃ奥が深いので、全ての機能を使いこなすのは正直無理な気がしてます。全てを理解することより、理解できた機能を使うという発想が大事な気がします。 色々手を出すこと自体は決して欲張り過ぎではないと思いますよ。 まずはプログラムを作ってみることかと。ある程度作れるようになったら、別の言語を学ぶのは非常に有用と思います。
tada_tadaa

2016/04/17 11:34

>全体をざっくり把握できたら、後は実践あるのみですよ。 早く全体をざっくり把握したいです。
Chironian

2016/04/17 11:59

このくらい分かっていれば、実践を始めても早すぎると言うことはないですよ。 何にせよ、始めたら判らないこと出てきますから、その都度調べればよいのです。 私も未だに調べつつ開発してます。C++は奥が深いです。 がんばです。
tada_tadaa

2016/04/17 12:08

>このくらい分かっていれば、実践を始めても早すぎると言うことはないですよ。 >何にせよ、始めたら判らないこと出てきますから、その都度調べればよいのです。 ありがとうございます。しかし、やはり僕は「急がば回れ」で、基礎を本などでじっくり 固めたほうが良いように思います。また、プログラミング能力を鍛えたくなったら、 CodeIQ ( https://codeiq.jp/ ) や AIZU ONLINE JUDGE (http://judge.u-aizu.ac.jp/onlinejudge/?lang=ja)で問題を解くのが良いのではと思います。 ちなみに僕はCodeIQでC言語を解いたら中級の認定を受けました。
Chironian

2016/04/17 12:15

> ちなみに僕はCodeIQでC言語を解いたら中級の認定を受けました。 確かにその通りと感じます。 やり方は人それぞれですし、tada_tadaさんが納得される方法で頑張って下さい。
tada_tadaa

2016/04/17 12:57

>やり方は人それぞれですし、tada_tadaさんが納得される方法で頑張って下さい。 ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問