c - 静态结构初始化

标签 c struct static header initialization

我在初始化某些在库 header 中声明为静态的结构时遇到问题

头文件:

struct game_setting
{
    uint8_t parameter;
    uint8_t alternatives[6];
    uint8_t alternatives_number;
};


static game_setting game_status;

.c 文件中的初始化函数:

void menu_init()
{
    static uint8_t game_parameters_array[6];
    static game_setting game_status = {&game_parameters_array[RUN_STATUS],{OFF,ON},2}

返回“初始化元素在加载时不可计算”

我正在寻找一种为静态结构赋值的有效方法,有什么问题吗?

主要脚本

#define F_CPU 4915200UL
#define OFFSET 0x2000
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <stdio.h>
#include <stdlib.h>
#include "SPI.h"
#include "MCP2515.h"
#include "MCP2515_Commands.h"

#include "adc.h"
#include "multiboard.h"
#include "OLED.h"
#include "OLED_menu.h"
#include "CAN.h"
#include "USART.h"
#define SPI_DEBUG
#define CAN_MESSAGE_DEBUG
#define UPDATEMESSAGES 255

// Define baud rate
#define USART_BAUDRATE 9600   
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)


int main(void){
    FILE fileHandle = USART_Init();
    init_xMem();
    stdout = &fileHandle;
    stdin = &fileHandle;
    printf("start of init\n\r");
    menu_init();

    printf("menu_init completed\n");
    OLED_init();
    CAN_init();
    ADCInit();
    initController();
    can_message msg;
    msg.id = 1;
    controller C;
    int i = 1;
    while (1) {
            menu_page_print_data();
            _delay_ms(1000);
    }
}

完整的 OLED_menu .c 文件(相关函数无需 OLED.h 定义即可工作):

#include "OLED.h"
#include "OLED_menu.h"

