user-0 提问: [疑惑]关于memset对结构体清零

回复:
user: user-1
content: 引用 7 楼 andyxu111 的回复:自己解决疑惑了！  1.在不使用microLib库的情况下         在keil的编译环境下，memset是四字节进行清零操作的。汇编代码中关键的一步是：         STM r0!,{r2-r3,r2,lr}  方括号中的四个寄存器的值均为0，如果r0（即代表结构体的初始地址），因为是4字节赋值，如果r0并不是4字节对齐的话，就会直接死机；所以当我们在定义数组的时候，如果指定四字节对齐，就不会死机、  2.在使用microLIb之后       通过查看汇编代码，发现此时对memset的实现是单字节进行的，因此不存在字节对齐问题。故程序能正常运行。  从上面的一点来看，microLib虽然减小了代码大小，但是因为没有字节对齐，一次赋值一个字节肯定比一次赋值四个字节来的慢，这也算是一个   时间（性能）换空间的例子吧赞一个

user: user-2
content: 仅供参考：#include <stdio.h> #define field_offset(s,f) (int)(&(((struct s *)(0))->f)) struct AD  { int a; char b[13]; double c;}; #pragma pack(push) #pragma pack(1) struct A1  { int a; char b[13]; double c;}; #pragma pack(2) struct A2  { int a; char b[13]; double c;}; #pragma pack(4) struct A4  { int a; char b[13]; double c;}; #pragma pack(8) struct A8  { int a; char b[13]; double c;}; #pragma pack(16) struct A16 { int a; char b[13]; double c;}; #pragma pack(pop) int main() {     printf("AD.a %d\n",field_offset(AD,a));     printf("AD.b %d\n",field_offset(AD,b));     printf("AD.c %d\n",field_offset(AD,c));     printf("AD sizeof %d\n", sizeof(AD));     printf("\n");     printf("A1.a %d\n",field_offset(A1,a));     printf("A1.b %d\n",field_offset(A1,b));     printf("A1.c %d\n",field_offset(A1,c));     printf("A1 sizeof %d\n", sizeof(A1));     printf("\n");     printf("A2.a %d\n",field_offset(A2,a));     printf("A2.b %d\n",field_offset(A2,b));     printf("A2.c %d\n",field_offset(A2,c));     printf("A2 sizeof %d\n", sizeof(A2));     printf("\n");     printf("A4.a %d\n",field_offset(A4,a));     printf("A4.b %d\n",field_offset(A4,b));     printf("A4.c %d\n",field_offset(A4,c));     printf("A4 sizeof %d\n", sizeof(A4));     printf("\n");     printf("A8.a %d\n",field_offset(A8,a));     printf("A8.b %d\n",field_offset(A8,b));     printf("A8.c %d\n",field_offset(A8,c));     printf("A8 sizeof %d\n", sizeof(A8));     printf("\n");     printf("A16.a %d\n",field_offset(A16,a));     printf("A16.b %d\n",field_offset(A16,b));     printf("A16.c %d\n",field_offset(A16,c));     printf("A16 sizeof %d\n", sizeof(A16));     printf("\n");     return 0; } //AD.a 0 //AD.b 4 //AD.c 24 //AD sizeof 32 // //A1.a 0 //A1.b 4 //A1.c 17 //A1 sizeof 25 // //A2.a 0 //A2.b 4 //A2.c 18 //A2 sizeof 26 // //A4.a 0 //A4.b 4 //A4.c 20 //A4 sizeof 28 // //A8.a 0 //A8.b 4 //A8.c 24 //A8 sizeof 32 // //A16.a 0 //A16.b 4 //A16.c 24 //A16 sizeof 32 // //

user: user-0
content: 引用 4 楼 DelphiGuy 的回复:但他说的是“偶尔会死机”，并不是数组没有32位对齐就导致死机。所以我觉得这不是memset要求目标地址4字节对齐造成的，应该没有这种限制。而是struct _RIP_MSG这个结构编译器是做了对齐处理的，你把它放在非对齐地址上，生成的代码访问成员可能错位了，这本身也不会造成死机，而是在数据处理部分出现问题。   我程序是运行到 memset这句的时候死机的，而且为了找原因，我就抠出了帖子中的那几句话，并未做其他任何的数据处理。  后来我发现，KEIL下有一个 microLib，勾选了的话，不管对不对齐都可以运行。     因此，我的问题就变成了，死机到底是如何造成的？我在研究下，应该是跟编译器的编译选项有关系，我去研究下microLib

user: user-3
content: 但他说的是“偶尔会死机”，并不是数组没有32位对齐就导致死机。所以我觉得这不是memset要求目标地址4字节对齐造成的，应该没有这种限制。而是struct _RIP_MSG这个结构编译器是做了对齐处理的，你把它放在非对齐地址上，生成的代码访问成员可能错位了，这本身也不会造成死机，而是在数据处理部分出现问题。

user: user-0
content: 自己解决疑惑了！  1.在不使用microLib库的情况下         在keil的编译环境下，memset是四字节进行清零操作的。汇编代码中关键的一步是：         STM r0!,{r2-r3,r2,lr}  方括号中的四个寄存器的值均为0，如果r0（即代表结构体的初始地址），因为是4字节赋值，如果r0并不是4字节对齐的话，就会直接死机；所以当我们在定义数组的时候，如果指定四字节对齐，就不会死机、  2.在使用microLIb之后       通过查看汇编代码，发现此时对memset的实现是单字节进行的，因此不存在字节对齐问题。故程序能正常运行。  从上面的一点来看，microLib虽然减小了代码大小，但是因为没有字节对齐，一次赋值一个字节肯定比一次赋值四个字节来的慢，这也算是一个   时间（性能）换空间的例子吧

user: user-4
content: 印象中VS的memset的实现是不需要4字节对齐的  也可能某些系统上memset使用特殊的实现，要求数据必须对齐。

user: user-1
content: 因为 每种CPU对对齐的处理不同吧  有的能正确处理对其问题，有的不能 有的可以设置对其处理模式  Keil 可 以开发各种CPU的程序， 大体上说，这可能不是开发环境的问题 也不排除Keil 有Bug；对某种CPU处理不完善 不过，个人感觉这是正常情况，不是Bug 但是，鉴于本人对Keil 了解不很深刻，这个结论未必正确 如果是Bug可以告知 Keil的开发者，想必他们会乐意解决这个问题的 。。。。。。。。。 PS： 很多人用的keil 是盗版的，不知道有没有问题 不知道你的 keil 是什么情况

user: user-5
content: 要不要4字节对齐，好像和开发环境，执行环境有关