I'm reading the values from a SD card in an ARM micro:
Res = f_read(&fil, (void*)buf, 6, &NumBytesRead);
where fil is a pointer, buf is a buffer where the data is stored.
And that's the problem: it's an array but I'd like to have the contents of that array in a single variable.
To give an actual example: the 6 bytes read from the file are:
buf[0] = 0x1B
buf[1] = 0x26
buf[2] = 0xB3
buf[3] = 0x54
buf[4] = 0xA1
buf[5] = 0xCF
And I'd like to have: uint64_t data be equal to 0x1B26B354A1CF. That is, all the elements of the array "concatenated" in one single 64 bit integer.
Without type punning you can do as below.
uint64_t data = 0;
for (int i=0; i<6; i++)
{
data <<= 8;
data |= (uint64_t) buf[i];
}
Use union but remember about the endianes.
union
{
uint8_t u8[8];
uint64_t u64;
}u64;
typedef union
{
uint8_t u8[8];
uint64_t u64;
}u64;
typedef enum
{
LITTLE_E,
BIG_E,
}ENDIANESS;
ENDIANESS checkEndianess(void)
{
ENDIANESS result = BIG_E;
u64 d64 = {.u64 = 0xff};
if(d64.u8[0]) result = LITTLE_E;
return result;
}
uint64_t arrayToU64(uint8_t *array, ENDIANESS e) // for the array BE
{
u64 d64;
if(e == LITTLE_E)
{
memmove(&d64, array, sizeof(d64.u64));
}
else
{
for(int index = sizeof(d64.u64) - 1; index >= 0; index--)
{
d64.u8[sizeof(d64.u64) - index - 1] = array[index];
}
}
return d64.u64;
}
int main()
{
uint8_t BIG_E_Array[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80};
ENDIANESS e;
printf("This system endianess: %s\n", (e = checkEndianess()) == BIG_E ? "BIG":"LITTLE");
printf("Punned uint64_t for our system 0x%lx\n", arrayToU64(BIG_E_Array, e));
printf("Punned uint64_t for the opposite endianess system 0x%lx\n", arrayToU64(BIG_E_Array, e == BIG_E ? LITTLE_E : BIG_E));
return 0;
}
To things to take care of here:
have the bytes be ordered correctly
read the six bytes into one 64bit integer
Issue 1 can be taken care of by storing the byte coming in in network byte order (Big Endian) into the 64 bit integer in host byte order by for example using the two marcos below:
/* below defines of htonll() and ntohll() are taken from this answer:
https://stackoverflow.com/a/28592202/694576
*/
#if __BIG_ENDIAN__
# define htonll(x) (x)
# define ntohll(x) (x)
#else
# define htonll(x) ((uint64_t)htonl((x) & 0xFFFFFFFF) << 32) | htonl((x) >> 32))
# define ntohll(x) ((uint64_t)ntohl((x) & 0xFFFFFFFF) << 32) | ntohl((x) >> 32))
#endif
Issue 2 can be solved in multiple ways:
Extending your approach
#define BUFFER_SIZE (6)
...
assert(BUFFER_SIZE <= sizeof (uint64_t));
uint8_t buffer[BUFFER_SIZE];
FILE * pf = ...; /* open file here */
/* test if file has been opened successfully here */
... result = f_read(pf, buffer, BUFFER_SIZE, ...);
/* test result for success */
uint64_t number = 0;
memset(&number, buffer, BUFFER_SIZE)
number = ntohll(number);
Use "Type Punning" by using a union
union buffer_wrapper
{
uint8_t u8[sizeof (uint64_t)];
uint64_t u64;
}
Instead of
uint8_t buffer[BUFFER_SIZE];
use
union buffer_wrapper buffer;
and instead of
memcpy(&number, buffer, BUFFER_SIZE)
number = ntohll(number)
use
number = ntohll(buffer.u64)
Related
I am trying to store a uint64_t representation of a crc64 checksum as an array.
The checksum will always be like uint64_t res = 0x72e3daa0aa188782, so the I want that to be stored as an array, char digest[8], where digest[0] is 72, digest[1] is e3... digest[7] is 82.
I attempted looping/dividing to break up the number, but that would be more appropriate if it was a smaller integer, and if the starting point was Base-10, as the starting point is Base-16, the output should but what is described above.
Update: I removed the nonsensical code and wish I can accept all three answers, as they all did what I asked. The bit shifting is what I was hoping to get as an answer so it is why it is accepted.
Shifting and bit-wise AND can also do what you need. For instance
unsigned char digest[8];
int shift = 56;
for (int i = 0; i < 8; ++i)
{
digest[i] = (res >> shift) & 0xff;
shift -= 8;
}
If it's okay to change the value of res another approach is:
for (int i = 7; i >= 0; --i)
{
digest[i] = res & 0xff;
res >>= 8;
}
You should use division by 256, not by 10:
unsigned char digest[sizeof(uint64_t) / sizeof(char)];
for (int i = sizeof(digest) - 1; i >= 0; i--) {
digest[i] = res % 256; // get the last byte
res /= 256; // get the remainder
}
// for demo purposes
for (int i = 0; i < sizeof(digest); i++) {
printf("%x ", digest[i]);
}
// 72 e3 da a0 aa 18 87 82
Obviously if you divide by 10 you'll get the decimal digits instead of what you expected. In this case you just want to get the underlying bits of uint64_t which can be done with a simple memcpy. But you're expecting the bytes in big endian order so you'll also need to convert to big endian first
uint64_t number = 0x72e3daa0aa188782ull;
#ifdef __unix__
uint64_t number_be = htonll(number);
#else
uint64_t number_be = htobe64(number);
#endif
char digest[8];
memcpy(&digest, &number_be , sizeof number);
In C it can also be done with a union
union Digest
{
uint64_t res;
char bytes[8];
} digest;
digest.res = htonll(0x72e3daa0aa188782ull); // or htobe64
// now just use digest.bytes[]
These need only a few machine instructions, hence would be far faster than looping 8 times just to get the 8 bytes
I think you can just use a union here.
union foo {
uint64_t u64;
uint8_t u8[8];
};
This saves you from having to do any conversion. You can access the 64-bit value using foo.u64 or the 8-bit values using foo.u8[0] to foo.u8[7].
try this:
#define INIT_LIST \
201234567890123456, \
12345678901234567890, \
98765432109876543, \
65432109887, \
12345234512345, \
217631276371261627, \
12354123512453124, \
2163521442531, \
2341232142132321, \
1233432112
#define STR_(...) #__VA_ARGS__
#define STR(x) STR_(x)
int main (void)
{
uint64_t numbers[10] = { INIT_LIST };
char array[] = STR(INIT_LIST);
puts(array);
}
i am currently trying to figure out an elegant and convinient way to store 4 14-bit values and 1 8-bit value within a 64 bit boundary.
something like this:
typedef struct my64bit{
unsigned data1 : 14;
unsigned data2 : 14;
unsigned data3 : 14;
unsigned data4 : 14;
unsigned other : 8;
}tmy64Bit;
later I wan't to create an array of these 'containers'
tmy64Bit myArray[1000];
so that i have a pointer "myArray" wich points to 1000x64-bits of memory
this array is send via tcp to an embedded-linux SOCFPGA system where it should be copied (with correction of endianess and network byte order) into a specific memory (directly accessible from the fpga)
my problem is that the upper code doesn't create a 64-bit type
sizeof(tmy64Bit)
returns 12, so 12 bytes are allocated instead of 8
filling the struct with data and watching the memory (on my 64 bit linux system) returns this
tmy64Bit test;
memset(&test,0,sizeof(tmy64Bit));
test.data1 = 0x3fff;
...
test.other = 0xAA;
Memory View:
after d1 written = 0xFF3F0000 00000000 00000000
after d2 written = 0xFFFFFF0F 00000000 00000000
after d3 written = 0xFFFFFF0F FF3F0000 00000000
after d4 written = 0xFFFFFF0F FFFFFF0F 00000000
after o written = 0xFFFFFF0F FFFFFF0F AA000000
so the first 2 14 bit variables are stored correctly but then padding fills up the last half-byte and at the end the last byte needs to be stored in a new 64 bit cell
an other aproach would be
typedef struct my2nd64Bit{
uint8_t data[7];
uint8_t other;
}tmy2nd64Bit;
where a
sizeof(tmy2nd64Bit)
returns an 8 (which was expected)
This generates correctly padded structure, but storing the 14 bit always involves a lot of bitshifting and masking
Avoid bit-fields, they are so poorly defined by the C standard that they can barely be used in practice. Your bit-field struct code contains something around 5 to 10 different forms of poorly-specified behavior. C standard bit-fields is a dangerous and superfluous feature, simple as that.
Instead, simply use a raw array of binary values, something like this:
typedef union {
uint8_t array [sizeof(uint64_t)];
uint64_t val64;
}tmy64Bit;
(Note that the uint64_t in the union will be endianess-dependent)
The de facto way to set and clear bits in such a raw array is:
void set_bit (tmy64Bit* x, size_t bit)
{
x->array [bit / 8] |= 1 << (bit % 8);
}
void clear_bit (tmy64Bit* x, size_t bit)
{
x->array [bit / 8] &= ~(1 << (bit % 8));
}
Or if you will, a more readable version (equivalent):
void set_bit (tmy64Bit* x, size_t bit)
{
uint8_t byte_index = bit / 8;
uint8_t bit_index = bit % 8;
x->array[byte_index] |= 1 << bit_index;
}
This is what you want :
typedef struct my64bit{
uint64_t data1 : 14;
uint64_t data2 : 14;
uint64_t data3 : 14;
uint64_t data4 : 14;
uint64_t other : 8;
}tmy64Bit;
unsigned means unsigned int, and this type is 32-bit on most systems. This will cause padding because the individual fields won't be allowed to cross 32-bit boundaries. Using a 64-bit member type won't add padding for this case (you don't cross any 64-bit boundary).
As for any question about bit-fields, you need to remember that most of the bit-field mechanics are implementation defined, which means that if you want to use that, you should check that you actually get what you want. Also, if you plan to use another compiler, check that the behavior is the same (usually it is, but maybe not on exotic platforms). If you properly check, this is safe to use (not undefined behavior), but you might want to use a more portable way, using bit operations for example.
I agree with Lundin's answer, but for this particular situation, my implementation would be a bit different (no pun).
First, I would decide how to pack the fields into each 64-bit word. For example:
Bits Description
0-13 data[0]
14-27 data[1]
28-41 data[2]
42-55 data[3]
56-64 other
Second, I would use a dynamically allocated structure with the FPGA data in a C99 flexible array member, to describe the target device:
typedef struct {
/* Other FPGA-related fields, maybe
* a struct sockaddr_in or _in6
* to identify the FPGA */
size_t words;
uint64_t word[];
} fpga;
fpga *fpga_create(const size_t words)
{
fpga *f;
f = malloc(sizeof (fpga) + word * sizeof(f->word[0]));
if (!f)
return NULL;
f->words = words;
memset(f->word, 0, f->words * sizeof (f->word[0]));
return f;
}
Third, I would use static inline accessors to manipulate the data:
static inline unsigned int fpga_get_data(const fpga *f, const int w, const int i)
{
assert(f != NULL);
assert(w >= 0 && (size_t)w < f->words);
assert(i >= 0 && i < 4);
return (f->word[(size_t)w] >> (i * 14)) & 0x3FFFU;
}
static inline unsigned int fpga_get_other(const fpga *f, const int w)
{
assert(f != NULL);
assert(w >= 0 && (size_t)w < f->words);
return (f->word[(size_t)w] >> 56) & 0xFFU;
}
static inline void fpga_set_data(const fpga *f, const int w, const int i,
const unsigned int value)
{
assert(f != NULL);
assert(w >= 0 && (size_t)w < f->words);
assert(i >= 0 && i < 4);
f->word[(size_t)w] = (f->word[(size_t)w] & (~(0x3FFFU << (i*14))))
| ((value & 0x3FFFU) << (i*14));
}
static inline void fpga_set_other(const fpga *f, const int w, const unsigned int value)
{
assert(f != NULL);
assert(w >= 0 && (size_t)w < f->words);
f->word[(size_t)w] = (f->word[(size_t)w] & (uint64_t)0x00FFFFFFFFFFFFFFULL)
| ((value & 0xFFU) << 56);
}
Above, w is the index to the word, and i is the index of the data entry (0 to 3). If you want a continuous data array, you could use
static inline unsigned int fpga_get_data(const fpga *f, const int i)
{
assert(f != NULL);
assert(i >= 0 && (size_t)i < 4 * f->words);
return (f->word[(size_t)i / 4] >> ((i & 3) * 14)) & 0x3FFFU;
}
if (f != NULL &&
i >= 0 && i < (size_t)4 * f->words)
return (f->word[(size_t)i / 4] >> ((i & 3) * 14)) & 0x3FFFU;
else
return 0U; /* Or abort with an error */
}
static inline void fpga_set_data(const fpga *f, const int i, const unsigned int value)
{
assert(f != NULL);
assert(i >= 0 && (size_t)i / 4 < f->words);
f->word[(size_t)i / 4] = (f->word[(size_t)i / 4] & (~(0x3FFFU << ((i & 3) * 14))))
| ((value & 0x3FFFU) << ((i & 3) * 14));
}
The accessors should be defined in the header file that defines the structure.
Note that if other is actually some sort of checksum for the four data fields, I would calculate them just before sending.
I am new to c language and having some trouble in a program.I have 3 arrays
size = 8;
u8 a [size]; // a = 0x0D
u8 b [size]; // b= 0xDE
u16 new_buffer[size]; // i want to see as 0xDE0D on the terminal
I need to move the contents of a as Lower order byte and contents of b as higher order byte in the new_buffer and later right shift the the new_buffer by three bits. I read about it and was suggested to use two for loops. I tried it but not getting appropriate output.
please help me for this..
u8 SendBuffer[BUFFER_SIZE];
u8 RecvBuffer[BUFFER_SIZE];
u16 Buffer[BUFFER_SIZE];
int main(void) {
RecvBuffer[0] = 0x00;
RecvBuffer[1] = 0x0D;
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
printf("Sensor data is = 0x%x \n\r", RecvBuffer[0]);
printf("---Data received successfully---\n\r");
return 0;
}
Thanks
Two versions here, depending on the endian-ness
for (i=0; i<BUFFER_SIZE; i++) {
// little endian
new_buffer[i] = (u16)a[i] << 8 | (u16)b[i]);
// big endian
new_buffer[i] = (u16)b[i] << 8 | (u16)a[i]);
// bit shift
new_buffer[i] >>= 3;
}
Or, to rotate the buffer 3 bits to the right
u16 bits, prev = 0;
for (i=0; i<BUFFER_SIZE; i++) {
bits = new_buffer[i];
new_buffer[i] = bits >> 3 | prev;
prev = bits << (sizeof(u16)*8 - 3);
}
Note that u8 is not part of the standard, you mean uintX_t, and these values are not arrays but variables:
uint8_t a = 0X0D;
uint8_t b = 0XDE;
uint16_t new_buffer = ((uint16_t)b << 8) | a;
As pointed out by #WeatherVane, you need to reverse those values if you are under big endian:
uint16_t new_buffer = ((uint16_t)a << 8) | b;
I am trying to create a 48-bit integer value. I understand it may be possible to use a char array or struct, but I want to be able to do bit masking/manipulation and I'm not sure how that can be done.
Currently the program uses a 16-bit uint and I need to change it to 48. It is a bytecode interpreter and I want to expand the memory addressing to 4GB. I could just use 64-bit, but that would waste a lot of space.
Here is a sample of the code:
unsigned int program[] = { 0x1064, 0x11C8, 0x2201, 0x0000 };
void decode( )
{
instrNum = (program[i] & 0xF000) >> 12; //the instruction
reg1 = (program[i] & 0xF00 ) >> 8; //registers
reg2 = (program[i] & 0xF0 ) >> 4;
reg3 = (program[i] & 0xF );
imm = (program[i] & 0xFF ); //pointer to data
}
full program: http://en.wikibooks.org/wiki/Creating_a_Virtual_Machine/Register_VM_in_C
You can use the bit fields which are often used to represent integral types of known, fixed bit-width. A well-known usage of bit-fields is to represent a set of bits, and/or series of bits, known as flags. You can apply bit operations on them.
#include <stdio.h>
#include <stdint.h>
struct uint48 {
uint64_t x:48;
} __attribute__((packed));
Use a structure or uint16_t array with special functions for an array of uint48.
For individual instances, use uint64_t or unsigned long long. uint64_t will work fine for individually int48, but may want to mask off the results operations like * or << to keep upper bits cleared. Just some space saving routines are needed for arrays.
typedef uint64_t uint48;
const uint48 uint48mask = 0xFFFFFFFFFFFFFFFFull;
uint48 uint48_get(const uint48 *a48, size_t index) {
const uint16_t *a16 = (const uint16_t *) a48;
index *= 3;
return a16[index] | (uint32_t) a16[index + 1] << 16
| (uint64_t) a16[index + 2] << 32;
}
void uint48_set(uint48 *a48, size_t index, uint48 value) {
uint16_t *a16 = (uint16_t *) a48;
index *= 3;
a16[index] = (uint16_t) value;
a16[++index] = (uint16_t) (value >> 16);
a16[++index] = (uint16_t) (value >> 32);
}
uint48 *uint48_new(size_t n) {
size_t size = n * 3 * sizeof(uint16_t);
// Insure size allocated is a multiple of `sizeof(uint64_t)`
// Not fully certain this is needed - but doesn't hurt.
if (size % sizeof(uint64_t)) {
size += sizeof(uint64_t) - size % sizeof(uint64_t);
}
return malloc(size);
}
I have a buffer of bits with 8 bits of data followed by 1 parity bit. This pattern repeats itself. The buffer is currently stored as an array of octets.
Example (p are parity bits):
0001 0001 p000 0100 0p00 0001 00p01 1100 ...
should become
0001 0001 0000 1000 0000 0100 0111 00 ...
Basically, I need to strip of every ninth bit to just obtain the data bits. How can I achieve this?
This is related to another question asked here sometime back.
This is on a 32 bit machine so the solution to the related question may not be applicable. The maximum possible number of bits is 45 i.e. 5 data octets
This is what I have tried so far. I have created a "boolean" array and added the bits into the array based on the the bitset of the octet. I then look at every ninth index of the array and through it away. Then move the remaining array down one index. Then I've got only the data bits left. I was thinking there may be better ways of doing this.
Your idea of having an array of bits is good. Just implement the array of bits by a 32-bit number (buffer).
To remove a bit from the middle of the buffer:
void remove_bit(uint32_t* buffer, int* occupancy, int pos)
{
assert(*occupancy > 0);
uint32_t high_half = *buffer >> pos >> 1;
uint32_t low_half = *buffer << (32 - pos) >> (32 - pos);
*buffer = high_half | low_half;
--*occupancy;
}
To add a byte to the buffer:
void add_byte(uint32_t* buffer, int* occupancy, uint8_t byte)
{
assert(*occupancy <= 24);
*buffer = (*buffer << 8) | byte;
*occupancy += 8;
}
To remove a byte from the buffer:
uint8_t remove_byte(uint32_t* buffer, int* occupancy)
{
uint8_t result = *buffer >> (*occupancy - 8);
assert(*occupancy >= 8);
*occupancy -= 8;
return result;
}
You will have to arrange the calls so that the buffer never overflows. For example:
buffer = 0;
occupancy = 0;
add_byte(buffer, occupancy, *input++);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 7);
*output++ = remove_byte(buffer, occupancy);
add_byte(buffer, occupancy, *input++);
remove_bit(buffer, occupancy, 6);
*output++ = remove_byte(buffer, occupancy);
... (there are only 6 input bytes, so this should be easy)
In pseudo-code (since you're not providing any proof you've tried something), I would probably do it like this, for simplicity:
View the data (with parity bits included) as a stream of bits
While there are bits left to read:
Read the next 8 bits
Write to the output
Read one more bit, and discard it
This "lifts you up" from worrying about reading bytes, which no longer is a useful operation since your bytes are interleaved with bits you want to discard.
I have written helper functions to read unaligned bit buffers (this was for AVC streams, see original source here). The code itself is GPL, I'm pasting interesting (modified) bits here.
typedef struct bit_buffer_ {
uint8_t * start;
size_t size;
uint8_t * current;
uint8_t read_bits;
} bit_buffer;
/* reads one bit and returns its value as a 8-bit integer */
uint8_t get_bit(bit_buffer * bb) {
uint8_t ret;
ret = (*(bb->current) >> (7 - bb->read_bits)) & 0x1;
if (bb->read_bits == 7) {
bb->read_bits = 0;
bb->current++;
}
else {
bb->read_bits++;
}
return ret;
}
/* reads up to 32 bits and returns the value as a 32-bit integer */
uint32_t get_bits(bit_buffer * bb, size_t nbits) {
uint32_t i, ret;
ret = 0;
for (i = 0; i < nbits; i++) {
ret = (ret << 1) + get_bit(bb);
}
return ret;
}
You can use the structure like this:
uint_8 * buffer;
size_t buffer_size;
/* assumes buffer points to your data */
bit_buffer bb;
bb.start = buffer;
bb.size = buffer_size;
bb.current = buffer;
bb.read_bits = 0;
uint32_t value = get_bits(&bb, 8);
uint8_t parity = get_bit(&bb);
uint32_t value2 = get_bits(&bb, 8);
uint8_t parity2 = get_bit(&bb);
/* etc */
I must stress that this code is quite perfectible, proper bound checking must be implemented, but it works fine in my use-case.
I leave it as an exercise to you to implement a proper bit buffer reader using this for inspiration.
This also works
void RemoveParity(unsigned char buffer[], int size)
{
int offset = 0;
int j = 0;
for(int i = 1; i + j < size; i++)
{
if (offset == 0)
{
printf("%u\n", buffer[i + j - 1]);
}
else
{
unsigned char left = buffer[i + j - 1] << offset;
unsigned char right = buffer[i + j] >> (8 - offset);
printf("%u\n", (unsigned char)(left | right));
}
offset++;
if (offset == 8)
{
offset = 0;
j++; // advance buffer (8 parity bit consumed)
}
}
}