void menu_init()
{


    menu_page_address_offset = 0x1C01;
    game_setting_address_offset = 0x1F01;

    game_status = game_setting_address_offset;
    game_setting_address_offset += 1;

    uint8_t alternatives[6];

    game_status->parameter =  &game_parameters_array[RUN_STATUS];
    game_status->alternatives[0] = OFF;
    game_status->alternatives[1] = ON;
    game_status->alternatives_number = 2;

    start_game = menu_page_address_offset;

    menu_page_address_offset += 1;

    strcpy(&start_game->title, "Start game");
    start_game->submenu_pages[0] =  NULL; 
    start_game->parent_menu_page = main_menu; 
    start_game->submenu_pages_number = 0; 
    start_game->setting = &game_status;

    solenoid_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    solenoid_param->parameter = &game_parameters_array[SOLENOID];
    solenoid_param->alternatives[0] = X_POSITION;
    solenoid_param->alternatives[1] = Y_POSITION;
    solenoid_param->alternatives[2] = LEFT_SLIDER;
    solenoid_param->alternatives[3] = RIGHT_SLIDER;
    solenoid_param->alternatives_number = 4;

    solenoid_control = menu_page_address_offset;
    menu_page_address_offset += 1;



    strcpy(&solenoid_control->title,"Solenoid");
    solenoid_control->submenu_pages[0] =  NULL;
    solenoid_control->parent_menu_page =  NULL;
    solenoid_control->submenu_pages_number =  0;
    solenoid_control->setting =  &solenoid_param;

    servo_param = game_setting_address_offset;
    game_setting_address_offset += 1;

    servo_param->parameter = &game_parameters_array[SERVO];
    servo_param->alternatives[0] = X_POSITION;
    servo_param->alternatives[1] = Y_POSITION;
    servo_param->alternatives[2] = LEFT_SLIDER;
    servo_param->alternatives[3] = RIGHT_SLIDER;
    servo_param->alternatives_number = 4;

    servo_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&servo_control->title, "Servo");
    servo_control->submenu_pages[0] = NULL;
    servo_control->parent_menu_page = NULL;
    servo_control->submenu_pages_number =  0;
    servo_control->setting =  &servo_param;

    motor_param = game_setting_address_offset;
    game_setting_address_offset += 1;


    motor_param->parameter = &game_parameters_array[MOTOR]; 
    motor_param->alternatives[0] = X_POSITION;
    motor_param->alternatives[1] = Y_POSITION;
    motor_param->alternatives[2] = LEFT_SLIDER;
    motor_param->alternatives[3] = RIGHT_SLIDER;

    motor_control = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(&motor_control->title, "Motor");
    motor_control->submenu_pages[0] = NULL; 
    motor_control->parent_menu_page = NULL;
    motor_control->submenu_pages_number =  0; 
    motor_control->setting = &motor_param;

    controller_layout = menu_page_address_offset;
    //printf("Controller_layout addr: , %d\n", (int)menu_page_address_offset);
    menu_page_address_offset += 1;

    /*
    strcpy(controller_layout->title, "Controller Layout");
    controller_layout->submenu_pages[0] = motor_control;
    printf("motor_control : %X\n", motor_control);
    controller_layout->submenu_pages[1] = servo_control;
    controller_layout->submenu_pages[2] = solenoid_control;
    controller_layout->parent_menu_page = NULL;
    controller_layout->submenu_pages_number = 3;
    controller_layout->setting =  NULL;

    settings_advanced = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_advanced->title, "Advanced Settings");
    settings_advanced->submenu_pages[0] = NULL;
    settings_advanced->parent_menu_page =  NULL;
    settings_advanced->submenu_pages_number =  0; 
    settings_advanced->setting = NULL;

    difficulty_param->parameter = &game_parameters_array[DIFFICULTY];
    difficulty_param->alternatives[0]  = DIFFICULTY_EASY;
    difficulty_param->alternatives[1]  = DIFFICULTY_NORMAL;
    difficulty_param->alternatives[2]  = DIFFICULTY_HARD;
    difficulty_param->alternatives_number = 3;

    settings_difficulty = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(settings_difficulty->title, "Difficulty");
    settings_difficulty->submenu_pages[0] =  NULL;
    settings_difficulty->parent_menu_page =  NULL;
    settings_difficulty->submenu_pages_number =  0;
    settings_difficulty->setting =  &difficulty_param;

    menu_setting = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(menu_setting->title, "Settings");
    menu_setting->submenu_pages[0] = controller_layout;
    menu_setting->submenu_pages[1] = settings_difficulty;
    menu_setting->submenu_pages[2] = settings_advanced;
    //printf("Child 1 before: %d, %d",menu_setting->submenu_pages[0], controller_layout);
    menu_setting->parent_menu_page = NULL;
    menu_setting->submenu_pages_number = 3;
    menu_setting->setting = NULL;

    */
        menu_setting = menu_page_address_offset;
        menu_page_address_offset += 1;
    main_menu = menu_page_address_offset;
    menu_page_address_offset += 1;

    strcpy(main_menu->title, "Main Menu");
    main_menu->submenu_pages[0] = start_game;
    main_menu->submenu_pages[1] = menu_setting;
    main_menu->parent_menu_page  = NULL;
    main_menu->submenu_pages_number =  2;
    main_menu->setting = NULL;
    menu_assign_parents(&main_menu);
}

void game_setting_init(game_setting* setting, uint8_t* parameter, uint8_t* alternatives, uint8_t elements)
{
    setting->parameter = parameter;
    for (int i; i < elements; i++)
    {
        setting->alternatives[i] = alternatives[i];
    }
}

int menu_assign_parents(menu_page* parent)
{
    if(parent->submenu_pages_number > 6)
    {
        return -1;
    }
    for (int i; i < parent->submenu_pages_number; i++)
    {
        parent->submenu_pages[i]->parent_menu_page = parent;

        if(menu_assign_parents(parent->submenu_pages[i]) == -1)
        {
            return -1;
        }
    }
    return 0;

}

int menu_page_print(menu_page* page)
{
    OLED_SRAM_Position_reset();
    OLED_TextBox_clear((boundary) {0,127,0,7});
    OLED_Goto_position(0,40);
    //printf("%d parent, ", page->submenu_pages_number);
    OLED_String_print(page->title, FONT_LARGE);


    for (int i = 0; i < page->submenu_pages_number; i++)
    {
        OLED_Goto_position(i+1,5);
        OLED_String_print(page->submenu_pages[i]->title, FONT_NORMAL);
        //printf("%s\n", page->submenu_pages[i].title);
    }
    return 0;
}


