Массив частично пуст

Я написал сценарий запуска и liker для своего приложения C ++, работающего на STM32F407VG.

Проблема у меня есть массив структуры, где поле структуры str всегда равен нулю, несмотря на инициализацию. Другое поле в структуре правильно инициализировано. Я не могу понять, что я делаю неправильно, я думаю, что некоторая часть инициализации в сценарии запуска отсутствует.

Массив объявлен следующим образом:

struct elem{
uint32_t str;
uint32_t value;
uint32_t value2;
};

const struct elem array[]{
{(uint32_t)(*(uint32_t*)"CM1"), 1, 1},
{(uint32_t)(*(uint32_t*)"CM2"), 2, 2},
{(uint32_t)(*(uint32_t*)"CM3"), 3, 3}
};

соответствующий раздел сценария запуска:

inline void static_init()
{
for (void (**p)() = __preinit_array_start; p < __preinit_array_end; ++p)
(*p)();

for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
(*p)();
}

void reset_handler(void)
{

unsigned long *source;
unsigned long *destination;

// Copying data from Flash to RAM
source = &_data_flash;
for (destination = &_data_begin; destination < &_data_end;)
{
*(destination++) = *(source++);
}

// default zero to undefined variables
for (destination = &_bss_begin; destination < &_bss_end;)
{
*(destination++) = 0;
}

static_init();

#ifndef __NO_SYSTEM_INIT
SystemInit();
#endif

// starting main program
main();
}

и скрипт компоновщика:

/* Entry Point */
ENTRY(reset_handler)

_estack = 0x20010000; /* end of 128K RAM */
/* Specify the memory areas */
/*
0x08000000 until 0x08010000 is reserved for BOOTLOADER! (64k)
*/
MEMORY
{
EEPROM (rwx)    : ORIGIN = 0x08010000, LENGTH = 64K /*fake EEPROM!*/
FLASH (rx)      : ORIGIN = 0x08020000, LENGTH = 896K
RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 128K
RAM2 (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
}

SECTIONS
{
/* The startup code goes first into FLASH */
.isr_vector :
{
. = ALIGN(4);
__intvec_start__ = .;
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH

/* The program code and other data goes into FLASH */
.text :
{
. = ALIGN(4);
_text = .;
*(.text)           /* .text sections (code) */
_text2 = .;
*(.text*)          /* .text* sections (code) */
_rodata = .;
*(.rodata)         /* .rodata sections (constants, strings, etc.) */
*(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
*(.glue_7)         /* glue arm to thumb code */
*(.glue_7t)        /* glue thumb to arm code */
*(.eh_frame)
_init_data = .;
KEEP (*(.init))
KEEP (*(.fini))
. = ALIGN(4);
_etext = .;        /* define a global symbols at end of code */
} > FLASH

.ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
.ARM : {
__exidx_start = .;
*(.ARM.exidx*)
__exidx_end = .;
} >FLASH

.preinit_array     :
{
PROVIDE_HIDDEN (__preinit_array_start = .);
KEEP (*(.preinit_array*))
PROVIDE_HIDDEN (__preinit_array_end = .);
} >FLASH
.init_array :
{
PROVIDE_HIDDEN (__init_array_start = .);
KEEP (*(SORT(.init_array.*)))
KEEP (*(.init_array*))
PROVIDE_HIDDEN (__init_array_end = .);
} >FLASH
.fini_array :
{
PROVIDE_HIDDEN (__fini_array_start = .);
KEEP (*(SORT(.fini_array.*)))
KEEP (*(.fini_array*))
PROVIDE_HIDDEN (__fini_array_end = .);
} >FLASH

/* used by the startup to initialize data */
_sidata = LOADADDR(.data);

/* used by the startup to initialize data */
_data_flash = _sidata;

/* Initialized data sections goes into RAM, load LMA copy after code */
.data :
{
. = ALIGN(4);
_data_begin = .;
*(.data)
*(.data*)

. = ALIGN(4);
_data_end = .;
} >RAM AT> FLASH.bss (NOLOAD) :
{
. = ALIGN(4);
_bss_begin = .;
__bss_start__ = _bss_begin;
*(.bss)
*(.bss*)
*(COMMON)
. = ALIGN(4);
_bss_end = .;
__bss_end__ = _bss_end;
} > RAM

stack_size = 1024;
__stack_end__ = ORIGIN(RAM)+LENGTH(RAM);
__stack_start__ = __stack_end__ - stack_size;

heap_size = 0;
__heap_end__ = __stack_start__;
__heap_start__ = __heap_end__ - heap_size;

. = __stack_start__;
._stack :
{
PROVIDE ( end = . );
. = . + stack_size;
. = . + heap_size;
. = ALIGN(4);
} > RAM

_siccmram = LOADADDR(.ram2);
.ram2 (NOLOAD) :
{
. = ALIGN(4);
*(.ram2);
*(.ram2*);
. = ALIGN(4);
} > RAM2 AT> FLASH

/* Remove information from the standard libraries */
/DISCARD/ :
{
libc.a ( * )
libm.a ( * )
libgcc.a ( * )
}

.ARM.attributes 0 : { *(.ARM.attributes) }
}

-3

Решение

Вы можете использовать многозначный литерал: см. (6.) из символьный.

Обратите внимание на одинарные кавычки:

const struct elem array[]{
{'CM1', 1, 1},
{'CM2', 2, 2},
{'CM3', 3, 3}
};

Вы можете увидеть, как gcc оценивает литерал с несколькими символами:

https://gcc.gnu.org/onlinedocs/cpp/Implementation-defined-behavior.html#Implementation-defined-behavior

Компилятор оценивает многосимвольную символьную константу символ за раз, сдвигая предыдущее значение влево на количество битов на целевой символ, а затем перемещая его в битовом массиве нового символа, урезанного до ширины цели персонаж. Конечный битовый шаблон имеет тип int и поэтому подписывается независимо от того, подписаны ли отдельные символы или нет. Если в константе больше символов, чем уместилось бы в цели int, компилятор выдает предупреждение, а лишние начальные символы игнорируются.

0

Другие решения

Это должно работать и не иметь UB.
Тем не менее, это порядковый номер.

#include <iostream>
#include <cstdint>
#include <cstring>

using namespace std;

struct elem {
uint32_t str;
uint32_t value;
uint32_t value2;
};

uint32_t makeint(const char str[4])
{
uint32_t val;
memcpy( &val, str, 4 );
return val;
}

const elem arr[] = {
{makeint("CM1"), 1, 1},
{makeint("CM2"), 2, 2},
{makeint("CM3"), 3, 3}
};

int main()
{
for (auto& e : arr)
cout << e.str << endl;

cout << "\ndone\n";
}

Видеть это Вот

1

По вопросам рекламы [email protected]