程序设计基本

作者: nino天 | 来源:发表于2014-08-06 14:51 被阅读42次

    1.变量的作用域:

    下面这段代码中,i虽然在声明时已经可见,但是main里的i跟外面的i无关,这里虽然编译器不会报错,但是运行后会提示i是一个未定义的值,而不是1.
    <pre>int i = 1;
    void main(){
    int i = i;
    }</pre>

    2.位运算和逻辑运算的区别

    &是位运算,而&&为逻辑运算。||是只要有一个操作数是1结果就是1....
    <pre>int y = 4, x = 3;
    cout << y&x; //输出0
    cout << y&&x; //输出1
    cout << y|x; //输出7
    cout << y||x; //输出1
    </pre>

    3.位运算的例子

    • 求的结果是x的二进制数中有多少位是1:

    <pre>int func(int x){
    int count = 0;
    while(x) {
    count++;
    x = x&(x-1);
    }
    return count;
    }
    </pre>

    • 判断一个数是不是2的N次方:因为所有2的次方都可以写成10,100,...所以只要用位与运算看看第一位是不是1就好了。
      <pre>!(x&(x-1))</pre>
    • 求两个数的平均值:与运算得到的是相同位的一半,异或除以二得到了不同位的一半
      <pre>int f(int x,int y){
      return (x&y)+((x^y)>>1);
      }</pre>

    4.i++的问题

    这里ptr最初指向arr[0]=129,然后ptr自增指向了arr[1],注意在输出时,先计算的是逗号表达式右边的表达式,即ptr自增到arr[2],输出8,然后*ptr也输出8.
    <pre>main(){
    int arr[] = {6,7,8,9,10};
    int ptr = arr;
    (ptr++) +=123;
    printf("%d,%d\n",
    ptr,
    (++ptr));
    }</pre>

    5.float内存方式

    浮点数据就是按下表的格式存储在4个字节中:
    Address+0 Address+1 Address+2 Address+3
    Contents SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
    S: 表示浮点数正负,1为负数,0为正数
    E: 指数加上127后的值的二进制数
    M: 24-bit的底数(只存储23-bit)
    主意:这里有个特例,浮点数 为0时,指数和底数都为0,但此前的公式不成立。因为2的0次方为1,所以,0是个特例。当然,这个特例也不用认为去干扰,编译器会自动去识别。

    <pre>通过上面的格式,我们下面举例看下-12.5在计算机中存储的具体数据:
    格式 SEEEEEEE EMMMMMMM MMMMMMMM MMMMMMMM
    二进制 11000001 01001000 00000000 00000000
    16进制 C1 48 00 00
    可见:
    S: 为1,是个负数。
    E:为 10000010 转为10进制为130,130-127=3,即实际指数部分为3.
    M:为 10010000000000000000000。 这里,在底数左边省略存储了一个1,使用 实际底数表示为 1.10010000000000000000000
    到此,我们吧三个部分的值都拎出来了,现在,我们通过指数部分E的值来调整底数部分M的值。调整方法为:如果指数E为负数,底数的小数点向左移,如果指数E为正数,底数的小数点向右移。小数点移动的位数由指数E的绝对值决定。
    这里,E为正3,使用向右移3为即得:
    1100.10000000000000000000
    至次,这个结果就是12.5的二进制浮点数,将他换算成10进制数就看到12.5了,如何转换,看下面:
    小数点左边的1100 表示为 (1 × 23) + (1 × 22) + (0 × 21) + (0 × 20), 其结果为 12 。
    小数点右边的 .100… 表示为 (1 × 2-1) + (0 × 2-2) + (0 × 2-3) + ... ,其结果为.5 。
    以上二值的和为12.5, 由于S 为1,使用为负数,即-12.5 。
    所以,16进制 0XC1480000 是浮点数 -12.5 。</pre>

    <pre>上面是如何将计算机存储中的二进制数如何转换成实际浮点数,下面看下如何将一浮点数装换成计算机存储格式中的二进制数。
    举例将17.625换算成 float型。
    首先,将17.625换算成二进制位:10001.101 ( 0.625 = 0.5+0.125, 0.5即 1/2, 0.125即 1/8 如果不会将小数部分转换成二进制,请参考其他书籍。) 再将 10001.101 向右移,直到小数点前只剩一位 成了 1.0001101 x 2的4次方(因为右移了4位)。此时 我们的底数M和指数E就出来了:
    底数部分M,因为小数点前必为1,所以IEEE规定只记录小数点后的就好,所以此处底数为 0001101 。
    指数部分E,实际为4,但须加上127,固为131,即二进制数 10000011
    符号部分S,由于是正数,所以S为0.
    综上所述,17.625的 float 存储格式就是:
    0 10000011 00011010000000000000000
    转换成16进制:0x41 8D 00 00
    所以,一看,还是占用了4个字节。</pre>

    6.类型转换

    如果定义了float a = 1.0f,可以算出他的存储为 3f800000h,其中
    M=0,E=0+127=01111111,S=0。因此下面&a将取值到3f800000h,而再对其强制转换成int会得到这个地址的十进制int值。

    <pre>(int&)a;</pre>

    下面这段代码中,第一个转换是把int转换成char,这时4字节截断为1字节,因此i变为000000f7。而后一个是地址的变化,即一个指向int 的指针强制转换成一个指向char的指针,地址并没有变化,只是在指针+1时移动的步长变为了sizeof(unsigned char),即移动1而不是4.

    <pre> unsigned int a = 0xfffffff7;
    unsigned char i = (unsigned char)a;
    char *b = (char*)&a;
    printf("%08x,%08x",i,*b);</pre>

    7. ab交换

    • 返回两个数中较大的那一个

    <pre>return (a+b+abs(a-b))/2;</pre>

    • 交换两个数的值:通常想到 a = a+b; b = a-b; a = a-b;但是这时如果两个数都很大有可能溢出。所以用位运算来做。
      <pre>a = a^b;
      b = a^b;
      a = a^b;
      </pre>

    相关文章

      网友评论

        本文标题:程序设计基本

        本文链接:https://www.haomeiwen.com/subject/zqketttx.html