按位连接

时间:2013-04-18 03:24:28

标签: c bitwise-operators

我有以下内容:

char *pointer = decimal_to_binary(192) // yields 11000000
char *pointer2 = decimal_to_binary(168) // yields 10101000

我想把它们连成:

1100000010101000

我正在引用:Concatenate binary numbers of different lengths,目前正在使用:

unsigned long pointer3 = (*pointer << 16) | *pointer2;

给出输出:

1100010000000000110001

我做错了什么?

5 个答案:

答案 0 :(得分:1)

好的,首先你不应该用整数初始化一个指针;编译器可能会这样警告你:

warning: initialization makes pointer from integer without a cast [enabled by default]
   char* pointer1 = 0xc0;

如果您不熟悉十六进制表示法,请参阅this;例如,你会看到从二进制转换为十六进制比从十进制到十六进制要简单得多。

如果你想表示这些8位数字,你可以直接将它们分配给unsigned char变量,就像我在这里做的那样(例如,将此代码粘贴到文件“test.c”中):

#include <stdio.h>

void main() {
  unsigned char num1 = 0xc0; /* Same as binary 11000000 in hex */
  unsigned char num2 = 0xa8; /* Same as binary 10101000 in hex */

  unsigned long result = (num1 << 8) | num2;
  printf("0x%x\n", result);
}

您可以使用gcc -o test test.c进行编译,0xc0a8在运行时输出:*pointer(这与1100000010101000相同)。

如果您将数字分配给指针,那么当您尝试使用*pointer2result取消引用时,您可能会遇到“细分错误”或“访问冲突”,因为意味着你想要存储在指针地址的值,这可能不在程序地址空间中。

由于num1是一个很长的(32位),它可以肯定地保持您的16位数字,但num2unsigned char必须是char ,所以当你离开移位和OR它们并不会使整个东西都是负数 - 在一个带符号的二进制数字中,最左边的位设置为1意味着它是一个负数,所以如果你使用普通0xffffffa8代替它将签名扩展32位结果,使其保持为负数:{{1}}

答案 1 :(得分:1)

您没有展示如何打印任何内容,因此很难解释您的问题。但是,这句话无可挽回地被打破,因为它不会连接pointerpointer2指向的字符串:

unsigned long pointer3 = (*pointer << 16) | *pointer2;

这将pointer指向的第一个字符(a 1)并将值左移16位,然后在pointer2指向的第一个字符中添加(ors) (另一个1),并将整数格式分配给名称错误的pointer3。因此,它得到了值:

pointer3 = 0x00310031;

这个问题需要一些解释,但是做出一些看似合理(但不一定准确)的假设,这段代码可能就是你所追求的:

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

static char *decimal_to_binary(unsigned char byte)
{
    char *result = malloc(9);
    if (result != 0)
    {
        char *digit = result;
        for (int i = 0; i < 8; i++)
            *digit++ = ((byte >> (7 - i)) & 0x01) + '0';
        *digit = '\0';
    }
    return result;
}

int main(void)
{
    char *pointer1 = decimal_to_binary(192);
    char *pointer2 = decimal_to_binary(168);
    char  concatenated[17];
    unsigned long pointer3 = (*pointer1 << 16) | *pointer2;

    strcpy(&concatenated[0], pointer1);
    strcpy(&concatenated[8], pointer2);

    printf("P1 = <<%s>>; P2 = <<%s>>; P3 = 0x%08lX; C = <<%s>>\n",
           pointer1, pointer2, pointer3, concatenated);

    free(pointer1);
    free(pointer2);
    return(0);
}

输出:

P1 = <<11000000>>; P2 = <<10101000>>; P3 = 0x00310031; C = <<1100000010101000>>

请注意,使用decimal_to_binary()的代码不会小心避免(误)使用空指针。 decimal_to_binary()的设计也不如恒星;那些free()电话很容易被遗忘。更好的设计是:

void decimal_to_binary(unsigned char byte, char buffer[9]);

其中调用代码提供写入二进制输出的缓冲区。在decimal_to_binary()中还有其他编写循环的方法;有些甚至可能比这里选择的更有效。

答案 2 :(得分:0)

首先只在指针中指定一个数字 unsigned long pointer3 = *pointer; 在此左移后此pointer3 16次。 pinter3=pointer3<<16; pointer3=pointer3|*pointer2;

这将起作用我认为

答案 3 :(得分:0)

你不需要像在

中那样改变16
unsigned long pointer3 = (*pointer << 16) | *pointer2;

指针只需要移动8 以下代码将实现您的目标。

#include <stdio.h>
#include <string.h>

void print_binary(int num) {
    short rem[16] = {0};
    for (short i = 1; i <= 16; i++) {
        rem[16-i] = num%2;
        num = num >> 1;
    }
    for (short int i = 0; i < 16; i++) {
        printf("%d", rem[i]);
    }
    printf("\n");
}

int main (int argc, char* argv[]) {

    unsigned char num1 = 192;
    unsigned char num2 = 168;
    int num3 = 0;
    num3 = (num1 << 8) | num2;
    printf("first number: %d\n", num1);
    print_binary(num1);

    printf("second number: %d\n", num2);
    print_binary(num2);

    printf("The number is %d\n", num3);
    print_binary(num3);

    return 0;
}

答案 4 :(得分:-1)

这个看起来很容易理解)

 #include <iostream>
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    using namespace std;



    int main()
    {
    int a = 32; // 100000
    int b = 5; // 101
    int step=0;
    int siz=0;
    while(1){
    if(pow(2,step) < b){
    step++;
    continue;
    }
    else{
    siz = step;
    break;
    }

    }
    a = a<<siz;
    a = a | b;
    cout<<a;
    }