Reputation: 15
While I know how to copy one bit from one byte to another (as explained here: Link), I have a problem for a full 4 bit shift from one byte to another byte from a different array (especially for up to 106 bytes).
I read here, how to shift two nibbles at once (for a single byte) and I also tried to implement it:
char *input = (char *)malloc(sizeof(int));
char gen_message[strlen(input) + 1];
for(int loop = (strlen(input) - 1); loop >= 0; loop--)
{
((gen_message[(loop + 1)]) & 0xF0) = ((*input[loop]) & 0x0F);
((gen_message[loop]) & 0x0F) = ((*input[loop]) & 0xF0);
}
gen_message[0] & 0xF0 = 0x4;
Note: Input can between 1 and up to 106 symbols, hence the malloc.
However, I get an error (invalid type of argument of unary '*') and even then I'm not sure if it would be correct.
Can anybody point to a solution or can explain where my brainfart lies, so that I can fix it? Thanks in advance!
-Greetings
Upvotes: 0
Views: 1481
Reputation: 37212
Normally (ignoring bitfields) C can't store anything smaller than a char
. To work around that you can read the whole char
, modify a portion of it, then store the whole (modified) char
.
Note that in C char
may be signed (e.g. maybe a signed octet with range -128 to +127); and this makes it messy to modify due to uncertainty (e.g. behaviour of "right shift of signed integer" isn't defined). For that reason I'd strongly recommend using unsigned char
or uint8_t
.
To write the lowest nibble you'd want to do something like:
dest = dest & 0xF0; // Clear all bits in the low nibble
dest = dest | new_nibble; // Set new bits in the low nibble
To write the highest nibble you'd want to do something like:
dest = dest & 0x0F; // Clear all bits in the high nibble
dest = dest | (new_nibble << 4); // Set new bits in the high nibble
To read nibbles you'd do something like:
low_nibble = src & 0x0F;
high_nibble = (src & 0xF0) >> 4;
Copying is just reading and then writing. For example, to copy the lowest nibble from src
to the highest nibble in dest
you could:
nibble = src & 0x0F;
dest = dest & 0x0F; // Clear all bits in the high nibble
dest = dest | (nibble << 4); // Set new bits in the high nibble
With elements of arrays it might look like this:
nibble1 = input[loop] & 0x0F;
nibble2 = (input[loop] & 0xF0) >> 4;
gen_message[loop + 1] = gen_message[loop + 1] & 0xF0;
gen_message[loop + 1] = gen_message[loop + 1] | nibble1;
gen_message[loop] = gen_message[loop] & 0x0F;
gen_message[loop] = gen_message[loop] | (nibble2 << 4);
This can also be done more concisely:
gen_message[loop + 1] &= 0xF0;
gen_message[loop + 1] |= input[loop] & 0x0F;
gen_message[loop] &= 0x0F;
gen_message[loop] |= ((input[loop] & 0xF0) >> 4) << 4;
Of course if know that the destination contains zeros already (e.g. due to memset()
or calloc()
), you can skip the "clear nibble" parts:
gen_message[loop + 1] |= input[loop] & 0x0F;
gen_message[loop] |= ((input[loop] & 0xF0) >> 4) << 4;
EDIT
The other commentors are right - due to the number of problems it's hard to guess what you're actually trying to do. I think that you might (but might not) be trying to do something like this:
unsigned char *shiftArray4Bits( unsigned char *srcArray ) {
int srcLen = strlen(srcArray);
unsigned char temp = 0;
unsigned char *destArray;
destArray = malloc(srcLen + 1);
if(destArray == NULL) {
return NULL; // Failed to allocate memory
}
for(int i = 0; i < srcLen; i++) {
dest[i] = temp | ((srcArray[i] & 0xF0) >> 4);
temp = (srcArray[i] & 0x0F) << 4;
}
dest[i] = temp;
return dest;
}
Upvotes: 2