I am pretty new in c programming and I am trying to figure out more about bits, binary e.c.t
For example, I have three int variables m1 =255 or 11111111 in binary; m2 =255 or 11111111 in binary, m3 = 255 or 11111111 in binary and m4 =0 or 00000000. I am trying to put all theme together into single int variable temp. Something like this (11111111 11111111 11111111 00000000)
Here is the piece of code that I have:
int x1;
unsigned char x2;
unsigned char x3;
unsigned char x4;
int temp;
x1 = x1|m1;
printf("x1:%d\n", x1);
x2 = x2|m2;
printf("x2:%d\n", x2);
temp = x1<<8;
printf("temp:%d\n", temp);
temp = temp|x2;
printf("temp:%d\n", temp);
x3 = x3|m3;
printf("x3:%d\n", x3);
temp = temp<<8;
printf("temp:%d\n", temp);
temp = temp|x3;
printf("temp:%d\n", temp);
x4 = x4|m4;
printf("x4:%d\n", x4);
temp = temp<<8;
printf("temp:%d\n", x1);
temp = temp|x4;
printf("%d\n", temp);
I am using left shift and OR operators here. But I got a little bit wierd output. (I printed out every to step to find out what is wrong).
I got next output:
x1:255
x2:255
temp:65280
temp:65535
x3:255
temp:16776960
temp:16777215
x4:0
temp:-256
temp:-256
Everything goes fine until temp becomes -256 and I do not know why.
I appreciate any help! Thank you!
You're using %d format and it treats variables as signed integers, you need to use %u and change the variable types to unsigned.
unsigned char x1;
unsigned int temp;
You really have a couple of choices in C. First, what it appears you are attempting to do is the following. (note: you should include stdint.h and use uint32_t guaranteed width values instead of int) Your problems surround invoking Undefined Behavior by OR'ing uninitialized values, and failing to properly shift the values for x1, ..., x4.
To do what it looks like you are attempting to do, you could:
#include <stdio.h>
int main (void) {
unsigned int x1 = 0, x2 = 0, x3 = 0, x4 = 0;
unsigned char m1, m2, m3, m4 = 0;
m1 = m2 = m3 = 255;
x1 |= m1;
x2 |= ((unsigned)m2 << 8);
x3 |= ((unsigned)m3 << 16);
x4 = ((x1 | x2 | x3) << 8) | (unsigned)m4;
printf("x1: %u\n", x1);
printf("x2: %u\n", x2);
printf("x3: %u\n", x3);
printf("x4: %u\n", x4);
return 0;
}
Example Use/Output
$ ./bin/shiftx
x1: 255
x2: 65280
x3: 16711680
x4: 4294967040
You can also simplify your logic by simply using a two variables and the value 255. Essentially, you are setting your temp variable to 255 and shifting left by 8, 3-times. Your final value is the OR'ing of the first 3 temp values with a final shift by 8 to get your combined value with the least significant byte zero, e.g.
#include <stdio.h>
#include <stdint.h>
int main (void) {
uint32_t tmp = 0, val = 0;
uint8_t m = 255;
val = m;
printf ("tmp1 : %u\n", val);
tmp = val << 8;
printf ("tmp2 : %u\n", tmp);
val |= tmp;
tmp <<= 8;
printf ("tmp3 : %u\n", tmp);
val |= tmp;
tmp <<= 8;
printf ("tmp4 : %u\n", tmp);
val <<= 8;
printf ("val : %u\n", val);
return 0;
}
Example Use/Output
$ ./bin/shift1var
tmp1 : 255
tmp2 : 65280
tmp3 : 16711680
tmp4 : 4278190080
val : 4294967040
An improved version could make use of a union between a bitfield struct and a uint32_t value, guaranteeing a 32-bit width regardless of architecture. For example, you could:
#include <stdio.h>
#include <stdint.h>
typedef union {
struct {
uint32_t a : 8,
b : 8,
c : 8,
d : 8;
} bits;
uint32_t value;
} bitunion;
int main (void) {
bitunion bu = { .bits = {.a = 0, .b = 255, .c = 255, .d = 255} };
printf ("bu.bits.a: %u\n", bu.bits.a);
printf ("bu.bits.b: %u\n", bu.bits.b << 8);
printf ("bu.bits.c: %u\n", bu.bits.c << 16);
printf ("bu.bits.d: %u\n", bu.bits.d << 24);
printf ("value : %u\n", bu.value);
return 0;
}
(note: the bitfield is made up of d-c-b-a bytes)
Example Use/Output
$ ./bin/shiftxstruct
bu.bits.a: 0
bu.bits.b: 65280
bu.bits.c: 16711680
bu.bits.d: 4278190080
value : 4294967040
Now, don't think these are the only ways to do this. You can use any combination of shifts and OR's as long as you accurately account for the bytes within your final value. Look things over and let me know if you have additional questions.
Related
It is my last semester but one in university, the sublect is called Architecture and Programming of Microprocessors, the professor wrote this code and i just cannot understand what he is doing. Especially the part with the mask. Here is the code. Can anyone help me to understand it please?
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
uint32_t Instruction_Memory[0x2000];
uint32_t PC = 0;
uint32_t Registers[32];
uint32_t Data_Memory[0x3000];
uint32_t get_instruction(uint32_t input){
uint32_t temp = input/4;
return Instruction_Memory[temp];
}
void print_registers() {
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 8; j++) {
printf("x%d: %x \t", i*8+j, Registers[i*8+j]);
}
printf("\n");
};
};
uint32_t get_bits(uint32_t input, int start, int numberOfBits){
uint32_t t4 = input >> start;
uint32_t mask = (1 << numberOfBits) - 1;
t4 = mask & t4;
// printf("input : %x, start : %d, nob : %d, mask : %x\n", input, start, numberOfBits, mask);
return t4;
}
int main(){
PC = 0x1000;
// x5
Registers[5] = 6;
// x9
Registers[9] = 0x2004;
Data_Memory[0x2000] = 10;
Instruction_Memory[0x1000 / 4] = 0xFFC4A303;
Instruction_Memory[0x1004 / 4] = 0x0064A423;
Instruction_Memory[0x1008 / 4] = 0x0062E233;
uint32_t instruction = get_instruction(0x1000);
printf("Instruction = 0x%x\n\r", instruction);
print_registers();
uint32_t A1 = get_bits(instruction, 15, 5);
printf("A1 = %x\n\r", A1);
return 0;
}
I understood that he printed out the registers and also provided an instruction to the system.
The function get_bits (aka "the part with the mask") takes a 32bit integer and two counts. The first count is how many low bits are to be ignored, the second how many are to be returned. (As #PeterCordes pointed out in a comment, the function as-is is not fit for general use due to some limitations, but I guess this code is a one-shot to illustrate certain points.)
get_bits is called with the values 15 and 5, respectively. This means ignore 15, return 5.
Mbbbbbbb bbbbbbbb bbbbbbbb bbbbbbbL
rrrr riiiiiii iiiiiiii
"M" for most significant bit, "L" for least significant bit, "i" for ignored (shifted right), "r" for returned.
As to how that is done, look at your C reference on bitshift and bitwise operators. As to what it means semantically, that should be clear from your accompanying course material explaining what those bits -- labeled A1 -- signify.
IN C Programming, how do I combine (note: not add) two integers into one big integer? So if i have
int a = 8
int b = 6
in binary it would be
int a = 1000
int b = 0110
so combined it would be = 01101000
You would use a combination of the << shift operator and the bitwise | operator. If you are trying to build an 8-bit value from two 4-bit inputs, then:
int a = 8;
int b = 6;
int result = (b << 4) | a;
If you are trying to build a 32-bit value from two 16-bit inputs, then you would write
result = (b << 16) | a;
Example:
#include <stdio.h>
int main( void )
{
int a = 8;
int b = 6;
printf( "a = %08x, b = %08x\n", (unsigned int) a, (unsigned int) b );
int result = (b << 4) | a;
printf( "result = %08x\n", (unsigned int) result );
result = (b << 8) | a;
printf( "result = %08x\n", (unsigned int) result );
result = (b << 16) | a;
printf( "result = %08x\n", (unsigned int) result );
return 0;
}
$ ./bits
a = 00000008, b = 00000006
result = 00000068
result = 00000608
result = 00060008
You can do it as follow using binary mask & 0x0F and bit translation <<:
int a = 0x08
int b = 0x06
int c = (a & 0x0F) + ((b & 0x0F) << 4 )
I hope that it helped
Update 1:
As mentionned in the comment addition + or binary or | are both fine.
What is important to highlight in this answer is the mask & 0x0F, I strongly recommand to use this kind of mecanism to avoid any overflow.
you could use or operator.
int a = 8 ;
int b = 6 ;
int c = (a << 8) | b;
You can use the bit-shift operator << to move the bits into the correct position:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
int main()
{
uint8_t a = 8;
uint8_t b = 6;
uint16_t c = (b << 4) | a;
printf( "The result is: 0x%" PRIX16 "\n", c );
}
This program will print the following:
The result is: 0x68
Note that this program uses fixed-width integer types, which are recommended in this situation, as you cannot rely on the size of an int or unsigned int to have a certain width.
However, there is no need for the result to be 16-bits, if you are only shifting one value by 4 bits, as you are doing in your example. In that case, an integer type with a width of 8-bits would have been sufficient. I am only using 16-bits for the result because you explicitly asked for it.
The macro PRIX16 will probably expand to "hX" or "X" on most platforms. But it is still recommended to use this macro when using fixed-width integer types, as you cannot rely on %hX or %X being the correct format specifier for uint16_t on all platforms.
I have a function that return 1 Byte
uint8_t fun();
the function should run 9 times , so I get 9 Byte I want to make the last8 one as 4 short values here what I've done but I'm not sure that the value that I get are correct :
char array[9];
.............
for ( i = 0; i< 9 ; i++){
array[i] = fun();
}
printf( " 1. Byte %x a = %d , b=%d c =%d \n" ,
array[0],
*(short*)&(array[1]),
*(short*)&(array[3]),
*(short*)&(array[5]),
*(short*)&(array[7]));
is that right ?
It's better to be explicit and join the 8-bit values into 16-bit values yourself:
uint8_t bytes[9];
uint16_t words[4];
words[0] = bytes[1] | (bytes[2] << 8);
words[1] = bytes[3] | (bytes[4] << 8);
words[2] = bytes[5] | (bytes[6] << 8);
words[3] = bytes[7] | (bytes[8] << 8);
The above assumes little-endian, by the way.
You will get alignement problems. Any pointer to a short can be seen as a pointer to char, but on non 8 bit machines, the inverse is not guaranteed.
IMHO, this would be safer :
struct {
char arr0;
union {
char array[8];
uint16_t sarr[4];
} u;
} s;
s.arr0 = fun();
for ( i = 0; i< 8 ; i++){
s.u.array[i] = fun();
}
printf( " 1. Byte %x a = %d , b=%d c =%d d=%d\n" ,
s.arr0,
s.u.sarr[0],
s.u.sarr[1],
s.u.sarr[2],
s.u.sarr[3]);
But I suppose you deal correctly with endianness on your machine and know how the conversion 2 chars <=> 1 short works ...
Try using struct to arrange the data and shift operations to convert for enianism.
// The existence of this function is assumed from the question.
extern unsigned char fun(void);
typedef struct
{
unsigned char Byte;
short WordA;
short WordB;
short WordC;
short WordD;
} converted_data;
void ConvertByteArray(converted_data* Dest, unsigned char* Source)
{
Dest->Byte = Source[0];
// The following assume that the Source bytes are MSB first.
// If they are LSB first, you will need to swap the indeces.
Dest->WordA = (((short)Source[1]) << 8) + Source[2];
Dest->WordB = (((short)Source[3]) << 8) + Source[4];
Dest->WordC = (((short)Source[5]) << 8) + Source[6];
Dest->WordD = (((hshort)Source[7]) << 8) + Source[8];
}
int main(void)
{
unsigned char array[9];
converted_data convertedData;
// Fill the array as per the question.
int i;
for ( i = 0; i< 9 ; i++)
{
array[i] = fun();
}
// Perform the conversion
ConvertByteArray(&convertedData, array);
// Note the use of %h not %d to specify a short in the printf!
printf( " 1. Byte %x a = %h , b=%h c =%h d =%h\n",
(int)convertedData.Byte, // Cast as int because %x assumes an int.
convertedData.WordA,
convertedData.WordB,
convertedData.WordC,
convertedData.WordD );
return 0;
}
Okay, so I'm trying to write a function to reverse a long (64 bytes) in C, and I'm getting some weird results with my bitshifting.
long reverse_long(long x) {
int i;
for(i=0; i<4; i++) {
long a = 0x00000000000000FF<<(8*i);
long b = 0xFF00000000000000>>(8*i);
a = x&a;
b = x&b;
a=a<<8*(7-2*i);
b=b>>8*(7-2*i);
x=x&(~(0x00000000000000FF<<(8*i)));
x=x&(~(0xFF00000000000000>>(8*i)));
x=x|a;
x=x|b;
}
}
On line 4 (long a = 0x00000000000000FF<<(8*i)), I'm shifting a byte of ones to the left by 8 bits for each iteration of the loop, which works fine for the first, second, and third iterations, but on the fourth iteration I get something like 0xFFFFFFFF000000, when I should be getting 0x00000000FF000000.
Line 5 (long b = 0x00000000000000FF>>(8*i)) works just fine though, and gives me the value 0x000000FF00000000.
Can anyone tell me what's going on here?
To understand potential problems in your code you need to understand the following things:
The type and value of integer literals
Rules about left-shifting signed values
Rules about right-shifting signed values
Rules about ~ on signed values
Rules about shifting a value by the width of its type or more
The behaviour of out-of-range integral conversions
That's quite a lot of things to remember. To avoid having to deal with all sorts of weird issues (for example, long a = 0x00000000000000FF<<(8*i); causes undefined behaviour when i == 3), I would recommend the following:
Only use unsigned variables and constants (including x)
Use constants which are the correct width for the type
Further, your code makes the assumption that long is 64-bit. This is not always true. It would be better to do one of the following two things:
Have your code work for unsigned long, whatever size unsigned long might be
Use uint64_t instead of long
To cut a long story short, this is how your code should look if we just fix errors relating to the points I listed above (and do not change the algorithm):
uint64_t reverse_long(uint64_t x)
{
int i;
for(i=0; i<4; i++)
{
uint64_t a = 0xFFull << (8*i);
uint64_t b = 0xFF00000000000000ull >> (8*i);
a = x&a;
b = x&b;
a=a<<8*(7-2*i);
b=b>>8*(7-2*i);
x=x&(~(0xFFull<<(8*i)));
x=x&(~(0xFF00000000000000ull>>(8*i)));
x=x|a;
x=x|b;
}
return x; // don't forget this
}
note: I have used ull suffix to create 64-bit literals. Actually this only guarantees at least 64 bit, but since everything is unsigned here it makes no difference, excess bits will just get truncated. To be very precise, write (uint64_t)0xFF instead of 0xFFull, etc.
You've received excellent advice on where you code went awry, but I thought you might like to see an alternate approach to reversing that might be a bit simpler.
uint64_t reverse_long(uint64_t n) {
uint8_t* a = (uint8_t*)&n;
uint8_t* b = a + 7;
while(a < b) {
uint8_t t = *b;
*b-- = *a;
*a++ = t;
}
}
a) Regarding your error:
What you doing there:
long a = 0x00000000000000FF<<(8*i);
Create signed int constant 0xFF;
Shit it left by i bytes
When it shift by 3 bytes, constant become: 0xFF000000;
When it assign it to long signed, performed sign extension:
0xFF000000 -> 0xFFFFFFFFFF000000;
b) Regarding your code:
There is exist more easy way to write your function, for example:
unsigned long reverse_long(unsigned long x) {
unsigned long rc = 0;
int i = 8;
do {
rc = (rc << 8) | (unsigned char)x;
x >>= 8;
} while(--i);
return rc;
}
The right shifting of signed longs is problematic when they're negative. This minor variant on your code, which is only safe for 64-bit machines where sizeof(long) == 8), ensures that the constants are long and the intermediate variables a and b are unsigned long to avoid those problems. The code contains quite a lot of diagnostics.
#include <stdio.h>
long reverse_long(long x);
long reverse_long(long x)
{
int i;
for (i = 0; i < 4; i++)
{
printf("x0 0x%.16lX\n", x);
unsigned long a = 0x00000000000000FFL << (8 * i);
unsigned long b = 0xFF00000000000000L >> (8 * i);
a &= x;
b &= x;
printf("a0 0x%.16lX; b0 0x%.16lX\n", a, b);
a <<= 8 * (7 - 2 * i);
b >>= 8 * (7 - 2 * i);
printf("a1 0x%.16lX; b1 0x%.16lX\n", a, b);
x &= (~(0x00000000000000FFL << (8 * i)));
x &= (~(0xFF00000000000000L >> (8 * i)));
printf("x1 0x%.16lX\n", x);
x |= a | b;
printf("x2 0x%.16lX\n", x);
}
return x;
}
int main(void)
{
long x = 0xFEDCBA9876543210L;
printf("0x%.16lX <=> 0x%.16lX\n", x, reverse_long(x));
return 0;
}
Output:
x0 0xFEDCBA9876543210
a0 0x0000000000000010; b0 0xFE00000000000000
a1 0x1000000000000000; b1 0x00000000000000FE
x1 0x00DCBA9876543200
x2 0x10DCBA98765432FE
x0 0x10DCBA98765432FE
a0 0x0000000000003200; b0 0x00DC000000000000
a1 0x0032000000000000; b1 0x000000000000DC00
x1 0x1000BA98765400FE
x2 0x1032BA987654DCFE
x0 0x1032BA987654DCFE
a0 0x0000000000540000; b0 0x0000BA0000000000
a1 0x0000540000000000; b1 0x0000000000BA0000
x1 0x103200987600DCFE
x2 0x1032549876BADCFE
x0 0x1032549876BADCFE
a0 0x0000000076000000; b0 0x0000009800000000
a1 0x0000007600000000; b1 0x0000000098000000
x1 0x1032540000BADCFE
x2 0x1032547698BADCFE
0xFEDCBA9876543210 <=> 0x1032547698BADCFE
Alternative Implementations
This is a variant of the program above, with the reverse_long() changed to reverse_uint64_v1() and using uint64_t instead of long and unsigned long. The printing is upgraded using PRIX64 format, but also commented out since it is being used in a performance test. The reverse_uint64_v2() function does fewer operations per cycle, though it does more cycles (8 instead of 4). It copies the low order byte of what's left of the input value into the low order byte of the current output value after it's been shifted left 8 places. The reverse_uint64_v3() function does a loop-unrolling of reverse_uint64_v2(), and micro-optimizes by avoiding one assignment to b and one extra shift at the end.
#include <inttypes.h>
#include <stdio.h>
#include "timer.h"
uint64_t reverse_uint64_v1(uint64_t x);
uint64_t reverse_uint64_v2(uint64_t x);
uint64_t reverse_uint64_v3(uint64_t x);
uint64_t reverse_uint64_v1(uint64_t x)
{
for (int i = 0; i < 4; i++)
{
//printf("x0 0x%.16" PRIX64 "\n", x);
uint64_t a = UINT64_C(0x00000000000000FF) << (8 * i);
uint64_t b = UINT64_C(0xFF00000000000000) >> (8 * i);
a &= x;
b &= x;
//printf("a0 0x%.16" PRIX64 "; b0 0x%.16" PRIX64 "\n", a, b);
a <<= 8 * (7 - 2 * i);
b >>= 8 * (7 - 2 * i);
//printf("a1 0x%.16" PRIX64 "; b1 0x%.16" PRIX64 "\n", a, b);
x &= ~(UINT64_C(0x00000000000000FF) << (8 * i));
x &= ~(UINT64_C(0xFF00000000000000) >> (8 * i));
//printf("x1 0x%.16" PRIX64 "\n", x);
x |= a | b;
//printf("x2 0x%.16" PRIX64 "\n", x);
}
return x;
}
uint64_t reverse_uint64_v2(uint64_t x)
{
uint64_t r = 0;
for (size_t i = 0; i < sizeof(uint64_t); i++)
{
uint64_t b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
}
return r;
}
uint64_t reverse_uint64_v3(uint64_t x)
{
uint64_t b;
uint64_t r;
r = x & 0xFF; // Optimization 1
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
x >>= 8;
b = x & 0xFF;
r = (r << 8) | b;
// x >>= 8; // Optimization 2
return r;
}
static void timing_test(uint64_t (*reverse)(uint64_t))
{
Clock clk;
clk_init(&clk);
uint64_t ur = 0;
uint64_t lb = UINT64_C(0x0123456789ABCDEF);
uint64_t ub = UINT64_C(0xFEDCBA9876543210);
uint64_t inc = UINT64_C(0x287654321);
uint64_t cnt = 0;
clk_start(&clk);
for (uint64_t u = lb; u < ub; u += inc)
{
ur += (*reverse)(u);
cnt++;
}
clk_stop(&clk);
char buffer[32];
printf("Sum = 0x%.16" PRIX64 " Count = %" PRId64 " Time = %s\n", ur, cnt,
clk_elapsed_us(&clk, buffer, sizeof(buffer)));
}
int main(void)
{
uint64_t u = UINT64_C(0xFEDCBA9876543210);
printf("0x%.16" PRIX64 " <=> 0x%.16" PRIX64 "\n", u, reverse_uint64_v1(u));
printf("0x%.16" PRIX64 " <=> 0x%.16" PRIX64 "\n", u, reverse_uint64_v2(u));
printf("0x%.16" PRIX64 " <=> 0x%.16" PRIX64 "\n", u, reverse_uint64_v3(u));
timing_test(reverse_uint64_v1);
timing_test(reverse_uint64_v2);
timing_test(reverse_uint64_v3);
timing_test(reverse_uint64_v1);
timing_test(reverse_uint64_v2);
timing_test(reverse_uint64_v3);
return 0;
}
Example output:
0xFEDCBA9876543210 <=> 0x1032547698BADCFE
0xFEDCBA9876543210 <=> 0x1032547698BADCFE
0xFEDCBA9876543210 <=> 0x1032547698BADCFE
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.543540
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.822616
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 7.303825
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.943668
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 7.314660
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 7.295862
The sum and count have two purposes. First, they provide a cross-check that the results from the three functions are the same. Second, they ensure that the compiler doesn't do anything like optimize the whole loop out of business.
As you can see, there is not a lot of difference between the v2 and v3 timings, but the v1 code is quite a bit slower than the v2 or v3 code. For clarity, then, I'd use the v2 code.
For comparison, I also added a 'do nothing' function:
uint64_t reverse_uint64_v4(uint64_t x)
{
return x;
}
Clearly, the sum from this is different, but the count is the same, so it measures the overhead of the loop control and counting. The times I got on two runs were:
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.965360
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 7.197267
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 7.454553
Sum = 0x09EBA33CFF9869C2 Count = 1683264863 Time = 3.607310
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.381292
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.804442
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.797625
Sum = 0x09EBA33CFF9869C2 Count = 1683264863 Time = 3.541233
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.438374
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.805865
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.797086
Sum = 0x09EBA33CFF9869C2 Count = 1683264863 Time = 3.532735
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 8.426701
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.824182
Sum = 0x0BC6E4692C2EC35A Count = 1683264863 Time = 6.834344
Sum = 0x09EBA33CFF9869C2 Count = 1683264863 Time = 3.510904
Clearly, about half the time in the test function is in the loop and function call overhead.
There are two variables,
uint8_t x (8 bit type)
uint16_t y (16 bit type)
, that together hold information about the value of an int num. Say num consists of four bytes abcd (where a is most significant). Then x needs to be copied to b, and y needs to be compied to cd. What is the best way/code to do this?
This works for me:
#include <stdio.h>
#include <stdint.h>
int main()
{
uint8_t x = 0xF2;
uint16_t y = 0x1234;
int a = 0x87654321;
// The core operations that put x and y in a.
a = (a & 0xFF000000) | (x<<16);
a = (a & 0xFFFF0000) | y;
printf("x: %X\n", x);
printf("y: %X\n", y);
printf("a: %X\n", a);
}
Here's the output:
x: F2
y: 1234
a: 87F21234
you can use a union (although be careful with padding/alignment)
typedef union
{
uint32_t abcd;
struct
{
uint8_t a;
uint8_t b;
uint16_t cd;
} parts;
} myvaluetype;
myvaluetype myvalue = {0};
uint8_t x = 42;
uint16_t y = 2311;
myvalue.parts.b = x;
myvalue.parts.cd = y;
printf( "%u\n", myvalue.abcd );
Bytemasks will do. something like below
int8 x = a & 0xff;
int16 y = a & 0xff00;