menu_page* menu_page_select(menu_page* page,controller* C)
{
    menu_page_print(page);
    if(page->submenu_pages_number  <= 0)
    {
        return (menu_page*)-1;
    }
    int submenu_number = -1;
    int submenu_result = -1;
    controller_direction generalDirection_prev;
    while(!C->rightButton)
    {
        updateController(C);
        if(generalDirection_prev != C->J.generalDirection)
        {
            switch(C->J.generalDirection)
            {
                case (DOWN):
                submenu_number = (submenu_number + 1)%page->submenu_pages_number;
                break;
                case (UP):
                submenu_number--;
                if(submenu_number < 0)
                {
                    submenu_number = page->submenu_pages_number-1;
                }
                break;
            }
            menu_page_selection_mark(submenu_number+1, page);
            generalDirection_prev = C->J.generalDirection;
        }
    }
    return &(page->submenu_pages[submenu_number]);
}

int TextBox_init(OLED_TextBox** box, char* str, TextBox_pos position, uint8_t line)
{
    uint8_t StringLength = strlen(str);
    printf("%d\n\r", StringLength);
    if (118 / StringLength >= FONT_LARGE)
    {
        (*box)->FontSize = FONT_LARGE;
    }
    else if (118 / StringLength >= FONT_NORMAL)
    {
        (*box)->FontSize = FONT_NORMAL;
    }
    else if (118 / StringLength >= FONT_SMALL)
    {
        (*box)->FontSize = FONT_SMALL;
    }
    printf("%d\n\r", (*box)->FontSize);
    switch (position)
    {
        case TEXBOX_LEFT:

        (*box)->Boundaries = (boundary){5,5+StringLength*(*box)->FontSize,line,line};

        case TEXTBOX_CENTER:
        printf("%d\n\r", (128-(*box)->FontSize*StringLength)/2);
        (*box)->Boundaries = (boundary){(128-(*box)->FontSize*StringLength)/2, (128+StringLength*(*box)->FontSize+1)/2,line,line};
        printf("%d, %d, %d, %d nr1\n\r", (*box)->Boundaries.Left, (*box)->Boundaries.Right, (*box)->Boundaries.Top, (*box)->Boundaries.Bottom);
        //printf("%d\n\r", (*box)->FontSize);
        case TEXTBOX_RIGHT:
        (*box)->Boundaries =(boundary){128-5-StringLength*(*box)->FontSize, 128-5,line,line};

    }
    (*box)->string = str;
    return 0;
}
int menu_page_selection_mark(uint8_t rowIndex, menu_page* menu)
{
    if(rowIndex < 1)
    {
        return -1;
    }
    //printf("Current index: %s\n", menu->submenu_pages[rowIndex].title);
    static int rowIndex_prev = -1;
    if(rowIndex_prev > -1)
    {
            OLED_Clear_line(rowIndex_prev);
            OLED_Goto_position(rowIndex_prev, 5);
            printf("title: %s\n", menu->submenu_pages[rowIndex_prev-1]->title);
            OLED_String_print(menu->submenu_pages[rowIndex_prev-1]->title, FONT_LARGE);
    }
    OLED_Clear_line(rowIndex);
    OLED_Goto_position(rowIndex, 7);
    OLED_String_print(menu->submenu_pages[rowIndex-1]->title, FONT_LARGE);
    OLED_String_print(" <-", FONT_LARGE);
    rowIndex_prev = rowIndex;
    return rowIndex;

}

void menu_page_print_data()
{
    menu_page* page = main_menu;
    printf("Menu page %s:   Children: ", page->title);
    for (int i; i < page->submenu_pages_number; i++)
    {
        printf("%s  ", page->submenu_pages[i]->title);
    }
    printf("Parent: %s", page->parent_menu_page->title);
}
int menu_print_parameters(game_setting* settings, controller* C)
{
    static uint8_t current_position = 1;
    controller_direction generalDirection_prev;

    menu_print_parameter_line(settings, LEFT, current_position);

    while(!C->leftButton)
    {
        if(C->J.generalDirection != generalDirection_prev)
        {
            if (C->J.generalDirection == LEFT)
            {
                current_position = menu_print_parameter_line(settings, LEFT, current_position);
            }
            else if(C->J.generalDirection == RIGHT)
            {
                current_position = menu_print_parameter_line(settings, RIGHT, current_position);
            }
        }
    }
}
int menu_print_parameter_line(game_setting* setting, controller_direction direction, uint8_t position)
{
    char* string;
    uint8_t next_position;
    if(setting->alternatives_number == 0)
    {
        return -1;
    }
    if(direction == LEFT)
    {
        next_position = position -1;
    }
    else if(direction == RIGHT)
    {
        next_position = position +1;
    }
    OLED_Clear_line(6);
    OLED_Goto_position(6,127);

    OLED_String_print("<-", FONT_LARGE);
    sprintf(&string, setting->alternatives[next_position]);

    OLED_String_print(string, FONT_LARGE);
    OLED_String_print("->", FONT_LARGE);

    return next_position;
}
int menu_assign_parameters(menu_page* page, controller* C)
{

}
int menu_run(menu_page* page, controller* C)
{
    menu_page* next_submenu_page;
    menu_page* current_page = page;
    while(next_submenu_page != -1)
    {
        current_page = next_submenu_page;
        next_submenu_page = menu_page_select(current_page, C);
    }   
}

