1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

C言語のビット・シフト演算で符号を反転

Last updated at Posted at 2022-06-01

(『独習C』第13章の理解度チェック大問1)

(コマンドライン引数で与えられた)int型の値の符号を反転した数を返すプログラム:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char *argv[])
{
	int n = atoi(argv[1]);

	if (!n) {
		puts("0");
	} else {
		int npositive = n;
		int shift = 0;
		for (; (npositive & 1) == 0; shift++) {
			npositive >>= 1;
		}
		printf("%i\n", ~npositive << shift | 1 << shift);
	}
}

(ヒントにある内容を噛み砕く)

まずint型の負数は2の補数。

int型の負数として2の補数を考える。

2の補数は、元の値の最も下の桁の1以下はそのままで、それよりも上の桁のビットが反転したもの

どういうことかというと、00001100なら、最も下の桁の1以下とは100。なのでそれより上の00001を反転させればよい。

00001101なら、最も下の桁の1以下とは1。なのでそれより上の0000110を反転させればよい。



上記を踏まえてプログラムを見てみる。

まずnpositive & 1で、一番最初に出てくる1(つまり最も下の桁の1、一番右端にある1)を探し出してる。

ここで& 1における100000001のことだから、npositive & 1は下一桁だけをみてる。

例えば(以下における=は等号の意味)

00001100 & 00000001 = 00000000 = 0
00000110 & 00000001 = 00000000 = 0
00000011 & 00000001 = 00000001 = 1

この動きのように、npositive >>= 1で1ビットずつ右シフトしてる(00001100→00000110→00000011)。

最後に「元の値の最も下の桁の1以下はそのままで、それよりも上の桁のビットが反転したもの」を思い出す。

~npositive << shift | 1 << shiftについて、そのままにする部分のことを考えて<< shiftしてやる。

そしてそれよりも上を反転(~npositive)してやる。

あとはそれらの和(|)をとってやれば目的のものが得られる。

1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?