取反和异或

最近碰到了一个问题:

#include 
int main(){
	int x;
	printf("%x\n",~x^x);
    return 0;
}

这段代码输出是多少?

碰到这个问题的第一感觉,这难道不是乱码?

取反和异或_第1张图片
这个结果会是乱码吗?我们来复习一下相关知识

格式控制符 输出格式
%d 按十进制数据的实际长度输出
%ld 输出长整型数据
%md m为指定的输出字段的宽度,如果数据的位数小于m,则左端补空格,若大于m,则按实际位数输出
%u 输出无符号整型
%c 输出一个字符
%f 用来输出实数,包括单精度和双精度以小数形式输出,不指定字符宽度,由系统自动指定,整数部分自动输出小数部分输出6位,超过6位的四舍五入
%.mf 输出实数时小数点后保留m位
%o 以八进制整数形式输出
%s 用来输出字符串
%x(或 %X 或 %#x 或 %#X) 以十六进制形式输出整数(x大写输出字母为大写x小写输出字母为小写)

按位取反

  • ~表示按位取反。
  • 我们来举一个例子:如果一个int类型的数2取反应该是多少呢?int类型在计算机中存储位数是32位,也就是说,2在计算机中应该是0000 0000 0000 0000 0000 0000 0000 0010,取反,得1111 1111 1111 1111 1111 1111 1111 1101,最高位是符号位,1表示负数。0表示正数,那这个数应该是一个负数,我们必须要求出它的源码。
  • 对于一个负数,我们已知的是它的补码,求它的源码的方法是,先对补码取反,再加一,最后在外面加一个负号。
  • 那上面这个问题补码应该是1111 1111 1111 1111 1111 1111 1111 1101,取反,得0000 0000 0000 0000 0000 0000 0000 0010,再加一,得 0000 0000 0000 0000 0000 0000 0000 0011,表示的数就是3,可以用下面的代码在计算机里运行一下。
	#include 
	int main(){
		int x;
		printf("%d\n",~2);
		return 0;
	}

按位异或

  • ^表示按位异或。
  • 例如:计算a^b时,根据操作数a与b每位的值,计算结果,当a与b对应位上的值相同时,算出结果的相应位上为0,否则为1,当然这里面输入输出都是十进制,只有在计算机内部运行才是二进制数。
  • 例:2^3,相当于二进制数10和11,运算时遵循同出0,异出1,得到的结果应该是01,转化成十进制就是1。
    这样回过头来看最开始的问题。

优先级是按位取反大于按位异或

对于一个int类型的数x(32位),~x使得得到的二进制数相对于x每个都相反,这样再对它按位异或,同出0,异出1,所以得到的应该是1111 1111 1111 1111 1111 1111 1111 1111 如果转化成十进制,应该取反码,再加一,最后加负号,所以是-1;如果转化成16进制,每个1111都可以转化成f(16进制中f表示15),所以就应该是8个f。

你可能感兴趣的:(c++)