我定義了一個結構體,用于跨兩個不同介面發送的訊息。其中之一需要 32 位對齊,但我需要盡量減少它們占用的空間。本質上,我試圖對結構進行位元組打包,即#pragma pack(1)但要確保生成的結構是 32 位長的倍數。我正在為 32 位 M3 處理器使用 gcc arm 交叉編譯器。我想我想做的是這樣的:
#pragma pack(1)
typedef struct my_type_t
{
uint32_t someVal;
uint8_t anotherVal;
uint8_t reserved[<??>];
}
#pragma pack()
where<??>確保 的大小my_type_t可以被 4 個位元組整除,但沒有硬編碼填充大小。我可以做這樣的事情:
#pragma pack(1)
typedef struct wrapper_t
{
my_type_t m;
uint8_t reserved[sizeof(my_type_t) 4 - (sizeof(my_type_t) % 4)]
}
#pragma pack()
但我想避免這種情況。
最終我需要做的是將其復制到 32 位可尋址的緩沖區中,例如:
static my_type_t t; //If it makes a difference, this will be declared statically in my C source file
...
memcpy(bufferPtr, (uint32_t*)&t, sizeof(t)) //or however I should do this
我查看了__attribute__((align(N)))屬性,它為我提供了結構的 32 位對齊記憶體地址,但它沒有對它進行位元組打包。我對如何(或是否)將其與pack(1).
我的問題是這樣的:
宣告這些結構的正確方法是什么,以便我可以最大限度地減少它們在記憶體中的占用空間,但允許我使用無符號 32 位指標以 4 位元組增量復制/設定它?(有很多這些型別的任意大小和內容)。如果我上面的組合pack和填充方法完全錯誤,我會很樂意采取替代方案。
編輯:
Some constraints: I do not have control over one of the interfaces. It is expecting byte-packed frames. The other side is 32-bit addressable memory mapped registers. I have 64k of memory for the entire executable, and I'm limited on the libraries etc. I can bring in. There is already a great deal of space optimization I've had to do.
The struct in this question was just to explain my question. I have numerous messages of varying content that this applies to.
uj5u.com熱心網友回復:
當您使用 gcc 時,您需要使用其中一個屬性。
示例 演示。
#define PACKED __attribute__((packed))
#define ALIGN(n) __attribute__((aligned(n)))
typedef struct
{
uint8_t anotherVal;
uint32_t someVal;
}PACKED my_type_t;
my_type_t t = {1, 5};
ALIGN(64) my_type_t t1 = {1, 5};
ALIGN(512) my_type_t t2 = {2, 6};
int main()
{
printf("%p, %p, %p", (void *)&t, (void *)&t1, (void *)&t2);
}
結果:
0x404400, 0x404440, 0x404600
https://godbolt.org/z/j9YjqzEYW
uj5u.com熱心網友回復:
我不能代表您正在使用的特定編譯器和架構,但我希望以下內容就足夠了:
typedef struct {
uint32_t someVal;
uint8_t anotherVal;
} my_type_t;
該結構通常與其最大欄位具有相同的對齊方式,其中包括在末尾添加必要的填充。
my_type_t
---------------
| |
--- -----------
| | [padding] |
--- -----------
|<-- 32 bits -->|
演示
這樣做是為了在您擁有一組欄位時正確對齊欄位。
my_type_t my_array[2];
my_array[1].someVal = 123; // Needs to be properly aligned.
這個答案假設您可以控制欄位的順序以獲得最佳空間效率,因為它依賴于編譯器對齊各個欄位。
uj5u.com熱心網友回復:
我建議結合#pragma pack使用alignas:
#include <stdalign.h>
#include <stdint.h>
typedef struct {
#pragma pack(1)
alignas(4) struct { // requires 2 1 2 bytes but is aligned to even 4:s
uint16_t someVal; // 0
uint8_t anotherVal; // 2
uint16_t foo; // 3 (would be 4 without packing)
};
#pragma pack()
} my_type_t;
匿名內部struct使訪問像以前一樣容易:
int main() {
my_type_t y;
y.someVal = 10;
y.anotherVal = 'a';
y.foo = 20;
printf("%zu\n", (char*)&y.someVal - (char*)&y.someVal); // 0
printf("%zu\n", (char*)&y.anotherVal - (char*)&y.someVal); // 2
printf("%zu\n", (char*)&y.foo - (char*)&y.someVal); // 3
my_type_t x[2];
printf("%zu\n", (char*)&x[1] - (char*)&x[0]); // 8 bytes diff
}
uj5u.com熱心網友回復:
你可以使用這個:
typedef struct {
uint8_t x;
uint32_t y;
uint8_t z;
}
__attribute__((packed)) // Remove interfield padding.
__attribute__((aligned(4))) // Set alignment and add tail padding.
my_type_t;
這產生了這個:
my_type_t
--- -----------
| |
--- --- -------
| | [PAD] |
--- --- -------
|<-- 32 bits -->|
該packed屬性可防止在欄位之間添加填充,但將結構對齊到 32 位邊界會強制進行您想要的對齊。這具有添加尾隨填充的副作用,因此您可以安全地擁有這些結構的陣列。
演示
與我的其他答案不同,除了對 GCC 屬性的支持之外,這個答案沒有做出任何假設。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qianduan/359056.html
