C语言的定义问题,关于__attribute__的用法,望大家帮忙解答

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言的定义问题,关于__attribute__的用法,望大家帮忙解答相关的知识,希望对你有一定的参考价值。

// ARM CC SFR register definition
SYS_T SYS __attribute__((at(SYS_BASE), zero_init));
CLK_T CLK __attribute__((at(CLK_BASE), zero_init));
SYSINT_T SYSINT __attribute__((at(INT_BASE), zero_init));
GPIO_T GPIOA __attribute__((at(GPIOA_BASE), zero_init));
GPIO_T GPIOB __attribute__((at(GPIOB_BASE), zero_init));
FMC_T FMC __attribute__((at(FMC_BASE), zero_init));
WDT_T WDT __attribute__((at(WDT_BASE), zero_init));
RTC_T RTC __attribute__((at(RTC_BASE), zero_init));
TMR_T TMR0 __attribute__((at(TMR0_BASE), zero_init));
TMR_T TMR1 __attribute__((at(TMR1_BASE), zero_init));
TMRF_T TMRF __attribute__((at(TMRF_BASE), zero_init));
TMR_IR_T TMRIR __attribute__((at(TMR_IR_BASE), zero_init));
TMR_T TMR2 __attribute__((at(TMR2_BASE), zero_init));
SPI_T SPI0 __attribute__((at(SPI0_BASE), zero_init));
SPI_T SPI1 __attribute__((at(SPI1_BASE), zero_init));
PWM_T PWM __attribute__((at(PWM_BASE), zero_init))

SYS_T和CLK_T等带“_T”的是对应的结构体变量名
请问这样定义是什么意思?

便于记忆和阅读程序,GPIO_T是代表io口时钟的结构体,都是结构体,一样的标识,不利于阅读 参考技术A 知道几个 这个CLK是时钟,GPIO是I/O口 SPI总线 你搞这个应该是学过电子,应该知道吧 RTC实时时钟追问

我问的是__attribute__用法是什么样的?

不是那些结构体的用法

GCC `__attribute__ ((pure))` 关于“输入状态”getter 方法的建议 - 正确吗?

【中文标题】GCC `__attribute__ ((pure))` 关于“输入状态”getter 方法的建议 - 正确吗?【英文标题】:GCC `__attribute__ ((pure))` suggestion on "input state" getter method - correct? 【发布时间】:2016-02-01 17:29:10 【问题描述】:

使用 -Wsuggest-attribute=pure 编译会使 GCC 建议可以使用 __attribute__ ((pure)) 标记的潜在函数以进行优化。

这是 GCC 文档中的 definition of pure

许多函数除了返回值之外没有任何影响,它们的返回值仅取决于参数和/或全局变量。这样的函数可以像算术运算符一样进行公共子表达式消除和循环优化。这些函数应该用pure属性声明。

我正在创建一个小型游戏引擎,其中有一个包含 input_state 成员的 input_context 类。 input_context 类通过从操作系统获取全局输入状态在每一帧更新input_state 成员。

它还包含几个“getter”来查询输入状态。

简化示例:

class input_context

private:
    input_state _input_state;

public:
    void update()
    
        os::fill_input_state(_input_state);
    

    auto mouse_x() const noexcept
     
        return _input_state._mouse_x;
    

    auto mouse_y() const noexcept
     
        return _input_state._mouse_y;
    

    auto is_key_down(keycode k) const noexcept
     
        // `_keys` is an array of `bool` values.
        return _input_state._keys[k];
    
;

GCC 告诉我所有这些“getter 方法”,例如 mouse_x()mouse_y()is_key_down(),都是 __attribute__ ((pure)) 的候选对象。

我应该将这些方法标记为pure吗?

我不这么认为,但 GCC 的建议让我对此感到好奇。

我不确定如何解释 GCC 对 pure 的定义 - 它说仅依赖于参数和/或全局变量的函数应该被标记为这样。

在某种程度上,全局操作系统输入状态可以解释为一个全局变量

另一方面,“getter 方法”总是返回不同的值,具体取决于 _input_state 成员变量。

【问题讨论】:

【参考方案1】:

我认为将其标记为纯是可以的。 以简化的形式考虑您的示例,并添加了一些 IO 功能:

#include <stdio.h>
class X 
  int x_=0;
public:
  int x() const noexcept __attribute__ ((pure)) /*__attribute__((noinline))*/;
  void inc() noxcept  x_++; 
;
int X::x() const noexcept  puts("getting x"); return x_;
int main()
  X x;
  printf("%d\n", x.x() + x.x() + x.x());
  x.inc();
  printf("%d\n", x.x() + x.x() + x.x());

让你得到:

getting x
0
getting x
3

而不是

getting x
getting x
getting x
0
getting x
getting x
getting x
3

在优化级别至少 -O1(在更高级别,您可能需要添加 __attribute__((noinline)) 以防止内联)。

只要编译器可以检测到状态发生了变化,如果在两次连续调用这些 getter 之间状态发生变化是可以的。 如果您需要运行non-const 方法来更改状态,那么这不违反纯度。但是,如果状态更改on its own(系统更改它/另一个线程更改它/信号处理程序更改它)以编译器无法知道更改的方式,则pure 属性不再合法。

【讨论】:

【参考方案2】:

我认为您可以将这些方法标记为纯方法,因为它们没有副作用。

根据您引用的文档,纯函数可以依赖于全局变量/外部状态。我想这也与闭包的概念有关。您可以基于外部变量定义函数f(例如使用 Haskell):

x=1
f y = x + y

函数本身仍然没有副作用(尽管在 Haskell 中,您无法更改 x 的值,而您可以在 C/C++ 中的函数/方法之外更改 x)。

pureconst的区别总结在这个问题:__attribute__((const)) vs __attribute__((pure)) in GNU C

引用the answer there:

attribute((const)) 与 attribute((pure)) 相同,但不能访问全局变量。

【讨论】:

以上是关于C语言的定义问题,关于__attribute__的用法,望大家帮忙解答的主要内容,如果未能解决你的问题,请参考以下文章

C语言中的__attribute__宏定义之section属性

C语言错误:error: expected ':', ',', ';', '' or '__attribute__' b

__attribute__ ((__packed__)); 怎么用?

GCC __attribute __((模式(XX))实际上做了什么?

C语言error: expected '=', ',', ';', 'asm' or '__attribute__' b

C/C++系列C语言中__attribute__机制的使用