combining MSB and LSB in short - c

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

Related

How to write only 12 bits to a char array in C?

I'm trying to implement a FAT12 file system in which there's a FAT table data structure which is an unsigned char array. I need to write a function which given an array index would write a value to the next 12 bits (because it's FAT12) which is quite tricky because part of the value needs to go to one byte and the other part needs to go the half of the second byte.
This is the get value function I came up with:
//FAT is the unsigned char array
int GetFatEntry(int FATindex, unsigned char * FAT) {
unsigned int FATEntryCode; // The return value
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
if (FATindex % 2 == 1){ // If the index is odd
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode >>= 4; // Extract the high-order 12 bits
}
else{ // If the index is even
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode &= 0x0fff; // Extract the low-order 12 bits
}
return FATEntryCode;
}
I'm struggling to come up with the function which would set a value given a FATindex. I would appreciate any suggestions.
This seems to work. The data that should be written should be in the first 12 bits of data
void WriteFatEntry(int FATindex, unsigned char * FAT, unsigned char data[2]) {
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
unsigned char d;
if (FATindex % 2 != 0){ // If the index is odd
// Copy from data to d and e, and shift everything so that second half of
// e contains first half of data[1], and first half of e contains second
// half of data[0], while second half of d contains first half of data[0].
// First half of d contains a copy of first four bits in FAT[FatOffset]
// so that nothing changes when it gets written
unsigned char e=data[1];
e>>=4;
d=data[0];
e|=(d<<4) & 0b11110000;
d>>=4;
d |= FAT[FatOffset] & 0b11110000;
FAT[FatOffset]=d;
FAT[FatOffset+1] = e;
}
else{ // If the index is even
d = data[1] & 0b11110000;
d |= FAT[FatOffset+1] & 0b00001111;
FAT[FatOffset] = data[0];
FAT[FatOffset+1] = d;
}
}
#include <stdio.h>
#if 1 /* assuming MSB first */
#define MSB (idx)
#define LSB (idx+1)
#else /* assuming LSB first */
#define MSB (idx+1)
#define LSB (idx)
#endif
unsigned fat_getval(unsigned char * tab, unsigned num)
{
unsigned idx;
unsigned val;
idx = num + num/2;
val = (tab[MSB] <<8 ) + (tab[idx+1] ) ;
if (num %2 ==0) val >>= 4;
return val & 0xfff;
}
void fat_putval(unsigned char * tab, unsigned slot, unsigned val)
{
unsigned idx;
idx = slot + slot/2;
if (slot %2 ==0) { /* xyz_ */
val <<= 4;
val |= tab[LSB] & 0xf;
}
else { /* _xyz */
val |= (tab[MSB] & 0xf0) << 8;
}
tab[MSB] = val >>8;
tab[LSB] = val &0xff;
}
#undef MSB
#undef LSB
unsigned char fattable[] = "\x01\x23\x45\x67\x89\xab"; // 12 nibbles
int main(void)
{
unsigned idx, ret;
for (idx = 0; idx < 6; idx++) { // 6 bytes -> 12 nibbles */
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(0,0xabc):\n");
fat_putval(fattable, 0, 0xabc);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(3,0xdef):\n");
fat_putval(fattable, 3, 0xdef);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Get(0 to 4):\n");
for (idx = 0; idx < 4; idx++) { // 12 / 3 ~> 4 * 12bit entries
ret = fat_getval( fattable, idx);
printf("%u := %x\n", idx, ret );
}
printf("\n");
return 0;
}

Converting a hex-string into two different context of decimal num. in C

I have a string say:
char *hexstring = "08fc0021";
this is a concatenation of two information each two bytes long.
The first two bytes of this string, ie.: 08fc corresponds to 2300 in dec.
the last 4 bytes, ie., 0021 -> 33.
My problem is to convert this string into two different variables, say:
int varA, varB;
here varA will have the number 2300, and varB = 33.
normally I would have used sscanf to convert the string into a decimal num.
but now i have this problem of a concatenated string with two different info.
any idea suggestion how to nail this ?
thx in advance
Bitwise AND to the Rescue!
So, doing what you require can be done using the bitwise AND opperator on the resulting 32bit number (int?) you get from sscanf.
You first get the number from the string:
char* hexstring = "0x08fc0021";
int num = 0;
sscanf(hexstring, "%x", &num); //put the number into num.
Then you get the bits you want using &:
int varA=0, varB=0;
varA = num & 0xFFFF; //will get the second half.
varB = num & 0xFFFF0000;
varB = varB >> 16; // now you have the first half as well.
And there you have it.
int main(int argc, char *argv[]) {
char *hexstring = "08fc0021";
unsigned long hexnumber = 0u;
unsigned short a = 0u;
unsigned short b = 0u;
/* Use sscanf() to convert the string to integer */
sscanf(hexstring, "%x", &hexnumber);
/* Use bitwise and to filter out the two higher bytes *
* and shift it 16 bits right */
a = ((hexnumber & 0xFFFF0000u) >> 16u);
/* Use bitwise AND to filter out the two lower bytes */
b = (hexnumber & 0x0000FFFFu);
printf("0x%X 0x%X\n",a,b);
return 0;
}
You can use this approach (bit operations):
char *hexstring = "08fc0021";
int aux;
sscanf(hexstring, "%x", &aux);
printf("aux = 0x%x = %d\n", aux, aux);
int varA = (aux & 0xFFFF0000) >> 16, varB = aux & 0x0000FFFF;
printf("varA = 0x%x = %d\n", varA, varA);
printf("varB = 0x%x = %d\n", varB, varB);
Result:
aux = 0x8fc0021 = 150732833
varA = 0x8fc = 2300
varB = 0x21 = 33
EDIT:
Or this approach (string manipulation):
// requires a hexstring length of 8 or more sophisticated logic
char *hexstring = "08fc0021";
int len = strlen(hexstring);
char varA[5], varB[5];
for(int i = 0; i<len; i++)
{
if(i < 4) varA[i] = hexstring[i];
else varB[i-4] = hexstring[i];
}
varA[4] = varB[4] = '\0';
int varAi, varBi;
sscanf(varA, "%x", &varAi);
sscanf(varB, "%x", &varBi);
printf("varAi = 0x%x = %d\n", varAi, varAi);
printf("varBi = 0x%x = %d\n", varBi, varBi);
Same result:
varAi = 0x8fc = 2300
varBi = 0x21 = 33

Bit Manipulation on char array in c

If I am given a char array of size 8, where I know the the first 3 bytes are the id, the next byte is the message, and the last 3 bytes are the values. How could I use bit manipulation in order to extract the message.
Example: a char array contains 9990111 (one integer per position), where 999 is the id, 0 is the message, and 111 is the value.
Any tips? Thanks!
Given:
the array contains {'9','9','9','0','1','1','1'}
Then you can convert with sscanf():
char buffer[8] = { '9', '9', '9', '0', '1', '1', '1', '\0' };
//char buffer[] = "9990111"; // More conventional but equivalent notation
int id;
int message;
int value;
if (sscanf(buffer, "%3d%1d%3d", &id, &message, &value) != 3)
…conversion failed…inexplicably in this context…
assert(id == 999);
assert(message == 0);
assert(value == 111);
But there's no bit manipulation needed there.
Well, if you want bit manipulation, no matter what, here it goes:
#include <stdio.h>
#include <arpa/inet.h>
int main(void) {
char arr[8] = "9997111";
int msg = 0;
msg = ((ntohl(*(uint32_t *) arr)) & 0xff) - 48;
printf("%d\n", msg);
return 0;
}
Output:
7
Just remember one thing... this does not comply with strict aliasing rules. But you can use some memcpy() stuff to solve it.
Edit #1 (parsing it all, granting compliance with strict aliasing rules, and making you see that this does not make any sense):
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <arpa/inet.h>
int main(void) {
char arr[8] = "9997111";
uint32_t a[2];
unsigned int id = 0, msg = 0, val = 0;
memcpy(a, arr, 4);
memcpy(&a[1], arr + 4, 4);
a[0] = ntohl(a[0]);
a[1] = ntohl(a[1]);
id = ((((a[0] & 0xff000000) >> 24) - 48) * 100) + ((((a[0] & 0xff0000) >> 16)- 48) * 10) + (((a[0] & 0xff00) >> 8)- 48);
msg = (a[0] & 0xff) - 48;
val = ((((a[1] & 0xff000000) >> 24) - 48) * 100) + ((((a[1] & 0xff0000) >> 16)- 48) * 10) + (((a[1] & 0xff00) >> 8)- 48);
printf("%d\n", id);
printf("%d\n", msg);
printf("%d\n", val);
return 0;
}
Output:
999
7
111
The usual way would be to define a structure with members which are bit fields and correspond to the segmented information in your array. (oh, re-reading your question: is the array filled with { '9', '9',...}?? Then you'd just sscanf the values with the proper offset into the array.
You can use Memory Copy to extract the values. Here is an example
char *info = malloc(sizeof(int)*3);
char *info2 = malloc(sizeof(int)*1);
char *info3 = malloc(sizeof(int)*3);
memcpy(info,msgTest, 3);
memcpy(info2,msgTest+3, 1);
memcpy(info3,msgTest+4, 3);
printf("%s\n", msgTest);
printf("ID is %s\n", info);
printf("Code is %s\n", info2);
printf("Val is %s\n", info3);
Lets say string msgTest = "0098457
The print statement willl goes as follows..
ID is 009
Code is 8
Val is 457
Hope this helps, Good luck!
here is an example in which i don't use malloc or memory copy for a good implementation on embedded devices, where the stack is limited. Note there is no need to use compact because it is only 1 byte. This is C11 implementation. If you have 4 Bytes for example to be analyzed, create another struct with 4 charbits, and copy the address to the new struct instead. This is coinstance with design patterns concept for embedded.
#include <stdio.h>
// start by creating a struct for the bits
typedef struct {
unsigned int bit0:1; //this is LSB
unsigned int bit1:1; //bit 1
unsigned int bit2:1;
unsigned int bit3:1;
unsigned int bit4:1;
unsigned int bit5:1;
unsigned int bit6:1;
unsigned int bit7:1;
unsigned int bit8:1;
}charbits;
int main()
{
// now assume we have a char to be converted into its bits
char a = 'a'; //asci of a is 97
charbits *x; //this is the character bits to be converted to
// first convert the char a to void pointer
void* p; //this is a void pointer
p=&a; // put the address of a into p
//now convert the void pointer to the struct pointer
x=(charbits *) p;
// now print the contents of the struct
printf("b0 %d b1 %d b2 %d b3 %d b4 %d b5 %d b6 %d b7 %d", x->bit0,x->bit1, x->bit2,x->bit3, x->bit4, x->bit5, x->bit6, x->bit7, x->bit8);
// 97 has bits like this 01100001
//b0 1 b1 0 b2 0 b3 0 b4 0 b5 1 b6 1 b7 0
// now we see that bit 0 is the LSB which is the first one in the struct
return 0;
}
// thank you and i hope this helps

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

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