【问题标题】:C macro for inlining functions with IAR compiler用于 IAR 编译器内联函数的 C 宏
【发布时间】:2021-03-04 11:20:08
【问题描述】:

使用以前的 gcc 编译器,我们这样做了:

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          DO_PRAGMA(pack(n))

所以实际上意味着 PACK_ON(2) 将扩展为 _Pragma(pack(2)) 然后我们就这样使用它

PACK_ON(2)
typedef struct{
...
};

然而,IAR 编译器想要这样的东西:_Pragma("pack(2)") 因此,我尝试通过以下非编译方式实现 pack 宏:

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          DO_PRAGMA(" ## "pack(#n)"" ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## pack(#n) ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## #pack(n) ## ")
#define PACK_ON(n)          DO_PRAGMA(" ## #pack(n) ## ")
#define PACK_ON(n)          DO_PRAGMA("pack(n)")
#define PACK_ON(n)          DO_PRAGMA("pack(#n)")
#define PACK_ON(n)          DO_PRAGMA(pack(#n))
#define PACK_ON(n)          DO_PRAGMA(pack(n))
#define PACK_ON(n)          DO_PRAGMA(#pack(#n))
#define PACK_ON(n)              \#if (n == 1)\ _Pragma("pack(1)")
#define PACK_ON(n)          _Pragma("pack( ## #n ## )")
#define PACK_ON(n)          _Pragma("pack( ## n ## )")
#define PACK_ON(n)          _Pragma("pack(n)")
#define PACK_ON(n)          _Pragma("pack(#n)")

有没有人有一个宏可以与 IAR 编译器一起使用来打包各种大小的 n ? 如果不是,我将强制所有内容打包大小 1 并手动更改使用 2 和 4 的结构。

临时解决方案: 我已经设法通过这样做来解决这个问题:

#define PACK_ON(n)              _Pragma("pack(1)")

并手动更改 PACK_ON(2) 和 PACK_ON(4) 的一小部分

【问题讨论】:

  • 有什么原因你不能直接使用标准 C #pragma,然后是 IAR 想要的任何东西?
  • 我刚刚阅读了一些 ARM 的随机 IAR 手册,它声称支持#pragma pack(n),与 gcc、clang 等一样,事实证明。那你为什么不能用它呢?
  • 您原来的 gcc 宏扩展为 _Pragma("pack(2)"),这正是 gcc 想要的。由于 IAR 应该支持 C99,因此格式相同。我发布了一个答案,请检查它是否也适用于 IAR。
  • "实际上意味着 PACK_ON(2) 将扩展为 _Pragma(pack(2))" 不,它将扩展为 _Pragma("pack(2)"),因为 #x .我在 EWARM 8.50.4 上进行了测试,它工作正常:PACK_ON(2) struct A { char a; int b; } 的大小为 6 个字节。
  • @Lundin 它有效,我在 GCC 上得到的结果与你相同:34

标签: c macros pragma iar pragma-pack


【解决方案1】:

鉴于编译器支持pack(1)pushpop pragma,那么这个标准的 C 解决方案可以工作:

#include <stdio.h>

#define DO_PRAGMA(x)        _Pragma(#x)
#define PACK_ON(n)          _Pragma("pack(push)") DO_PRAGMA(pack(n))
#define PACK_OFF            _Pragma("pack(pop)")

PACK_ON(1)
typedef struct 
{
  char c;
  short s;
} foo;
PACK_OFF

typedef struct 
{
  char c;
  short s;
} bar;


int main()
{ 
  printf("%zu\n", sizeof(foo));
  printf("%zu\n", sizeof(bar));
}

输出

3
4

在 gcc、clang 和 icc 上使用严格的标准设置进行测试 (-std=c11 -pedantic-errors)。

【讨论】:

  • 使用上述 PACK_ON 我得到错误标识符“pack”未定义。我已经设法通过这样做来解决这个问题:#define PACK_ON(n) _Pragma("pack(1)") 并手动更改少数 PACK_ON(2) 和 PACK_ON(4)
  • @Adeishere 这听起来不合规。 pack 不是标识符,它是预处理器令牌。编译器应该在“翻译阶段 4”中扩展宏并执行 _Pragma,并且在“翻译阶段 8”之前不要担心标识符。你确定你在 C99 模式下运行它吗?其他人声称已在 IAR 上成功测试了代码。
  • @Adeishere,听起来您的编译器没有正确实现预处理器字符串化运算符 (#)。这将构成编译器错误。
  • ^ 或者那个,我想。虽然# 是比_Pragma 更早的功能。
  • 确实,@Lundin,字符串化已经出现在 ISO C 的每个版本中。但是未能正确处理此运算符与 OP 的每一项声明都是一致的,尤其是他们关于(不正确的)扩展的声明PACK_ON(2) 的初始宏定义以及他们声称 _Pragma("pack(1)") 具有预期效果的声明。
【解决方案2】:

使用上述 PACK_ON 我得到错误标识符“pack”未定义。我已经设法通过这样做来解决这个问题:#define PACK_ON(n) _Pragma("pack(1)") 并手动更改少数 PACK_ON(2) 和 PACK_ON(4)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-02-20
    • 2015-01-10
    • 2018-05-12
    • 2012-10-20
    • 2011-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多