c - 围绕初始化器元素的好方法不是 C 中的常量错误吗?

标签 c avr avr-gcc

使用 avr-gcc 时出现初始化元素不是常量编译错误。有什么好的方法可以完成我在这里尝试做的事情吗?

文件.c

#include "file.h"
#include "../notes/octave_two_notes.h"

//F2 is defined in octave_two_notes.h
//This is the file giving me the compilation error
struct Song_Note F2_500ms = { .note = F2, .duration_ms = 500 };

song_note.h

#include "note.h"

struct Song_Note {
    struct Note note;
    uint16_t duration_ms;
} Song_Note;

octave_two_notes.h

extern struct Note F2;

octave_two_notes.c

#define CALC_CTC_FREQ(clock_freq, prescaler, note_freq_hz) ( (uint32_t) clock_freq / ( (uint16_t) note_freq_hz * (uint16_t) prescaler * 2) - 1)

struct Note F2 = {.freq_hz = 87, .ocr_val = CALC_CTC_FREQ(16000000, 8, 87)};

note.h

#include <stdint.h>

struct Note {
    uint16_t freq_hz;
    uint16_t ocr_val;
} Note;

最佳答案

首先,这些变量都应该声明为const。主要是因为您希望它们位于闪存中,而不是 RAM 中。

遗憾的是,

const 并不能解决主要问题,因为 C 语言甚至不将 const 限定的变量视为常量表达式。在文件范围内声明的变量具有“静态存储持续时间”,因此必须使用常量表达式进行初始化。

C 提供的唯一解决方案是将初始化列表声明为一个不优雅的宏,在这种情况下它必须位于头文件中:

// header file

#define CALC_CTC_FREQ ...

#define F2_INIT                              \
{                                            \
  .freq_hz = 87,                             \
  .ocr_val = CALC_CTC_FREQ(16000000, 8, 87)  \
}

并在 .c 文件中使用该宏:

// c file
const struct Note F2 = F2_INIT;

然后在其他地方的 .c 文件中:

const struct Song_Note F2_500ms = { .note = F2_INIT, .duration_ms = 500 };

请注意,CALC_CTC_FREQ 部分应该没问题,其中的所有内容都是常量表达式,并且在编译时对其求值。

关于c - 围绕初始化器元素的好方法不是 C 中的常量错误吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46882553/

相关文章:

c - 为什么它打印 10 而不是 3?在C郎

c - 我的用于删除C文件中注释的代码版本不起作用

c - C代码获取Lua中加载的变量列表

c - scanf() 将换行符保留在缓冲区中

c - 使用 strcmp 解引用指向不完整类型错误的指针

c - AVR 编程,在 7 段上显示错误值。引领

c++ - ATMega328P 和 ESP8266ex 之间的 I2c 通信只能发送 8 个字节,bug?

c - AVR : Relocation truncated to fit

c - 使用 ATTiny 和 Atmel Studio 处理 32 位数字

c - 在 C 中高效地访问 long 中的各个字节(在 8 位平台上)