John Smith
John Smith

Reputation: 85

Bitwise Concatenation

I have the following:

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

I am trying to concat them into:

1100000010101000

I was referencing: Concatenate binary numbers of different lengths and am currently using:

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

which gives the output:

1100010000000000110001

What am I doing wrong?

Upvotes: 1

Views: 23237

Answers (5)

Mr. Hello_world
Mr. Hello_world

Reputation: 85

This one looks easy to understand)

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

Upvotes: 0

Vineet Kapoor
Vineet Kapoor

Reputation: 8289

There is not need to shift by 16 as you are doing in

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

pointer only needs to be shifted by 8.
Following code will achieve what you are trying to do.

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

Upvotes: 0

Claudio
Claudio

Reputation: 2217

Ok, first you shouldn't initialize a pointer with an integer; the compiler will probably warn you like this:

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

If you're not familiar with hexadecimal notation, please refer to this; you'll see converting from binary to hex is much more straightforward than from decimal to hex, for instance.

If you want to represent these 8-bit numbers you could assign them directly to unsigned char variables, like I did down here (paste this code in a file "test.c", for example):

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

You can compile this with gcc -o test test.c, which outputs this when run: 0xc0a8 (this is the same as 1100000010101000).

If you assign the numbers to pointers like you did, you'll likely get a "segmentation fault" or "access violation" when you try to dereference them with *pointer and *pointer2, because that means you want the value stored at the pointer address, which probably doesn't lie in your program address space.

Since result is a long (32-bit), it can surely hold your 16-bit number just fine, but num1 and num2 have to be unsigned char, so when you left shift and OR them it doesn't make the whole thing negative - in a signed binary number the leftmost bit set to 1 means it is a negative number, so if you use a plain char instead it will sign extend the 32-bit result so it remains negative: 0xffffffa8

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 753695

You don't show how you print anything, which makes it difficult to interpret your question. However, this statement is irretrievably broken in that it does nothing to concatenate the strings pointed at by pointer and pointer2:

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

This takes the first character that pointer points at (a 1) and shifts the value left 16 bits, and then adds (ors) in the first character that pointer2 points at (another 1), and assigns the integer thus format to the misnamed pointer3. Thus, it gets the value:

pointer3 = 0x00310031;

The question takes some interpretation, but making some plausible (but not necessarily accurate) assumptions, this code might do what you're after:

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

Output:

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

Note that the code using decimal_to_binary() does not take care to avoid (mis)using null pointers. The design of decimal_to_binary() is also less than stellar; those free() calls are easily forgotten. A better design would be:

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

where the calling code provides the buffer into which the binary output is written. There are also other ways of writing the loop in decimal_to_binary(); some might even be more efficient than the one chosen here.

Upvotes: 1

umang2203
umang2203

Reputation: 78

First only assign one number in pointer like unsigned long pointer3 = *pointer; after this left shift this pointer3 16 times. pinter3=pointer3<<16; pointer3=pointer3|*pointer2;

this will work i think

Upvotes: 0

Related Questions