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;
}
时间: 2024-10-12 11:13:15

c11---位运算相关的相关文章

位运算相关内容整理

位运算相关内容整理 1) 负数 负数的右移:负数右移的话,由于要保持它是负数,所以负数的二进制的左边补1.如果一直右移的话,最后就就变成0xFFFFFFFF 即-1 如: -4>>1 为-2 :-4>>2为-1 负数的左移:跟正整数左移一样,右边补0.左移总是在低位补零,高位丢失,因而负数左移后可能会变成正数. int x = 0x8fff0000; cout << (x << 1); // 输出为536739840 cout << (-2 &l

!codeforces 558C Amr and Chemistry-yy题-(位运算相关)

题意:有n个数,每次进行的操作只能是除以2或者乘以2,求这n个数转换成同一个数字所需要的最小的操作步数 分析: 乍一看题目,觉得好难,对于这种每次有两种情况求最后到达的终点的balabala的我就觉得很复杂,这道题说明其实并不可怕,至少有一部分并不可怕. 这道题的做法是暴力枚举出每个数能够走到的所有的数,记录步数,最后找交点输出最小值即可.找交点也不要想复杂了,这n个数都能到达的数就是交点,那么只需要用一个数组记录能到到达这个点的起点个数,最后起点个数等于n的就是交点,这在以每个起点出发枚举的时

位运算相关

位运算符/移位运算符 运算符 &运算符 操作数1的位 操作数2的位 &的结果位 1 1 1 1 0 0 0 1 0 0 0 0 |运算符 操作数1的位 操作数2的位 &的结果位 1 1 1 1 0 1 0 1 1 0 0 0 ^运算符 操作数1的位 操作数2的位 ^的结果位 1 1 0 1 0 1 0 1 1 0 0 0 ~运算符 操作数的位 ~的结果位 1 0 0 1 移位运算符 原因:主要用于高度优化的代码,在这些代码中,使用其他数据操作的开销太高了 示例: int var1,

N皇后问题(位运算实现)

本文参考Matrix67的位运算相关的博文. 顺道列出Matrix67的位运算及其使用技巧 (一) (二) (三) (四),很不错的文章,非常值得一看. 主要就其中的N皇后问题,给出C++位运算实现版本以及注释分析. 皇后问题很经典,就不再赘述问题本身,解决皇后问题,一般采用的都是深搜DFS+回溯的方法,按照行(列)的顺序枚举每一个可以放置的情况,然后进行冲突判断,当前的放置是否合法,合法就继续搜索下一层,不合法就搜索就回溯.直到,找到一个合法的解,每一层都有一个皇后并且不发生冲突,这时候,放置

位运算常用技巧总结(01)

基础知识 对于位运算,大家都很熟悉,基本的位操作有与(&&).或(||).非(!).异或(&)等等.在面试中经常会出现位运算相关的题,所以我就做了简单的整理,参考了很多写的很好的博客及书籍,在此一并谢过. 现在简单说一下,移位运算. 左移运算:x << y.将x左移y位,将x最左边的y位丢弃,在右边补y个0. 右移运算:x >> y.将x右移y位,这需要区分x是有符号数还是无符号数.在x是无符号数时,只需将x的最右边的y位丢弃,在左边补上y个0.在x是有符号

C++基础-位运算

昨天笔试遇到一道题,让实现乘法的计算方法,设计方案并优化,后来总结位运算相关知识如下: 在计算机中,数据是以1010的二进制形式存储的,1bytes = 8 bits,bit就是位,所以位运算就是对每个1010进行操作. 位运算有&|~^<<>>,分别是与或非异或左移右移. 与:1与不变,0与为0: 或:只有0或0为0,其他情况都为1: 非:取反: 异或:相同为0,不同为1: 左移右移:向左/右移动若干位: 乘法: 左移一位,相当于x2: 除法: 右移一位,/2; 不用申请

#C语言初学记录(位运算)

位运算 Problem Description7-1 数组元素循环右移问题 一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0 ??A?1?A?N?1)变换为(A?N?M?? ?A?N?1?? A?0?? A?1?? ?A?N?M?1?? )(最后M个数循环移至最前面的M个位置).如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法? 输入格式: 每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0):

状压dp中常用的位运算式子

原址:状压dp入门 为了更好的理解状压dp,首先介绍位运算相关的知识. 1.’&’符号,x&y,会将两个十进制数在二进制下进行与运算,然后返回其十进制下的值.例如3(11)&2(10)=2(10). 2.’|’符号,x|y,会将两个十进制数在二进制下进行或运算,然后返回其十进制下的值.例如3(11)|2(10)=3(11). 3.’^’符号,x^y,会将两个十进制数在二进制下进行异或运算,然后返回其十进制下的值.例如3(11)^2(10)=1(01). 4.’<<’符号

java位运算

Java的位运算(bitwise operators)直接对整数类型的位进行操作,这些整数类型包括long.int.short.char和 byte,位运算符具体如下表: 运算符 说明 << 左移位,在低位处补0 >> 右移位,若为正数则高位补0,若为负数则高位补1 >>> 无符号右移位,无论正负都在高位补0 & 与(AND),对两个整型操作数中对应位执行布尔代数,两个位都为1时输出1,否则0. | 或(OR),对两个整型操作数中对应位执行布尔代数,两个位

位运算心得

1.位运算 今天复习位运算的时候发现一个规律,之前都没有注意的,就是二进制和2的关系 2^0 = 0000 2^1 = 0010 2^2 = 0100 2^3 = 1000 后面的一次类推,可以很容易识别一个二进制的数和2的关系 二进制之间的运算也都可以换算成和2相关的运算,和2相关的乘法和除法直接可以转化成移位运算来解决 例如: 0010 + 0010 => 0010 * 2 => 0010 左移1位 => 0100 = > 2*2 = 4 0101 * 0100 = >