Character pointer to a union storage - c

I am trying to trace out the value at 1st byte of the union with the help of a char pointer.I assume that the output for byte1 should be ff but instead it's ffffffff.
Correct me If I am wrong.
#include <stdio.h>
#include <stdint.h>
#include <iostream>
struct TriggerMsg
{
uint32_t x[3];
uint32_t y[3];
};
struct sysData
{
union
{
TriggerMsg tTrigger;
uint8_t u8Wakeup;
uint8_t u8Reset;
}
u;
};
int main()
{
sysData sys;
for(int i =0 ; i<3 ; i++)
{
sys.u.tTrigger.x[i] = 0;
sys.u.tTrigger.y[i]= 0;
}
sys.u.u8Wakeup = 0xffffffff;
//sys.u.tTrigger = { 0 };
char *c = (char *)&(sys.u) ;
printf("u.tTrigger.x = %x \nu.tTrigger.y = %x \nu.u8Wakeup = %d \n\n" , \
sys.u.tTrigger.x[0], sys.u.tTrigger.y[0], sys.u.u8Wakeup);
for(int i=0; i<24;i++)
printf("Byte%d = %x \n", i, c[i]) ;
return 0;
}
Output:
u.tTrigger.x = ff
u.tTrigger.y = 0
u.u8Wakeup = 255
Byte0 = ffffffff
Byte1 = 0
Byte2 = 0
Byte3 = 0
Byte4 = 0
Byte5 = 0
Byte6 = 0
Byte7 = 0
Byte8 = 0
Byte9 = 0
Byte10 = 0
Byte11 = 0
Byte12 = 0
Byte13 = 0
Byte14 = 0
Byte15 = 0
Byte16 = 0
Byte17 = 0
Byte18 = 0
Byte19 = 0
Byte20 = 0
Byte21 = 0
Byte22 = 0
Byte23 = 0
I am trying to trace out the value at 1st byte of the union with the help of a char pointer.I assume that the output for byte1 should be ff but instead it's ffffffff.
Correct me If I am wrong.

The %x format prints unsigned ints, but your char is signed. It is promoted to a signed int when passed to printf. This leads to the unexpected output when the negative value in the signed integer is shown as though it were unsigned.
Change the char to unsigned char to fix this:
unsigned char *c = (unsigned char *)&(sys.u);

What you probably wanted is not char but unsigned char.
The first bit in a signed char indicates the sign, so there are only 7 bit left for the actual value. This results in interpreting 0xff as decimal -1 which is printed as hexadecimal 0xffffffff.
With an unsigned char everything is fine.

Related

printing variable after setting a bit

I am trying to set a bit in a 8 bit variable.
Every time I print the variable after setting a particular bit , I always get the value as 1.
uint8 value;
value = (1<<1 || value)
printf(%x \n,value); //prints 1 instead of 2
value = (1<<2 || value)
printf(%x \n,value); //prints 1 instead of 4
You're using boolean 'or' ||. Bitwise 'or' is |.
Also you haven't initialized value so you can't expect it to be anything.
No you don't do it like that.
To set a bit you OR with 1.
For example to set the least significant bit you OR with 1.
ie:
unsigned char val = 4;
// set bit 0
val |= 1;
printf("Value now: %x\n", val);
To set bit 1:
unsigned char val = 4;
// set bit 1
val |= 1 << 1;
printf("Value now: %x\n", val);
A complete example
#include <stdio.h>
char* get_binary(unsigned char buffer, char* binary) {
for (int i = 0; i < 8; ++i) {
int bit = (buffer >> i) & 1;
binary[7 - i] = bit ? '1' : '0';
}
return binary;
}
int main() {
unsigned char val = 4; // val now 100
int bits_to_shift;
unsigned char buffer[10] = { 0 };
unsigned char* p = buffer;
// set bit 0
val |= 1;
printf("Value now: %x, binary=%s\n", val, get_binary(val, p)); // val now 5 :- 101
// To set bit 1 (ie set so we have 111), shift to position then OR
// set bit 1
bits_to_shift = 1;
val |= 1 << bits_to_shift;
printf("Value now: %x, binary=%s\n", val, get_binary(val, p)); // val now 7 :- 111
// set bit 3
bits_to_shift = 3;
val |= 1 << bits_to_shift;
printf("Value now: %x, binary=%s\n", val, get_binary(val, p)); // val now F :- 1111
}

combining MSB and LSB in short

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

a method to do bit-operation in C

