I am trying to align compound literal to 16 bytes.
I found this
which is :
#define ALIGNED_STRING(S) (struct { _Alignas(16) char s[sizeof S]; }){ S }.s
char *u = ALIGNED_STRING("agsdas");
which compiles.
and tried to apply it to uint32_t.
I tried this so far with gcc.
#define BLOCK_ALIGNED_U32(...) (struct { _Alignas(16) uint32_t x[sizeof ((uint32_t[]){__VA_ARGS__})]; }){ __VA_ARGS__ }.x
uint32_t toto[] = BLOCK_ALIGNED_U32(0x11111111, 0x22222222);
and even:
uint32_t tata[] = (struct { uint32_t __attribute__((aligned(16))) x[2]; }){.x = {0x11111111, 0x22222222}}.x;
but it gives me error : invalid initializer
What am I doing wrong / missing?
note: I am doing this because I want to control the aligment of some data block inside a structure declaration, like this:
struct
{
uint32_t* foo1;
uint32_t* foo2;
uint32_t* foo3;
uint32_t* foo4;
}s_t;
s_t foo[]=
{
.foo1 = BLOCK_ALIGNED_U32(1,2,3),
.foo2 = BLOCK_ALIGNED_U32(2,2),
.foo3 = (uint32_t[]){1,2,3},//could be not 16-bytes-aligned
.foo4 = (uint32_t[]){2,2},//could be not 16-bytes-aligned
}
At least these issues:
OP's macro array sizing was wrong.
// uint32_t x[sizeof ((uint32_t[]){__VA_ARGS__})]
uint32_t x[sizeof ((uint32_t[]){__VA_ARGS__}) / sizeof(uint32_t)]
Add { }
// OP's
#define ALIGNED_U32(...) (struct { _Alignas(16) uint32_t x[sizeof ((uint32_t[]){ __VA_ARGS__}) ]; }){ __VA_ARGS__ }.x
// Suggested fix
#define ALIGNED_U32(...) (struct { _Alignas(16) uint32_t x[sizeof ((uint32_t[]){ __VA_ARGS__})/sizeof(uint32_t)]; }){ { __VA_ARGS__ } }.x
Sample usage
#define ALIGNED_U32(...) (struct { _Alignas(16) uint32_t x[ \
sizeof ((uint32_t[]){ __VA_ARGS__ })/sizeof(uint32_t) \
]; }) { .x = { __VA_ARGS__ } }.x
typedef struct {
uint32_t *foo1;
uint32_t *foo2;
uint32_t *foo3;
uint32_t *foo4;
} s_t;
s_t foo = { //
.foo1 = ALIGNED_U32(1, 2, 3), //
.foo2 = ALIGNED_U32(2, 2), //
.foo3 = (uint32_t[]) {1, 2, 3}, // might be not 16-bytes-aligned
.foo4 = (uint32_t[]) {2, 2}, // might be not 16-bytes-aligned
};
Alignment is determined by the type of the object and directives associated with the object itself. It isn't determined by the value from which it is initialized.
In other words, there's nothing you can place on the right of uint32_t foo[] = that will affect how the array or individual elements of the array are aligned.
Let's compare.
In the linked post
char *u = ALIGNED_STRING("agsdas");
This produces two objects.
u <anon>
alignment = char* alignment = 16
+----------------+ +---+---+---+-...-+
| -------------->| a | g | s | ... |
+----------------+ +---+---+---+-...-+
As you can see, ALIGNED_STRING has no effect on the alignment of the variable (u), just the alignment of the anon object to which u will point.
In your post
uint32_t foo[] = ...;
This produces a single object.
foo
alignment = uint32_t[] = uint32_t
+----------------+
| |
+----------------+
| |
+----------------+
| |
⋮ ⋮
| |
+----------------+
If you had an array of pointers to uint32_t, you could align those uint32_t as you wish.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
int main( void ){
_Alignas( 16 ) uint32_t i1 = 1;
_Alignas( 16 ) uint32_t i2 = 2;
uint32_t i3 = 3;
uint32_t i4 = 4;
uint32_t *ptrs[] = {
&i1,
&i2,
&i3,
&i4,
};
size_t n = sizeof(ptrs)/sizeof(*ptrs);
for ( size_t i=0; i<n; ++i ) {
uint32_t *ptr = ptrs[i];
printf( "%p %" PRIu32 "\n", (void *)ptr, *ptr );
}
}
We can even make those object anonymous. Anonymous objects can be created using the ( type ){ initializer body } syntax, and can use _Alignas as part of the type to align the object.
#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>
#define ALIGNED_UINT32( S, I ) ( ( _Alignas( S ) uint32_t ){ I } )
#define ANON_UINT32( I ) ( ( uint32_t ){ I } )
int main( void ){
uint32_t *ptrs[] = {
&ALIGNED_UINT32( 16, 1 ),
&ALIGNED_UINT32( 16, 2 ),
&ANON_UINT32( 3 ),
&ANON_UINT32( 4 ),
};
size_t n = sizeof(ptrs)/sizeof(*ptrs);
for ( size_t i=0; i<n; ++i ) {
uint32_t *ptr = ptrs[i];
printf( "%p %" PRIu32 "\n", (void *)ptr, *ptr );
}
}
Both of the above produce five objects.
ptrs
alignment = uint32_t*
+----------------+ +---+---+---+---+ i1/<anon>
| -------------------------->| 1 | alignment = 16
+----------------+ +---+---+---+---+
| ----------------------+
+----------------+ | +---+---+---+---+ i2/<anon>
| -----------------+ +--->| 2 | alignment = 16
+----------------+ | +---+---+---+---+
| ------------+ |
+----------------+ | | +---+---+---+---+ i3/<anon>
| +-------->| 3 | alignment = uint32_t
| +---+---+---+---+
|
| +---+---+---+---+ i4/<anon>
+------------->| 4 | alignment = uint32_t
+---+---+---+---+
Sample run:
0x7ffe29b31b30 1
0x7ffe29b31b20 2
0x7ffe29b31b1c 3
0x7ffe29b31b18 4
Demo on Compiler Explorer
Related
Can somebody explain to me what happens with br agument in union, after assigning str.a and str.b? We need to set that value before calling the function above? I tried to run the code in simulator https://pythontutor.com/render.html#mode=display which says that the value of br is 516 before calling the function. How is that possible?
#include <stdio.h>
void f(short num, short* res){
if (num){
*res = *res * 10 + num%10;
f(num / 10, res);
}}
typedef union {
short br;
struct {
char a, b;
} str;
} un;
void main() {
short res = 0; un x;
x.str.a = 4; x.str.b = 2;
f(x.br, &res); x.br = res;
printf("%d %d %d\n", x.br, x.str.a, x.str.b);}
Assuming that char is one byte and short is two bytes (the most common), then it's really simple.
Begin by drawing out the members of the union on a piece of paper, one member next to the other. Something like this:
br str
+---+ +---+
| | | | a
+---+ +---+
| | | | b
+---+ +---+
Now we do the assignments:
x.str.a = 4;
x.str.b = 2;
And write the results in the drawing:
br str
+---+ +---+
| 4 | | 4 | a
+---+ +---+
| 2 | | 2 | b
+---+ +---+
Assuming little endianness like on a normal x86 or x86-64 system, then the value of br will be 0x0204 which is 516 in decimal.
So that's where the value 516 is coming from.
The value of the short will depend on the computer's endianess. On a little endian machine, a will correspond to the least significant byte and b to the most significant. Thus when those two bytes are converted to a short, you get the number 0x0204 = 516 decimal.
As a side note, it is a bad idea to use short and char since those may be signed and negative. Use uint16_t and uint8_t instead, whenever dealing with binary arithmetic.
If you put some effort into your debugging you would see what is going on:
void f(short num, short* res)
{
if (num)
{
*res = *res * 10 + num%10;
f(num / 10, res);
}
}
typedef union
{
short br;
struct
{
char a, b;
};
} un;
int main(void)
{
short res = 0; un x;
x.a = 4; x.b = 2;
printf("Before br=0x%04x (%d) a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.br, x.a, x.b, res, res);
f(x.br, &res); x.br = res;
printf("After br=0x%04x a=0x%02x b=0x%02x res = %d 0x%x\n", x.br, x.a, x.b, res, res);
}
result:
efore br=0x0204 (516) a=0x04 b=0x02 res = 0 0x0
After br=0x0267 a=0x67 b=0x02 res = 615 0x267
Do your br was 516 and it was reversed by the f function becoming 615 which is 0x0276. It contains of two bytes 0x02 and 0x67.
Your computer is little-endian so the first byte is 0x67 and the second one is 0x02 because this system stores the least significant byte first.
I have a structure like below:
struct myCoolStuff{
uint32_t stuff1 : 4;
uint32_t stuff2 : 4;
uint32_t stuff3 : 24;
uint32_t differentField;
}
How can I combine these fields into a hex format for printing to the screen or writing out to a file? Thank you.
struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233, .differentField=99};
printf("my combined stuff is: %x\n", <combined stuff>);
printf("My full field is: %x\n", data.differentField);
Expected Output:
my combined stuff is: 0xFF66112233
My different field is: 99
First, you can't get 0xFF out of 0xFF after you put it in a 4-bit variable. 0xFF takes 8 bits. Same for 0x66.
As for reinterpretting the bitfields as a single integer, you could,
in a very nonportable fashion (there's big-endian/little-endian issues and the possibility of padding bits) use a union.
( This:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
struct myCoolStuff{
union{
struct {
uint32_t stuff1 : 4;
uint32_t stuff2 : 4;
uint32_t stuff3 : 24;
};
uint32_t fullField;
};
};
struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233};
int main()
{
printf("My full field is: %" PRIX32 "\n", data.fullField);
}
prints 1122336F on my x86_64. )
To do it portably you can simply take the bitfields and put them together manually:
This:
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
struct myCoolStuff{
uint32_t stuff1 : 4;
uint32_t stuff2 : 4;
uint32_t stuff3 : 24;
};
struct myCoolStuff data = {.stuff1=0xFF, .stuff2=0x66, .stuff3=0x112233};
int main()
{
uint32_t fullfield = data.stuff1 << 28 | data.stuff2 << 24 | data.stuff3;
printf("My full field is: %" PRIX32 "\n", fullfield);
}
should print F6112233 anywhere where it compiles (uint32_t isn't guaranteed to exist (although on POSIX platforms it will); uint_least32_t would've been more portable.)
Be careful to make sure data.stuff1 has enough bits to be shiftable by 28. Yours does because it's typed uint32_t, but it would be safer to do it e.g., with (data.stuff1 + 0UL)<<28 or (data.stuff1 + UINT32_C(0))<<28 and same for the second shift.
Add a union inside of this struct that you can use to reinterpret the fields.
struct myCoolStuff{
union {
struct {
uint32_t stuff1 : 4;
uint32_t stuff2 : 4;
uint32_t stuff3 : 24;
};
uint32_t stuff;
}
uint32_t fullField;
};
...
printf("my combined stuff is: %x\n", data.stuff);
Multiply (using at least uint32_t math) and then print using the matching specifier.
#include <inttypes.h>
struct myCoolStuff{
uint32_t stuff1 : 4;
uint32_t stuff2 : 4;
uint32_t stuff3 : 24;
uint32_t differentField;
}
uint32_t combined stuff = ((uint32_t) data.stuff1 << (4 + 24)) |
((uint32_t) data.stuff2 << 24) | data.stuff3;
printf("my combined stuff is: 0x%" PRIX32 "\n", combined stuff);
printf("My full field is: %x\n", data.differentField);
Maybe something like this will help :
unsigned char *ptr = (unsigned char *)&data; // store start address
int size = sizeof(myCoolStuff); // get size of struct in bytes
while(size--) // for each byte
{
unsigned char c = *ptr++; // get byte value
printf(" %x ", (unsigned)c); // print byte value
}
I am trying to retrieve the raw data bytes from a constant float in C. This is being done to create a readable constant byte array. This can be seen below.
#define FLOAT_TO_BYTES(value) \
(uint8_t)(value), (uint8_t)(value << 8), \
(uint8_t)(value << 16), (uint8_t)(value << 24)
const uint8_t byteArray[] = {
FLOAT_TO_BYTES(11.4)
};
The problem is that I cannot use pointers or any sort of a code block. I know the above doesn't work because you cannot shift a float value. I have tried using unions but cannot get that to work either. Any help would be greatly appreciated!
Here's how you can get the bytes with a union:
#include <stdio.h>
union float_bytes{
float f;
char b[sizeof(float)];
};
int main()
{
union float_bytes fb = { 1.1 };
for(int i=0; i<sizeof(float);i++)
printf("%hhx\n", fb.b[i]);
}
You can also simply just do:
#include <stdio.h>
int main()
{
float f = 1.1;
for(int i=0; i<sizeof(float);i++)
printf("%hhx\n", ((char*)&f)[i]);
}
Inspecting anything via a character pointer is always allowed.
If you really want to, you can put the cast to a (char*) into a macro
and pass in a float pointer or you can create a compound literal temporary in the macro so as to avoid an explicit float variable:
#include <stdio.h>
#define FLOAT_BYTES(Float) ((char*)(&(float){Float}))
int main()
{
for(int i=0; i<sizeof(float);i++)
printf("%hhx\n", FLOAT_BYTES(1.1)[i]);
}
(The lifetime of a compound literal is that of its nearest enclosing block.)
You cannot use byte operations on floats, because they are not standarized.
How can it be done? NOTE: All methods below assume that float is 32 bit wide.
Pointer
#define FLOAT_TO_BYTES(value) (*((unsigned char *) value)), (*(((unsigned char *) value) + 1)), (*(((unsigned char *) value) + 2)), (*(((unsigned char *) value) + 3))
Union
typedef union
{
float f;
unsigned char chars[4];
} __attribute__ ((packed)) floatunion;
// I am lazy:
#define FLOAT_TO_BYTES(value) FLOAT_TO_BYTES0 ((floatunion *) &value)
#define fLOAT_TO_BYTES0(value) value->chars[0], value->chars[1], value->chars[2], value->chars[3]
Use a compound literal of a union, available since C99.
Does not use pointers or shifts. Code needs to specify which byte and order of the float desired.
#define FLOAT_TO_BYTE(float_value, index) \
(( \
(union { float f; uint8_t u8[sizeof (float)]; }) {(float_value)} \
).u8[(index)])
// size sensitive code - assume sizeof (float) == 4
#define FLOAT_TO_BYTES(float_value) \
FLOAT_TO_BYTE((float_value), 0), FLOAT_TO_BYTE((float_value), 1), \
FLOAT_TO_BYTE((float_value), 2), FLOAT_TO_BYTE((float_value), 3)
int main(void) {
const uint8_t byteArray[] = {
42,
FLOAT_TO_BYTE(11.4, 0),
FLOAT_TO_BYTE(11.4, 1),
FLOAT_TO_BYTE(11.4, 2),
FLOAT_TO_BYTE(11.4, 3),
42,
FLOAT_TO_BYTES(11.4)
};
for (unsigned i=0; i<sizeof byteArray; i++) {
printf("%u %u\n", i, 1u*byteArray[i]);
}
}
Output
0 42
1 102
2 102
3 54
4 65
5 42
6 102
7 102
8 54
9 65
I'm a computer science student.
Now, I'm working on a computer architecture project in C, which simulates a processor.
There are many types of instructions such as
31 27 26 22 21 17 16 0
---------------------------------------------------------------
| op | ra | rb | imm17 |
---------------------------------------------------------------
31 27 26 22 21 17 16 7 6 5 4 0
---------------------------------------------------------------
| op | ra | rb | imm10 | m | shamt |
---------------------------------------------------------------
31 27 26 22 21 0
---------------------------------------------------------------
| op | ra | imm22 |
---------------------------------------------------------------
So, I wanted to make a C structure which contains bit-fields corresponding to each elements such as op, ra and so on.
At first, I thought that I could use unions and nested structs.
For example, I wrote code like:
struct instr_t {
union {
uint32_t imm22 : 22;
struct {
union {
uint32_t imm17: 17;
struct {
uint8_t shamt: 5;
uint8_t mode : 2;
uint16_t imm10 : 10;
};
};
uint8_t rb : 5;
};
};
uint8_t ra : 5;
uint8_t op : 5;
}
I expected that the result of sizeof(struct instr_t) would be 4 but the reality was 12.
Maybe the nested structs got some paddings.
So, here is my qeustion:
How can one achieve overlapped C bit-fields?
or
Does anybody can recommend a better way to implement multiple types of instruction in C?
Thank you!
The bit-fields members must be stored in the same storage unit to be layed out contiguously:
struct instr_1_t {
uint32_t imm22 : 17;
uint32_t rb : 5;
uint32_t ra : 5;
uint32_t op : 5;
};
struct instr_2_t {
uint32_t shamt: 5;
uint32_t m: 2;
uint32_t imm10 : 10;
uint32_t rb : 5;
uint32_t ra : 5;
uint32_t op : 5;
};
struct instr_3_t {
uint32_t imm22 : 22;
uint32_t ra : 5;
uint32_t op : 5;
};
union instr_t {
struct {
uint32_t pad : 22;
uint32_t op : 5;
};
instr_1_t instr_1;
instr_2_t instr_2;
instr_3_t instr_3;
};
static_assert(sizeof(instr_t) == sizeof(uint32_t), "sizeof(instr_t) != sizeof(uint32_t)");
void handle_instr(instr_t i) {
switch(i.op) {
//
}
}
Maxim gave the correct answer.
I also suggest looking over this code to understand why sizeof instr_t was giving 12 :)
typedef struct s1{
uint8_t shamt: 5;
uint8_t mode : 2;
uint16_t imm10 : 10;
} s_1;
typedef union u1{
uint32_t imm17: 17;
s_1 member0;
} u_1;
typedef struct s2{
u_1 member1;
uint8_t rb : 5;
} s_2;
typedef union u2{
uint32_t imm22 : 22;
s_2 member3;
} u_2;
typedef struct instr_t {
u_2 member4;
uint8_t ra : 5;
uint8_t op : 5;
} s_instr;
int main(int argc, char* argv[])
{
printf("sizes s_1=%d, u_1=%d, s_2=%d, u_2=%d, s_instr=%d\n", sizeof(s_1), sizeof(u_1), sizeof(s_2), sizeof(u_2), sizeof(s_instr));
printf("uint8_t=%d, uint16_t=%d, uint32_t=%d\n", sizeof(uint8_t), sizeof(uint16_t), sizeof(uint32_t));
printf("Sizeof instr_t is %d\n", sizeof(s_instr));
}
Hope this helps!
Cheers!
Bitfields are not portable. You never know if the same bitfield definition gets you the same results on two different compilers. Bitfields also have let's say interesting semantics in multi-threaded programs.
Go with C++ and write a class with appropriated inlined accessors. I mean you are a computer science student, you know C++, right?
If for some mad reason your superiors demand that the code is written in C, write a struct with one uint32_t member and individual accessor functions using shift and masking operations. Obviously also inlined.
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;