简体   繁体   English

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

[英]bit manipulation in C, setting the least significant 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;
}

I am trying to set byte1 with the least signifcant digits of the elements in the array. 我正在尝试使用数组中元素的最低有效位设置byte1 For example, the rightmost bit of p[0] will be the leftmost bit of byte 1. The rightmost byte of p[1] will be the second bit of byte 1 and so forth. 例如, p[0]的最右边的位将是字节1的最左位p[1]的最右边的字节将是字节1的第二位,依此类推。 The code works for some numbers but it doesnt for others and I cant quite figure it out. 该代码适用于某些数字,但不适用于其他数字,我无法弄清楚。 I think my algorithm is right. 我认为我的算法是正确的。

Running the code: 运行代码:

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 should equal Byte0. 字节1应等于字节0。

arr is declared as 7-element array, while you are accessing it as 8-element. 当您将其访问为8元素时, arr被声明为7元素数组。 It results in undefined behavior, which explains "sometimes works, sometimes not". 它导致不确定的行为,这说明“有时有效,有时却不行”。

You should of course fix the definition of the array arr in main to be 8 bytes long: 您当然应该将main数组arr的定义固定为8个字节长:

unsigned char arr[8];

Furthermore, your method in getlsbs is incorrect: you should shift the byte before or-ing the next bit, otherwise you lose the top bit and always set the low bit to 0. You do not need to modify the argument buffer for that, it is a nasty side-effect. 此外,您在getlsbs的方法是不正确的:您应该对下一位进行“或” getlsbs 之前先将字节移位,否则会丢失高位,并且始终将低位设置为0。您不需要为此修改参数缓冲区,它是一个令人讨厌的副作用。 Also note that your algorithm actually transposes the bits from b0 into b1 . 还要注意,您的算法实际上将b0的位转置为b1 It is not obvious from your comment that you really mean that. 从您的评论中看不出您是真的意思。

Here is a modified version: 这是修改后的版本:

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;
}

I had to reindent your code to make it readable. 我不得不重新缩进代码以使其可读。 Do not use TABs in your source files, and forget the silly /* end if */ comments. 不要在源文件中使用TAB, /* end if */注释,则忘了愚蠢的/* end if */ The BYTETOBINARY macro should be fixed too: you should protect byte with parentheses in the expansion. BYTETOBINARY宏也应该被修复:在扩展中,您应该用括号将byte保护起来。 It does not cause a bug here, but BYTETOBINARY(1|2) would fail. 它不会在此处导致错误,但是BYTETOBINARY(1|2)会失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM