我正在用C编写一个宏PAGE_ALIGN
,如下所示。
#include <stdio.h>
#define PAGE_ALIGN(x) ((x) & 0xfffff000U)
int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}
现在,我想确保用户向PAGE_ALIGN
传递了正确的类型,我使用_Static_assert()
执行Assert,并且运行良好。
#define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
但是,我的一些代码在函数中没有使用PAGE_ALIGN
,例如,在定义全局变量时:
char a[PAGE_ALIGN(0x12345678U)];
然后我得到编译错误
a.c:3:24: error: braced-group within expression allowed only inside a function
3 | #define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
| ^
a.c:5:8: note: in expansion of macro 'PAGE_ALIGN'
5 | char a[PAGE_ALIGN(0x12345678U)];
| ^~~~~~~~~~
有没有办法定义PAGE_ALIGN
,使宏在函数之外工作?
完整a.c
:
#include <stdio.h>
#define PAGE_ALIGN(x) (({_Static_assert(sizeof(x) == 4); x;}) & 0xfffff000U)
char a[PAGE_ALIGN(0x12345678U)];
int main() {
printf("0x%08x\n", PAGE_ALIGN(0x12345678U));
}
**更新:**这是提出此问题的动机。
我在写一个操作系统,处理物理地址和虚拟地址,分别是32位和64位,虚拟地址在32位是32位,在64位是64位,所以虚拟地址用unsigned long
,物理地址都是64位,所以用unsigned long long
,我在写一个头文件来区分这些不同的类型
例如,页面大小宏为:
#define VA_PAGE_SIZE_4K 0x1000UL // VA for virtual address
#define PA_PAGE_SIZE_4K 0x1000ULL // PA for physical address
然后定义用于对齐的宏:
#define VA_PAGE_ALIGN_UP_4K(x) (((x) + VA_PAGE_SIZE_4K - 1) & ~(VA_PAGE_SIZE_4K - 1))
#define PA_PAGE_ALIGN_UP_4K(x) (((x) + PA_PAGE_SIZE_4K - 1) & ~(PA_PAGE_SIZE_4K - 1))
请想象一下还有其他宏,比如VA_PAGE_ALIGN_UP_2M
、VA_PAGE_ALIGN_UP_1G
...
我的操作系统有一个固定的物理地址大小(比如4 GiB),我需要一个身份Map页表。所以我可以使用对齐宏来计算我需要支持多少页表条目。当然,由于多级分页,还有页目录等。
// maximum physical memory, 4G
#define MAX_PHYS_MEM 0x100000000ULL
// number of page table entries
#define PAGE_TABLE_NELEMS (PA_PAGE_ALIGN_UP_4K(MAX_PHYS_MEM) / PA_PAGE_SIZE_4K)
// Define page table (global variable)
unsigned long page_table[PAGE_TABLE_NELEMS];
// number of page directory entries
#define PAGE_DIRECTORY_NELEMS (PA_PAGE_ALIGN_UP_2M(MAX_PHYS_MEM) / PA_PAGE_SIZE_2M)
// Define page directory (global variable)
unsigned long page_directory[PAGE_DIRECTORY_NELEMS];
// ...
但是,在其他代码中,我想确保PA_PAGE_ALIGN_UP_4K
和VA_PAGE_ALIGN_UP_4K
没有混合使用。也就是说,PA_PAGE_ALIGN_UP_4K
只在unsigned long long
上使用,VA_PAGE_ALIGN_UP_4K
只在unsigned long
上使用。所以我想在这些宏中添加一个静态Assert。但是添加一个静态Assert会在上面的page_table
和page_directory
中导致编译错误。
1条答案
按热度按时间pb3skfrl1#
@Tavian巴恩斯的评论解决了我的问题,我更新的程序看起来像: