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

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

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

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

1回答

13123閲覧

Arduinoでのビット反転について

tickJam

総合スコア12

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

0クリップ

投稿2016/09/12 08:02

編集2016/09/12 08:11

###前提・実現したいこと
int 変数value を作り、「1」もしくは「0」を代入して、
後ほどその値を反転して使いたい。
value = 1 の時は 0
value = 0 の時は 1

そのため変数valueを反転するために~valueとしたのですが
value = 1 のときは-2
value = 0 のときは-1
となってしまいます。

結果的にはBooleanを使い!で逆の値をとり動作させることはできましたが
int/booleanと「~」の組み合わせで何がダメだったのか
その理由をしりたいです。

###発生している問題・エラーメッセージ

エラーメッセージはありません。

###該当のソースコード

Arduino

1int value =1; //1 or 0 2 3void setup() { 4 Serial.begin(9600); // put your setup code here, to run once: 5 6} 7 8void loop() { 9 Serial.println(value); 10 Serial.println(~value); 11 12}

###試したこと
結果的にboolean型変数でtrueもしくはfalseと代入し、!で逆の値をとることで動作しましたが、なぜintと~ではうまくいかなかったのか知りたいです。

###補足情報(言語/FW/ツール等のバージョンなど)
より詳細な情報

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

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

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

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

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

guest

回答1

0

ベストアンサー

intが2の補数によって負数を表現しているから、ではないでしょうか。

こちらのサイトの「符号付き整数を2の補数によって表現する」がわかりやすかったです。
(4ビットの場合の説明ですが、イメージはつかめるかと)
つまり

10進数の1=2進表現で0001 ↓ NOT でビット反転 2進表現で1110=10進数の-2 10進数の0=2進表現で0000 ↓ NOT でビット反転 2進表現で1111=10進数の-1

ということです。
(等幅文字にしたいがためにコードブロックを使うのは邪道かな……)


ちなみにintで1→0、0→1 がしたい場合は

value = 1 - value;

なんてコードを書いたりしますね。

投稿2016/09/12 09:09

alg

総合スコア2019

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

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

tickJam

2016/09/12 16:39

ありがとうございます。私の知識がおいつかず少し時間がかかりましたが、わかりやすくかったので無事理解できました。簡単に変換できるコードの例も教えていただきありがとうございます。 一点だけ確認したいのですが、以下のサイトでみるとBoolean型は符号なしのuint8t型と書かれているのですが http://garretlab.web.fc2.com/arduino/clang/data/index.html それでも補数になってしまうのは、変数型が符号の有無にかかわらず「~」によって補数変換される場合、出力される結果は符号ありの型に自動的に変換されてしまうということなのでしょうか?
alg

2016/09/13 04:47

> 変数型が符号の有無にかかわらず「~」によって補数変換される場合 「~」は補数変換の演算子ではなく、各ビットを反転させる演算子です。 参考: > ~ (NOT) > C++言語のNOT演算子「~」は、&や|と違って、右側の1つの値に対して働きます。NOT演算子は各ビットを反対の値にします。0は1に、1は0になります。 http://www.musashinodenpa.com/arduino/ref/index.php?f=0&pos=767 なので、uint8のような符号なし整数に~をかけた場合は負数になったりはせず、 00000000(10進の0) → 11111111(10進の255) 00001111(10進の15) → 11110000(10進の240) といった変換が行われます。
tickJam

2016/09/13 07:39

毎度わかりやすい説明をありがとうございます! ほど型には関係なく、そのままビット反転するだけの機能なんですね。 BooleanもしくはIntの1や0を~で補数表現したところで1→0、0→1にはならないことはよくわかりました。 あと、しつこくすみません(^^;) 以下のコードでテストしていたのですが uint8_t value =1; void setup() { Serial.begin(9600); // put your setup code here, to run once: } void loop() { Serial.println(~value); } シリアルモニタに返ってくる値は-2なってしまいます。 value 00000001 ~value 11111110 と二進での値が変わり、uint8_t型なので結果は十進数:254となるのではないかと思うのですがなぜか‐2で返ってきてしまいます。 void loop(){ uint8_t b = ~value; Serial.println(b); } とすれば254で返ってくるのですが、 この違いがどこから生まれてくるのかよくわからないでいます。
alg

2016/09/23 03:48

今更ながら正直に言います。私、あまりCには詳しくないのです……。なので、以下は自分なりに調べてみた結果であり、間違っている可能性もありますのでご了承ください。m(_ _)m uint8_tに対するNOT演算(~)の際には、下記のように処理されるようです。 (1)intに変換 (2)NOT演算 つまり、 uint8_t value =1; の場合の ~value は、intの-2に変換される、ということです。 これをそのまま Serial.println(~value); すると、intの-2が渡されたわけですから結果は -2 となります。 一方、~value(=intの-2)をいったんuint8_t型の変数に代入しようとすると、型が一致しませんのでintからuint8_tへの型変換がおこなわれます。 この際、uint8_tではintの-2を表現できませんので、 -2 % (uint8_tの表現しうる最大値 + 1) という計算が行われます。つまり-2を256で割った余りです。で、この計算結果が254です。 (-2を256で割った余りが254、というのは直感的にはわかりにくいですが、"負数の剰余"でググると色々闇が見えて面白いと思いますw) 詳しくは、http://www.symmetric.co.jp/blog/archives/95http://www9.plala.or.jp/sgwr-t/detail/TypeConversion.html を見ていただくか、"暗黙の型変換"や"符号拡張"でググってみてください。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問