OLED_menu.h 文件:

#ifndef OLED_MENU_H
#define OLED_MENU_H
#include "symbols_enums.h"
#include "OLED.h"
#include "multiboard.h"
#include "CAN_message_IDs.h"
#include <assert.h>
#include <string.h>
#include <avr/delay.h>
typedef struct menu_page menu_page;

typedef struct game_setting game_setting;
struct game_setting
{
    uint8_t* parameter;
    uint8_t alternatives[6];
    uint8_t alternatives_number;
};
struct menu_page
{
    char title[12];
    menu_page* submenu_pages[4];
    menu_page* parent_menu_page;
    uint8_t submenu_pages_number;
    //Used to set values for settings:
    game_setting* setting;
};
typedef enum {TEXBOX_LEFT, TEXTBOX_CENTER, TEXTBOX_RIGHT}TextBox_pos;

static volatile menu_page* menu_page_address_offset;
static volatile game_setting* game_setting_address_offset;
static uint8_t game_parameters_array[5];

//Indicates if the game should start/stop:
static volatile game_setting* game_status;
static volatile menu_page* start_game;

//***********************************
static volatile game_setting* solenoid_param;
static volatile menu_page* solenoid_control;

static volatile game_setting* servo_param;
static volatile menu_page* servo_control;   

static volatile game_setting* motor_param;      
static volatile menu_page* motor_control;                       //Controller layout
//***********************************
static volatile menu_page* controller_layout;

static volatile menu_page* settings_advanced;

static volatile game_setting* difficulty_param;
static volatile menu_page* settings_difficulty;

static volatile menu_page* menu_setting;


static volatile menu_page* main_menu;



int menu_page_init(char*, menu_page*, menu_page*);
int menu_page_print(menu_page* page);
menu_page* menu_page_select(menu_page* page,controller* C);
int menu_page_selection_mark(uint8_t, menu_page*);
void menu_page_print_data();
int menu_print_parameter_line(game_setting*, controller_direction , uint8_t);
//int TextBox_init(OLED_TextBox**, char*, TextBox_pos, uint8_t);
#endif // OLED_MENU_H

我将其更改为一次手动初始化一个结构成员,这似乎有效。但是,当在 menu_init() 完成之前执行程序时,由于这些初始化而崩溃:

    menu_setting->submenu_pages[0] = controller_layout;
    menu_setting->submenu_pages[1] = settings_difficulty;
    menu_setting->submenu_pages[2] = settings_advanced;



    main_menu->submenu_pages[0] = start_game;
    main_menu->submenu_pages[1] = menu_setting;

    controller_layout->submenu_pages[1] = servo_control;
    controller_layout->submenu_pages[2] = solenoid_control

最佳答案

初始化是提供事物的地址,而不是事物本身。

struct game_setting {
  uint8_t parameter;  // this is a byte
  ...
};

然后在main()

{
  static uint8_t game_parameters_array[6];

  static struct game_setting game_status = {
    &game_parameters_array[RUN_STATUS],  // this is an address, not a byte
    ...
  }

另外,我没有看到 RUN_STATUS 的定义 - 它有可能不是一个常量值吗?如果它是一个可以更改的宏(例如状态标志),那么它不适合在加载时建立索引来初始化它。

关于c - 静态结构初始化,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58660698/

相关文章:

c++ - 复杂类型数组的静态初始化

c++ - 将 lambda 放在静态初始化列表中并通过引用捕获是否安全?

c中将一个文件复制到另一个错误

c - 为什么这个 printf 在 C 中打印出错误的数字表示?

c# - 具有对 C# 的整数引用的编码结构

c++ - 低于结构的运算符

c - 在给定特定字节格式的情况下,如何通过 fread 读取结构?

C#:如何在 form.cs 中引用 Program.cs 中的内容?

c - 从文本文件中读取指令

c - 我无法将元素添加到 C 中链接列表的末尾