c11---位运算相关
Posted 672530440
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c11---位运算相关相关的知识,希望对你有一定的参考价值。
// // main.c // 03-原码反码补码 #include <stdio.h> int main(int argc, const char * argv[]) { // int占4个字节 1个字节8位 int num = 12; /* // 12的二进制 12在内存中存储的是它的补码 00000000 00000000 00000000 00001100 正数的特点:(三码合一) 正数的原码就是TA的反码就是TA的补码 -12 二进制的最高位我们称之为符号位 如果符号位是0代表是一个正数, 如果符号位是1代表是一个负数 10000000 00000000 00000000 00001100 (-12的原码,人思维的码) 11111111 11111111 11111111 11110011(反码, 符号位不变其它位取反) 11111111 11111111 11111111 11110011 +00000000 00000000 00000000 00000001 _____________________________________________ 11111111 11111111 11111111 11110100(补码 , 反码+1,内存中存储的) 结论:无论正数负数在内存中存储的都是补码 11111111 11111111 11111111 11110101 (补码) -00000000 00000000 00000000 00000001 (-1) _____________________________________________ 11111111 11111111 11111111 11110100 (反码) 10000000 00000000 00000000 00001011 */ printf("%d\n", 0b11111111111111111111111111110101); return 0; }
// // main.c // 01-进制 #include <stdio.h> int main(int argc, const char * argv[]) { // 1.默认就是10进制 int num = 12; // 2.在前面加上一个0就代表八进制 int num1 = 014; // %d是以十进制的方式输出一个整数 printf("%d\n", num1); // %o是以八进制的方式输出一个整数 printf("%o\n", num); // 在数值前面加上0b就代表二进制 int num2 = 0b1100; printf("%d\n", num2); // 在数值前面加上0x就代表十六进制 int num3 = 0xc; printf("%d\n", num3); // %x是以十六进制的方式输出一个整数 printf("%x\n", num); // 口诀:不看你怎么存,只看你怎去取 return 0; }
// // main.c // 02-进制转换 #include <stdio.h> int main(int argc, const char * argv[]) { /* 十进制 -> 二进制 9 转换原理:除2取余 倒序读取 9/2 4 1 4/2 2 0 2/2 1 0 1/2 0 1 9 --> 1001 二进制 --> 十进制 1001 转换原理:乘以2的幂数(幂数从0开始), 然后相加 1 * 2(0) = 1 0 * 2(1) = 0 0 * 2(2) = 0 1 * 2(3) = 8 1 + 0 + 0 + 8 = 9 1 1 1 1 1 16 8 4 2 1 N位二进制的取值范围 1位 取值范围 0~1 0~2的1次方-1 2位 取值范围 0~3 0~2的2次方-1 3位 取值范围 0~7 0~2的3次方-1 n位 取值范围 0~2(n)-1 000 001 010 011 100 101 110 111 11111 0~ (32-1) 二进制转换为八进制 进制越大表示的位数就越短 规律:三个二进制位代表一个八进制位 因为3位的最大取值是7 而八进制是逢八进一 1个字节 8位 000 0 001 1 100 4 014 二进制转换为十六进制 规律:四个二进制位代表一个十六进制位 因为4位的最大取值是15, 而十六进制是逢十六进一 0000 0 1100 c 0xc */ printf("%d\n", 0b1001); return 0; }
// // main.c // 05-位运算 #include <stdio.h> /* 位运算都是针对二进制的 & | ^ ~ << >> */ int main(int argc, const char * argv[]) { /* & 按位与 特点:只有对应的两位都是1才返回1 否则返回0 口诀: 一假则假 规律:任何数按位与上1结果还是那个数 1001 & 0101 _______ 0001 1001 &1111 ______ 1001 */ /* | 按位或 特点:只要对应的两位其中一位是1就返回1 口诀:一真则真 1001 | 0101 ________ 1101 */ /* ^ 按位异或 特点:对应的两位不相同返回1 相同返回0 1001 ^ 0101 _______ 1100 // 多个整数按位异或的结果和顺序无关 1001 ^ 0101 _______ 1100 1100 ^ 0110 _______ 1010 1001 ^ 0110 _______ 1111 1111 ^ 0101 _______ 1010 // 相同整数按位异或结果是0 1001 ^ 1001 _______ 0000 // 任何整数按位异或上0结果不变 1001 ^ 0000 _______ 1001 // 任何整数按位异或上另一个整数两次结果还是那个数 1001 ^ 1001 ____________ 0000 0000 ^0101 ______ 0101 */ // int result = 9 & 5; // int result = 9 | 5; // int result = 9 ^ 5; // 多个整数按位异或的结果和顺序无关 // int result2 = 9 ^ 5 ^ 6; // int result2 = 9 ^ 6 ^ 5; // 相同整数按位异或结果是0 // int result3 = 9 ^ 9; // 任何整数按位异或上0结果不变 // int result4 = 9 ^ 0 ; // 任何整数按位异或上另一个整数两次结果还是那个数 // int result5 = 9 ^ 9 ^ 5; // int result6 = 9 ^ 5 ^ 9; // printf("result = %d\n", result6); /* ~ 按位取反 特点: 0变1 1变0 0000 0000 0000 0000 0000 0000 0000 1001 ~1111 1111 1111 1111 1111 1111 1111 0110 (补码) 0000 0000 0000 0000 0000 0000 0000 0001 ______________________________________________ 1111 1111 1111 1111 1111 1111 1111 0101 (反码) 1000 0000 0000 0000 0000 0000 0000 1010 */ // int result = ~9; //// printf("result = %d\n", result); // printf("%d\n",0b11111111111111111111111111110110); return 0; }
// // main.c // 位运算符2 // // Created by xiaomage on 15/6/9. // Copyright (c) 2015年 itcast. All rights reserved. // #include <stdio.h> int main(int argc, const char * argv[]) { /* << 左移 a << n 把整数a的二进制位往左边移n位 移出的位砍掉,低位补0, 发现左移会把原有的数值变大 9 << 1 = 18 9 * 2(1) = 18 9 << 2 = 36 9 * 2(2) = 26 9 << n = 9 * 2(n) 左移的应用场景:当要计算某个数乘以2的n次方的时候就用左移,效率最高 0000 0000 0000 0000 0000 0000 0000 0000 100 0000 0000 0000 0000 0000 0000 10010 注意点:左移有可能改变数值的正负性 */ /* >> 右移 a >> n 把整数a的二进制位往右边移n位 移出的位砍掉, 缺少的以为最高位是0就补0是1就补1(是在当前操作系统下) 9 >> 1 = 4 9 / 2(1) = 4 9 >> 2 = 2 9 / 2(2) = 2 右移的应用场景:当要计算某个数除以2的N次方的时候就用右移,效率最高 0000 0000 0000 0000 0000 0000 0000 0000 000000 0000 0000 0000 0000 0000 0000 10 */ // int result = 9 << 2; int result = 9 >> 2; printf("result = %d\n", result); return 0; }
// // main.c // 位运算符练习1 // // Created by xiaomage on 15/6/9. // Copyright (c) 2015年 itcast. All rights reserved. // #include <stdio.h> void printBinay(int value); int main(int argc, const char * argv[]) { /* 要求定义一个函数, 传入一个整数, 输出该整数的二进制 %i %o %x 0000 0000 0000 0000 0000 0000 0000 1001 &0000 0000 0000 0000 0000 0000 0000 0001 // 1.让9的二进制向右移31, 就可以获取到9得最高位的二进制, 然后让9的二进制的最高位和1相&, 那么就可以获得9的最高位 // 2.让9的二进制向右移30, 就可以获得9二进制的第二位 // 3.以此类推, 直到0位置 技巧: 1.任何数与1相&都是那个数 2.利用位移取出每一位 */ int num = 15; printBinay(num); return 0; } void printBinay(int value) { // 1.定义变量需要向右移动的位数 int offset = 31; // 2.通过循环取出每一位 while (offset >=0) { int result = (value >> offset) & 1; printf("%i", result); // 3.每次取出一位就让控制右移的变量-1 offset--; if ((offset+1) % 4 == 0) { printf(" "); } } printf("\n"); }
// // main.c // 位运算符练习2 #include <stdio.h> int main(int argc, const char * argv[]) { // 利用位运算符, 判断一个数的奇偶性 int num = 9; // 开发中常用的方式 if (num % 2 == 0) { printf("偶数\n"); }else { printf("奇数\n"); } // 注意: 三目(三元)运算符, 的结果A和结果B如果是表达式, 那么必须有返回值 (num % 2 == 0) ? printf("偶数\n"):printf("奇数\n"); int length = printf("李"); printf("------%i\n", length); /* 1001 9 1011 11 1010 10 1100 12 通过观察, 我们发现如果是偶数, 那么二进制的最后一位是0, 如果是奇数那么二进制的最后一位是1 */ /* if ((num & 1) == 1) { printf("奇数\n"); }else { printf("偶数\n"); } */ if ((num & 1)) { printf("奇数\n"); }else { printf("偶数\n"); } return 0; }
// // main.c // 变量的存储细节 // // Created by xiaomage on 15/6/9. // Copyright (c) 2015年 itcast. All rights reserved. // #include <stdio.h> int main(int argc, const char * argv[]) { // 变量为什么要有类型? 每种类型占用的内存空间不一样 int 4, char 1 double 8 // 只要定义变量, 系统就会开辟一块存储空间给我们的变量存储数据, 内存寻址是从大到小 // 越先定义的变量, 内存地址越大 // 变量的地址就是所占的存储空间最小的字节地址 int num; // 注意: 由于内存寻址是从大到小, 所以存储数据也是从大到小的存储(先存储二进制的高位, 再存储低位) // 高位 --> 低位 // 00000000 00000000 00000000 00001001 num = 9; // 9 -->二进制 -->存储(补码) int value; value = 600; //00000000 00000000 00000010 01011000 // %p是输出地址 // &变量名称, 是取出变量的地址 printf("num = %p\n", &num); printf("value = %p\n", &value); // 获取存储的每一位 char *c = &value; for (int i = 0; i < sizeof(num); i++) { int result = c[i]; // 取出每个字节中存储的数据 printf("%i\n", result); } return 0; }
// // main.c // char基本概念 // // Created by xiaomage on 15/6/9. // Copyright (c) 2015年 itcast. All rights reserved. // #include <stdio.h> int main(int argc, const char * argv[]) { // 研究的问题: char类型的变量在内存中是如何存储的? // char 1个字节 int num; char charValue; charValue = ‘a‘; // 计算机智能识别0和1 // a == 97 == 01100001 int size = sizeof(charValue); printf("%i\n", size); printf("num = %p\n", &num); printf("char = %p\n", &charValue); // 在C语言中, 不看怎么存, 只看怎么取 printf("%c\n", charValue); printf("%i\n", charValue); 字符6和数字6就是完全不相同的两个数 char c1 = 6; // 00000110 char c2 = ‘6‘;// 00110110 printf("%i\n", c1); printf("%i\n", c2); // char类型在某些情况下可以当做整型来用 // 如果对内存要求特别严格, 而且需要存储的整数不超过char类型的取值范围, 那么就可以使用char类型来代替int类型 // -2(7)~2(7)-1 == -128 ~ 127 char c = 129; // 1000 0000 printf("%i\n", c); return 0; }
// // main.c // 类型说明符 #include <stdio.h> /* 类型说明符: 1.说明长度的(它可以用于修改类型所占用的存储空间的大小) short; short == short int == 2个字节 == %hi/ %hd long; long == long int == 8个字节 == %li / %ld long long; == long long int == 8个字节 == %lli / %lld 用于说明数据类型, 一般情况下和int配合使用 2.说明符号位(它可以用于修改符号位是否用于正负数) unsigned; 无符号 , 取值正数和零 == %u signed; 有符号, 默认就是有符号 , 取值 正数和零以及负数 3.不同类型的说明符可以混合使用 unsigned short signed long // 注意: 相同类型不能在一起使用 unsigned signed */ int main(int argc, const char * argv[]) { // int == 4个字节 == -2(31)~2(31)-1 int num = 12345678901; printf("num = %i\n", num); // int == 4个字节, long int == 8个字节 == -2(63)~2(63)-1 long int num1 = 12345678901; printf("num1 = %li\n", num1); // long int == long // 用%li 或者 %ld来输出long类型的数据 // C语言中不看怎么存, 只看怎么取 long num2 = 12345678901; printf("num2 = %li\n", num2); // long long // 在64位变一下, 基本没区别, 但是如果是在32位就有区别 // 32位下long占4个字节, long long 占8个字节 // 注意: 如果使用long long修饰变量, 那么输出的时候需要使用%lli或者%lld long long int num3 = 12345678901; printf("num3 = %lli\n", num3); printf("long long = %i, long = %i\n", sizeof(num3), sizeof(num2)); // long long int == long long long long num4 = 12345678901; printf("num4 = %lli\n", num4); // int == 4个字节 == -2(31)~2(31)-1 int num = 9; // 0000 1001 printf("num = %i\n", num); // 如果以后需要保存的数据的取值范围没有超过short int的取值范围, 可以使用short int来保存 // 但是在企业级开发中很少使用 // short int == 2个字节 == -2(15)~2(15)-1 short int num1 = 9; printf("num1 = %i\n", num1); // short int == short // 如果要输出short int类型的数据, 可以使用%hi或者%hd short num2 = 9; printf("num2 = %hi\n", num2); printf("short = %i, int = %i\n", sizeof(num1), sizeof(num)); // signed 有符号 // 如果给变量加上修饰符signed, 代表当前变量的取值可以是正数 / 负数/ 零 // 如果给变量加上修饰符signed, 就代表把二进制的最高位作为符号位 // 而且默认情况下所有变量都是有符号的(signed) signed int num = 0; // 正数 / 负数/ 零 int == -2(31)~2(31)-1 printf("num = %i\n", num); // unsigned 代表无符号. 无符号就代表当前变量的取值只能是正数 / 零 // 如果给变量加上修饰符unsigned, 就代表"不"把二进制的最高位作为符号位 // 如果想打印无符号的变量, 只能用%u unsigned int num1 = -12; printf("num1 = %u", num1); // 不同类型的说明符可以混合使用 unsigned long int num = 99; printf("num = %lu\n", num); signed short int num1 = 23; printf("num1 = %hi\n", num1); // 注意: 相同类型的说明符不能同时在一起使用 // short long int num2 = 998; // unsigned signed int num3 = 998; return 0; }
以上是关于c11---位运算相关的主要内容,如果未能解决你的问题,请参考以下文章