为什么我们需要在C++中#pragma pack使用typedef结构?特别是当您在网络通信中使用这些结构时.
我总是假设,正如他们在这里所说的http://en.wikipedia.org/wiki/Data_structure_alignment,“重要的是要注意最后一个成员填充了所需的字节数,以便结构的总大小应该是任何结构成员的最大对齐的倍数"
所以对于像这样的结构,它的大小在 32 处理器时应该是 16
typedef struct
{
double s; /* 8 bytes */
char c; /* 7 bytes padding at the end of make the total size 8*2 */
} structa_t;
Run Code Online (Sandbox Code Playgroud)
所以我对尺寸是 12 而不是 16 感到非常惊讶!!这是为什么 ?有人可以对它有所了解吗?
sizeof(double) = 8
sizeof(structa_t) = 12
Run Code Online (Sandbox Code Playgroud)
顺便说一句,所以系统信息
$ uname -a
Linux 2.6.18-8.el5xen #1 SMP Thu Mar 15 21:02:53 EDT 2007 i686 i686 i386 GNU/Linux
$ gcc --version
gcc (GCC) 4.1.1 20070105 (Red Hat 4.1.1-52)
Run Code Online (Sandbox Code Playgroud) 如果有的话,使用Visual Studio或gcc
#pragma pack(push, 16)
typedef std::map<uint32_t, uint32_t> MyIntMap;
#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)
然后再:
#pragma pack(push, 8)
MyIntMap thisInstance;
#pragma pack(pop)
Run Code Online (Sandbox Code Playgroud)
thisInstance的结构对齐方式是什么?也就是说,对于typedef的模板类,pragma pack是在typedef的位置还是在变量定义的位置生效?如果是后者,那么获得在文件之间具有一致对齐的类型的一个好的解决方法是什么?
我正在研究 ARM 指令体系结构,并且我读到指令是按字对齐存储的,因此指令地址的最低有效两位在 ARM 状态下始终为零。
Thumb 和 Thumb-2 指令的长度为 16 位或 32 位。指令以半字对齐方式存储,因此指令地址的最低有效位在 Thumb 状态下始终为零。
在我对 AVR 等不同微控制器的一些研究中,在访问程序存储器时,我使用最低有效位来区分要访问的高字节或低字节。但那是关于数据内存访问。
在 ARM 中,指令无论如何都是 32 位的,因此应该一次获取所有字节。
为什么那么,最后两位来获取指令的特定字节(在 Thumb 模式下为 1 位)并使用库。
PS:如果我要获取 4 字节长指令的单个字节,则需要 4 个周期,这是非常低效的,那么具有字节寻址能力的目的是什么,是因为新的 THUMB 类型指令是 16 位宽但仍占用 32 位空间?
我正在尝试计算这个结构的字节大小,并有几个问题
struct stc {
int a;
int b;
char c;
union stc2 {
long a0;
int a1;
int a2;
};
char arr[10];
int z:2;
};
Run Code Online (Sandbox Code Playgroud)
我正在用这种方式检查大小:
int main(void) {
printf("%zu\n", sizeof(struct stc));
}
Run Code Online (Sandbox Code Playgroud)
并编译:
gcc -std=c99 -m32 -Wall -Wextra test.c
这是gcc 4.9,我在64位计算机上,但首先要尝试32位值,所以-m32.现在,结果是20,但我不知道为什么会这样.这就是我的计算方式.
struct stc {
int a; // +4 = 4
int b; // +4 = 8
char c; // +1 but next is long, so +4 (alignment) = 12
union stc2 {
long a0; // +4 = …Run Code Online (Sandbox Code Playgroud) 我使用的是Haswell Core i7-4790K.
当我编译以下玩具示例时icc -O3 -std=c99 -march=core-avx2 -g:
#include <stdio.h>
#include <stdint.h>
#include <immintrin.h>
typedef struct {
__m256i a;
__m256i b;
__m256i c;
} mystruct_t;
#define SIZE 1000
#define TEST_VAL 42
int _do(mystruct_t* array) {
int value = 0;
for (size_t i = 0; i < SIZE; ++i) {
array[i].a = _mm256_set1_epi8(TEST_VAL + i*3 );
array[i].b = _mm256_set1_epi8(TEST_VAL + i*3 + 1);
array[i].c = _mm256_set1_epi8(TEST_VAL + i*3 + 2);
value += _mm_popcnt_u32(_mm256_movemask_epi8(array[i].a)) +
_mm_popcnt_u32(_mm256_movemask_epi8(array[i].b)) +
_mm_popcnt_u32(_mm256_movemask_epi8(array[i].c));
}
return …Run Code Online (Sandbox Code Playgroud) 我对提供的答案有疑问
@ dan04.什么是对齐的内存分配?
特别是,如果我有这样的事情:
int main(){
int num; // 4byte
char s; // 1byte
int *ptr;
}
Run Code Online (Sandbox Code Playgroud)
如果我有一台32位机器,你认为默认情况下它仍会填充数据吗?
在上一个问题中,它被问及struct,我在询问有关变量main.
更新:
a = 2 bytes
b = 4 bytes
c = 1 byte
d = 1 byte
0 1 2 3 4 5 6 7
|a|a|b|b|b|b|c|d| bytes
| | | words
Run Code Online (Sandbox Code Playgroud) 我试图测量结构及其字段(Playground)的大小:
use std::mem;
struct MyStruct {
foo: u8,
bar: char,
}
println!("MyStruct: {}", mem::size_of::<MyStruct>());
let obj = MyStruct { foo: 0, bar: '0' };
println!("obj: {}", mem::size_of_val(&obj));
println!("obj.foo: {}", mem::size_of_val(&obj.foo));
println!("obj.bar: {}", mem::size_of_val(&obj.bar));
Run Code Online (Sandbox Code Playgroud)
该程序打印:
MyStruct: 8
obj: 8
obj.foo: 1
obj.bar: 4
Run Code Online (Sandbox Code Playgroud)
因此结构的大小大于其字段大小的总和(这将是5).这是为什么?
RFC 1358提出了一个对齐属性#[repr(align="N")],它被接受了.Rust问题33626将该功能纳入夜间版本.
我无法使用此功能rustc 1.19.0-nightly (777ee2079 2017-05-01).如果我在没有 feature gate(#![feature(repr_align)])的情况下编译:
#[repr(align="16")]
struct Foo {
bar: u32,
}
Run Code Online (Sandbox Code Playgroud)
我收到以下错误声明:
error: the struct `#[repr(align(u16))]` attribute is experimental (see issue #33626)
--> foo.rs:3:1
|
3 | / struct Foo {
4 | | bar: u32,
5 | | }
| |_^
|
= help: add #![feature(repr_align)] to the crate attributes to enable
Run Code Online (Sandbox Code Playgroud)
当我使用功能门编译时,错误消息显示:
error[E0552]: unrecognized representation hint
--> foo.rs:3:8 …Run Code Online (Sandbox Code Playgroud) 我正在开发STM32F7。当我free()在以下(简化)代码中点击时,会触发一次Hardfault :
typedef struct
{
uint8_t size;
uint8_t* data;
}my_struct;
void foo()
{
my_struct msg;
msg.size = 5;
msg.data = malloc(msg.size);
if(msg.data != NULL)
{
free(msg.data); // Hardfault
}
}
Run Code Online (Sandbox Code Playgroud)
我在GDB中一步一步地free()找到了引起Hardfault的汇编指令:
ldrd r1, r3, [r5, #8]
Run Code Online (Sandbox Code Playgroud)
的值r5就是0x5F0FE9D0
CFSR是,0x8200并且MMFAR和BFAR寄存器都包含0x5F0FE9D8,
看着LDRDR在网络上的问题,我试图添加__attribute__((__packed__))到my_struct定义。当通过指针/结构使用未对齐的内存访问时,应该强制编译器生成2x LDR。
这样,我在运行时不再需要Hardfault。好...
出于好奇,我想在此修改后通过GDB检查地址,并且感到惊讶!没有任何变化(我的意思是关于地址),尽管有了并生成了我的Hardfault(但仅在GDB调试执行中),我最终还是再次命中了LDRD指令packed。
在删除属性并比较MMFAR和BFAR寄存器的值后,我启动了新的运行,当我不在GDB中时,我得到了0x41AFFE60
memory-alignment ×10
c ×4
c++ ×3
struct ×3
arm ×2
rust ×2
avx ×1
bit-fields ×1
embedded ×1
gcc ×1
gdb ×1
instructions ×1
intel ×1
intrinsics ×1
padding ×1
sizeof ×1
sse ×1
stm32 ×1
templates ×1
visual-c++ ×1