C中的位操作,设置最低有效位

时间:2015-11-17 20:35:09

标签: c bit-manipulation bit

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

#define BYTETOBINARYPATTERN "%d%d%d%d%d%d%d%d"

#define BYTETOBINARY(byte) \
    (byte & 0x80 ? 1 : 0), \
    (byte & 0x40 ? 1 : 0), \
    (byte & 0x20 ? 1 : 0), \
    (byte & 0x10 ? 1 : 0), \
    (byte & 0x08 ? 1 : 0), \
    (byte & 0x04 ? 1 : 0), \
    (byte & 0x02 ? 1 : 0), \
    (byte & 0x01 ? 1 : 0)

#define PRINTBIN(x) printf(BYTETOBINARYPATTERN, BYTETOBINARY(x));

void printarr(unsigned char *p);
void setlsbs(unsigned char *p, unsigned char b0);
unsigned char getlsbs(unsigned char *p);

int main(int argc, char *argv[])
{
    unsigned char arr[7];
    unsigned char byte0, byte1;
    int i;

    if (argc != 2) {
        printf("Error.Invalid arguments.\n");
        exit(1);
    }

    //seed random
    srandom(atoi(argv[1]));

    for (i = 0; i < 8; i++)
        arr[i] = random() % 255+1;

    byte0 = random() % (255 + 1);

    printarr(arr);

    printf("\nbyte0: ");
    PRINTBIN(byte0);
    printf("  %d\n\n",byte0);

    setlsbs(arr, byte0);

    printarr(arr);

    byte1 = getlsbs(arr);

    printf("\nbyte1: ");
    PRINTBIN(byte1);
    printf("   %d\n\n", byte1);

    return 0;
}

void printarr(unsigned char *p)
{
    int i;

    for (i = 0; i < 8; i++) {
        PRINTBIN(p[i]);
        printf("   %d\n", p[i]);
    }
}

void setlsbs(unsigned char *p, unsigned char b0)
{
    int i, counter;
    unsigned char x;
    x = b0;

    for (i = 0, counter = 1; i < 8; i++, counter++) {
        p[i] &= 0xFE;
        x &= 0x01;
        p[i] |= x;
        x = b0;
        x >>= counter;
    }
}

unsigned char getlsbs(unsigned char *p)
{
    int i, counter;
    unsigned char b0 = 0;

    for (i = 0; i < 8; i++) {
        p[i] &= 0x01;
        b0 |= p[i];
        b0 <<= 1;
    }
    return b0;
}

我正在尝试将byte1设置为数组中元素的最不重要的数字。例如,p[0]的最右边位是字节1的最左边的位。p[1]的最右边的字节将是字节1的第二位,依此类推。该代码适用于某些数字,但它不适用于其他人,我无法弄明白。我认为我的算法是正确的。

运行代码:

John Doe@DESKTOP-QFEGQQD ~/learn
$ ./lab11 50
00110101   53
10100110   166
01101101   109
11001001   201
10111101   189
01000101   69
10010011   147
10000001   129

byte0: 01011001  89

00110101   53
10100110   166
01101100   108
11001001   201
10111101   189
01000100   68
10010011   147
10000000   128

byte1: 00110100   52

Byte1应该等于Byte0。

2 个答案:

答案 0 :(得分:3)

arr被声明为7元素数组,而您将其作为8元素访问。它导致了未定义的行为,这解释了&#34;有时是有效的,有时不是&#34;。

答案 1 :(得分:2)

您当然应该将arr中数组main的定义修复为8个字节:

unsigned char arr[8];

此外,getlsbs中的方法不正确:您应该将字符移位到之前或下一位,否则会丢失最高位并始终将低位设置为0你不需要为此修改参数缓冲区,这是一个令人讨厌的副作用。另请注意,您的算法实际上会将b0中的位转换为b1。你的评论并不明显,你的意思是。

以下是修改后的版本:

unsigned char getlsbs(unsigned char const *p) {
    int i;
    unsigned char b0 = 0;

    for (i = 0; i < 8; i++) {
        b0 = (b0 << 1) | (p[i] & 1);
    }
    return b0;
}

我不得不重新编写代码以使其可读。不要在源文件中使用TAB,忘记愚蠢的/* end if */注释。 {@ 1}}宏也应该修复:您应该在扩展中用括号保护BYTETOBINARY。它不会导致错误,但byte会失败。