I'm trying to define a structure that can allow to set a byte value directly, and also allow to manipulate the bits of the byte without using function like bit_set(), bit_clear() etc,.
Here's my definition
typedef union FLAG_WORK {
volatile unsigned char BYTE;
struct {
volatile unsigned char bit0:1;
volatile unsigned char bit1:1;
volatile unsigned char bit2:1;
volatile unsigned char bit3:1;
volatile unsigned char bit4:1;
volatile unsigned char bit5:1;
volatile unsigned char bit6:1;
volatile unsigned char bit7:1;
}BIT;
}FLAG8;
and a sample code
int main()
{
FLAG8 i;
i.BYTE=(unsigned char)0; // initial the value of i.BYTE
i.BIT.bit0 = 1; // set bit0 of i.BYTE
i.BIT.bit1 = 1;
cout << (int)i.BYTE << endl;
cout << "Hello world!" << endl;
return 0;
}
I just wonder how to modify the structure allowing me to assign value to "i" in above code directly?
any suggestion?
C99 allows intializing members explicitly. Assuming I understand your question correctly, you're looking for
FLAG8 i = { .BIT = { .bit2 = 1, .bit5 = 1 } };
FLAG8 j = { .BYTE = 42 };
FLAG8 k = { 42 }; // same as j as initializing the first member is default
As normal you can assign like But the values are overlapped, because Here union holds only 1 byte of memory
FLAG8 i = { .BIT = { .bit2 = 1, .bit5 = 1 } , .BYTE = 42};
//result of i.BYTE is 42 depens on Byte value
FLAG8 i = { .BYTE = 42 , .BIT = { .bit2 = 1, .bit5 = 1 } };
//result of i.BYTE is 36 depends on bits values
1.As #Christoph suggested You can assign value BYTE or bit by bit directly Like this
FLAG8 i = { .BYTE = 42 };
FLAG8 j = { .BIT = { .bit2 = 1, .bit5 = 1 } };
printf("%d \n\n",(int)i.BYTE );
printf("%d \n\n",(int)j.BYTE );
2.You can assign value bit by bit
i.BIT.bit0 = 1; // set bit0 of i.BYTE
i.BIT.bit1 = 1;
i.BIT.bit4 = 1;
printf("%d \n\n",(int)i.BYTE );
3.You can assign directly a BYTE with hexa decimal value
i.BYTE=0x10;
printf("%d \n\n",(int)i.BYTE );
4.You can assign directly a BYTE with decimal value
i.BYTE=100;
printf("%d \n\n",(int)j.BYTE );
5.You can assign directly with the Identifier of same type
j.BYTE=0x30;
printf("%d \n\n",(int)j.BYTE );
i=j;
printf("%d \n\n",(int)i.BYTE );
6.Assign a decimal value and check it in printing both decimal and hexa decimal format
j.BYTE=100;
printf("%d \n\n",(int)j.BYTE );
printf("%x \n\n",(int)j.BYTE );
j.BIT.bit4=0;
j.BIT.bit5=0;
printf("%d \n\n",(int)j.BYTE );
printf("%x \n\n",(int)j.BYTE );

Two's complement stm32 c

I have a number that is "significant byte", it may be 0 or 255.
Which means 0 or -1.
How to convert 255 to -1 in one time.
I have a function that doesn't works for me:
acc->x = ((raw_data[1]) << 8) | raw_data[0];
Assuming that every 8th bit set to 1 means negative (254 == -2) then a widening conversion from signed types should do:
int n = (signed char)somebyte;
so
unsigned char rawdate[2] = ...;
int msbyte = (signed char)rawdata[1];
acc->x = (msbyte << 8) | (raw_data[0] & 0xFF);
I am not sure what is required but here are the rules for arithmetic conversions of integers.
If an integer is assigned to another lower bit integer, the data will be truncated.
Example:
struct A {
int c1 : 8;
unsigned c2 : 8;
} a;
int main()
{
short int i = 255; // right 8 bits containing all bits set
a.c1 = i; // or a.c1 = 255. casting not required.
a.c2 = i; // same as above.
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
i = 511; // 9 number of 1 bits
a.c1 = i; // left 9th bit will be truncated. casting not required.
a.c2 = i; // same as above
// prints -1, 255
printf("c1: %d c2: %d\n", a.c1, a.c2);
return 0;
}
If a signed 8 bit integer (or char) is assigned to higher bit integer (say int), it's sign bit will be shifted.
ex:
char c = 255; // which is -1
int i = c; // i is now -1. sign bit will be shifted to 32nd bit.

how to store 8 bits in char using C

what i mean is that if i want to store for example 11110011 i want to store it in exactly 1 byte in memory not in array of chars.
example:
if i write 10001111 as an input while scanf is used it only get the first 1 and store it in the variable while what i want is to get the whole value into the variable of type char just to consume only one byte of memory.
One way to write that down would be something like this:
unsigned char b = 1 << 7 |
1 << 6 |
1 << 5 |
1 << 4 |
0 << 3 |
0 << 2 |
1 << 1 |
1 << 0;
Here's a snippet to read it from a string:
int i;
char num[8] = "11110011";
unsigned char result = 0;
for ( i = 0; i < 8; ++i )
result |= (num[i] == '1') << (7 - i);
like this....
unsigned char mybyte = 0xF3;
Using a "bit field"?
#include <stdio.h>
union u {
struct {
int a:1;
int b:1;
int c:1;
int d:1;
int e:1;
int f:1;
int g:1;
int h:1;
};
char ch;
};
int main()
{
union u info;
info.a = 1; // low-bit
info.b = 1;
info.c = 0;
info.d = 0;
info.e = 1;
info.f = 1;
info.g = 1;
info.h = 1; // high-bit
printf("%d %x\n", (int)(unsigned char)info.ch, (int)(unsigned char)info.ch);
}
You need to calculate the number and then just store it in a char.
If you know how binary works this should be easy for you. I dont know how you have the binary data stored, but if its in a string, you need to go through it and for each 1 add the appropriate power of two to a temp variable (initialized to zero at first). This will yield you the number after you go through the whole array.
Look here: http://www.gidnetwork.com/b-44.html
Use an unsigned char and then store the value in it. Simple?
If you have read it from a file and it is in the form of a string then something like this should work:
char str[] = "11110011";
unsigned char number = 0;
for(int i=7; i>=0; i--)
{
unsigned char temp = 1;
if (str[i] == '1')
{
temp <<= (7-i);
number |= temp;
}
}

Resources