__align(4)的问题

本文深入探讨了ARM编译器文档中的对齐概念,解释了__align与__packed关键字的使用场景及其对数据访问性能的影响。通过实例展示了对齐与非对齐访问的区别,并提供了消除非对齐访问带来的问题的方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Q:

__align(4)  这是MDK中的一种语法?作用什么;;__align(4) u8 mem1base[MEM1_MAX_SIZE];这条语句的作用是定义MEM1_MAX_SIZE个u8类型的数组,使用4字节对齐的方式吗?

A:

用align修饰数组后,可以去掉packed关键字了. 

ARM下的对齐处理  
from DUI0067D_ADS1_2_CompLib 

3.13 type  qulifiers 

有部分摘自ARM编译器文档对齐部分 

对齐的使用: 
1.__align(num) 
   这个用于修改最高级别对象的字节边界。在汇编中使用LDRD或者STRD时 
   就要用到此命令__align(8)进行修饰限制。来保证数据对象是相应对齐。 
   这个修饰对象的命令最大是8个字节限制,可以让2字节的对象进行4字节 
   对齐,但是不能让4字节的对象2字节对齐。 
   __align是存储类修改,他只修饰最高级类型对象不能用于结构或者函数对象。 
    
2.__packed  
  __packed是进行一字节对齐 
  1.不能对packed的对象进行对齐 
  2.所有对象的读写访问都进行非对齐访问 
  3.float及包含float的结构联合及未用__packed的对象将不能字节对齐 
  4.__packed对局部整形变量无影响 
  5.强制由unpacked对象向packed对象转化是未定义,整形指针可以合法定 
  义为packed。 
     __packed int* p;  //__packed int 则没有意义 
  6.对齐或非对齐读写访问带来问题 
  __packed struct STRUCT_TEST 

  char a; 
  int b; 
  char c; 
}  ;    //定义如下结构此时b的起始地址一定是不对齐的 
         //在栈中访问b可能有问题,因为栈上数据肯定是对齐访问[from CL] 
//将下面变量定义成全局静态不在栈上  
static char* p; 
static struct STRUCT_TEST a; 
void Main() 

__packed int* q;  //此时定义成__packed来修饰当前q指向为非对齐的数据地址下面的访问则可以 

p = (char*)&a;           
q = (int*)(p+1);       

*q = 0x87654321;  
/*    
得到赋值的汇编指令很清楚 
ldr      r5,0x20001590 ; = #0x12345678 
[0xe1a00005]   mov      r0,r5 
[0xeb0000b0]   bl       __rt_uwrite4  //在此处调用一个写4byte的操作函数  
       
[0xe5c10000]   strb     r0,[r1,#0]   //函数进行4次strb操作然后返回保证了数据正确的访问 
[0xe1a02420]   mov      r2,r0,lsr #8 
[0xe5c12001]   strb     r2,[r1,#1] 
[0xe1a02820]   mov      r2,r0,lsr #16 
[0xe5c12002]   strb     r2,[r1,#2] 
[0xe1a02c20]   mov      r2,r0,lsr #24 
[0xe5c12003]   strb     r2,[r1,#3] 
[0xe1a0f00e]   mov      pc,r14 
*/ 

/* 
如果q没有加__packed修饰则汇编出来指令是这样直接会导致奇地址处访问失败 
[0xe59f2018]   ldr      r2,0x20001594 ; = #0x87654321 
[0xe5812000]   str      r2,[r1,#0] 
*/ 

//这样可以很清楚的看到非对齐访问是如何产生错误的 
//以及如何消除非对齐访问带来问题 
//也可以看到非对齐访问和对齐访问的指令差异导致效率问题 
}

### 关于 `lv_obj_align` 的功能与用法 在 LVGL 图形库中,`lv_obj_align` 是用于调整对象相对于其他对象或父容器位置的一个重要函数。该函数允许开发者精确控制 UI 元素的位置布局,从而实现灵活的界面设计。 以下是关于 `lv_obj_align` 函数的具体说明: #### 参数详解 `lv_obj_align` 的定义如下所示: ```c void lv_obj_align(lv_obj_t * obj, const lv_obj_t * base, lv_align_t align, lv_coord_t x_ofs, lv_coord_t y_ofs); ``` - **obj**: 需要调整的对象指针。 - **base**: 对齐的基础对象指针。如果设置为 `NULL`,则会以屏幕作为基础进行对齐[^1]。 - **align**: 定义如何对齐目标对象。常见的选项包括但不限于以下几种: - `LV_ALIGN_CENTER`: 将对象居中对齐到基础对象。 - `LV_ALIGN_TOP_LEFT`, `LV_ALIGN_TOP_MID`, `LV_ALIGN_TOP_RIGHT`: 分别表示顶部左、中、右对齐。 - `LV_ALIGN_BOTTOM_LEFT`, `LV_ALIGN_BOTTOM_MID`, `LV_ALIGN_BOTTOM_RIGHT`: 表示底部左、中、右对齐。 - 更多枚举值可参考官方文档中的 `lv_align_t` 类型定义[^4]。 - **x_ofs**, **y_ofs**: 偏移量参数,分别指定水平方向和垂直方向上的额外偏移距离(单位为像素)。正值向右/下移动,负值向左/上移动。 #### 使用示例 下面是一个简单的例子来展示如何使用 `lv_obj_align` 调整按钮的位置: ```c // 创建一个基本的屏幕对象 lv_obj_t * screen = lv_scr_act(); // 添加一个标签作为参照物 lv_obj_t * label = lv_label_create(screen, NULL); lv_label_set_text(label, "Reference Label"); // 添加一个按钮并对其定位 lv_obj_t * button = lv_btn_create(screen, NULL); // 设置按钮大小 lv_obj_set_size(button, 80, 30); // 将按钮放置在标签下方中心对齐,并向下偏移20px lv_obj_align(button, label, LV_ALIGN_OUT_BOTTOM_MID, 0, 20); ``` 在这个例子中,创建了一个新的按钮并将它放在名为 `"Reference Label"` 的标签正下方中间位置,同时设置了额外的垂直间距为20像素。 #### 注意事项 当调用此方法时需要注意几点: - 如果希望某个控件始终位于窗口中央,则可以将其第二个参数设为 `NULL` 并采用 `LV_ALIGN_CENTER` 方式[^3]。 - 不同版本间可能存在细微差异,请查阅对应版本头文件确认最新接口签名[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值