441
社区成员




在看官方文档的时候,发现出现大量如下代码,特别是这一句:
ALIGN(RT_ALIGN_SIZE)
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static struct rt_thread thread1;
这个应该是他的定义 部分,但是还是不懂。
#define ALIGN(n) __attribute__((aligned(n))
在网上找了一下,好像是对齐用的,但是不是特别理解什么意思,而且还有,就是定义之后全局都可以对齐还是只能后一个数据对齐。
RT-Thread-ALIGN(RT_ALIGN_SIZE)问题RT-Thread问答社区 - RT-Thread
在这段代码中就出现了两次 ,而且为什么不要分号啊啊啊啊啊啊!
简单复刻了一段代码
#include <stdio.h>
#define RT_ALIGN_SIZE 4
#define ALIGN(n) __attribute__((aligned(n)))
typedef struct rt_thread {
int test;
} rt_thread_t;
ALIGN(RT_ALIGN_SIZE)
static char thread1_stack[1024];
static char test1[2];
static char thread2_stack[1024];
static char test2[3];
static char thread3_stack[1024];
static struct rt_thread thread1;
int main(void)
{
printf("thread1_stack: %p\n", thread1_stack);
printf("thread2_stack: %p\n", thread2_stack);
printf("thread3_stack: %p\n", thread3_stack);
return 0;
}
直接gcc编译,把预编译后的文件同步输出,看下宏定义展开后的代码长啥样:
# 9 "xxx.c"
typedef struct rt_thread {
int test;
} rt_thread_t;
__attribute__((aligned(4)))
static char thread1_stack[1024];
static char test1[2];
static char thread2_stack[1024];
static char test2[3];
static char thread3_stack[1024];
static struct rt_thread thread1;
int main(void)
{
printf("thread1_stack: %p\n", thread1_stack);
printf("thread2_stack: %p\n", thread2_stack);
printf("thread3_stack: %p\n", thread3_stack);
return 0;
}
很明显在无语法错误的前提下,attribute((aligned(4))) 只能与最近的一行拼在一起;
即应该是 attribute((aligned(4))) static char thread1_stack[1024];
而帖子中提及,ALIGN(RT_ALIGN_SIZE) 后为何不加分号啊???
从这里就可以知道,加了分号是有语法问题的。比如gcc下报警告就是这样:
> gcc -o test xxx.c -save-temps=obj
xxx.c:13:1: warning: empty declaration
13 | ALIGN(RT_ALIGN_SIZE);
| ^~~~~~~~~~~~~
再来说说,这个 attribute((aligned(4))) 究竟干啥用的!
就像它的名字的含义一样,就是告诉编译器,我这个定义是要按4字节对齐的。
比如帖子中的1024字节的thread1_stack数组;在极度紧凑的时候,编译器是完全可以给你分配一个非对齐的地址的,比如0x1234587作为该数组的起始地址。
那么地址对齐与不对齐,对我们的代码究竟影响怎么样呢?
自然是有影响的,一般32位平台的处理器对4字节对齐是友好的,有些处理场景不对齐还会报 UNALIGNED的硬件异常。
曾经,我遇到一个问题就是由这个引发的。
很简单,我定义了一个128字节的字节数组,然后强制转换为一个结构体指针,通过结构体指针去访问,这种处理方式在处理通讯协议的时候很常见,
当时我的结构体定义大概是这样的:
typedef struct _test_t {
uint8_t u8index;
uint16_t u16_index;
uint32_t u32_index;
} test_t;
强转之后,通过指针访问u16_index就出现异常了,原理就是此时u16_index的地址可能不是一个对齐的地址,触发了硬件异常。
后面通过修饰128字节的字节数组,强制让它N字节对齐,这个问题得到解决。
已投五星(可查记录),欢迎给五星、诚信互访:https://bbs.csdn.net/topics/611389800
希望各位大佬能回答一下