initialiser element is not constant
Asked Answered
D

2

5

I want to create vector-table to create start-up code for MCU when I try to put function address in to the vector-table the compiler produces an error: initialiser element is not constant

void reset_handler(void);

uint32_t const vector_table[] = {
    STACK_START,
    (uint32_t)&reset_handler
};

void rest_handler(void)
{
}

I always use function pointer type to create array of function but this time I want to know why when I use uint32_t type array I cannot put the address of a function in it

Dalliance answered 21/2, 2023 at 18:19 Comment(4)
It is caused by the conversion to the wrong integer type. The message emmited by GCC is wrong gcc.gnu.org/bugzilla/show_bug.cgi?id=108875 & gcc.gnu.org/bugzilla/show_bug.cgi?id=22020Demetrius
Mohammad Pourbahram, Note that a function pointer may be wider than 32-bit. C does not specify an integer type always wide enough for a function pointer.Church
@chux-ReinstateMonica the vector table structure is same as ARM Cortex-M. Pointers and function pointers are 32 bit there.Demetrius
You would do better in n any event to use uintptr_t>Almanac
G
3

From the C Standard (6.6 Constant expressions)

6 An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.

This expression (uint32_t)&reset_handler with the cast operator used to initialize an integer is incorrect because the operand of the cast operator does not have an arithmetic type. So it may not be used to initialize integer objects (elements of an integer array) with static storage duration.

So the compiler issues the error

initialiser element is not constant

You could move the array declaration for example from the file scope in main. In this case the array will have automatic storage duration. Nevertheless in any case this casting (uint32_t)&reset_handler of a function pointer to an integer of the type uint32_t is wrong.

Geriatric answered 21/2, 2023 at 18:25 Comment(17)
6.6p9 is relevant here: "An address constant is a null pointer, a pointer to an lvalue designating an object of static storage duration, or a pointer to a function designator. ..." OP needs to use an actual pointer and not use a dubious cast to uint32_t.Appose
@AndrewHenle But he is trying to initialize an array of integers.:)Geriatric
It is not wrong on the ARM Cortex-M targets. It has to be const to be places in the FLASH memory.Demetrius
@Demetrius And why does the compiler issue the error in your opinion?Geriatric
I use avr-gcc and gcc compiler both of them give me same errorDalliance
@MohammadPourbahram You cant use arv-compiler to compile code for ARM Cortex targetsDemetrius
@VladfromMoscow because converting function pointer to wrong integer type invokes UB. The error message is wrong. Probably bugDemetrius
@Demetrius Reread one more the error message. I doubt that it is a bug. It is a reasonable error message.Geriatric
godbolt.org/z/3cj97YzTd and godbolt.org/z/16YoK433r and godbolt.org/z/YoP9bx86a You see? Sometimes it gives wring error messages. function pointers are constant expressionsDemetrius
@Demetrius There are the same error message and a warning. So it is not a bug of the compiler.Geriatric
@VladfromMoscow I am right gcc.gnu.org/bugzilla/show_bug.cgi?id=22020 and my one which was marked as the dupe gcc.gnu.org/bugzilla/show_bug.cgi?id=108875Demetrius
@Demetrius According to the C Standard the error message is correct. There is no used a constant expression. See the quote from the C Standard I provided.Geriatric
@VladfromMoscow it is not. Function reference is constant expressionDemetrius
@Demetrius There is a casting of a function pointer. Pointers are not arithmetic types.Geriatric
@VladfromMoscow More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following: ... an arithmetic type, - read the rest in the standard. Conversion of function pointer evaluates to the integer typeDemetrius
@Demetrius Function pointer to a static function is a constant expression of a function pointer type but casting it to integer is not a constant arithmetic type.Geriatric
@Demetrius In general this question is interesting. Maybe you should ask it to the C Standard Committee.Geriatric
D
-1

I use avr-gcc and gcc compiler both of them give me same error

The code shows that the vector table is for ARM-Cortex target. You cant use avr-gcc or x86 gcc to compiler code targeting ARM Cortex-M

You can't do this for the targer where sizeof function pointer is different that sizeof(uint32_t)

Using arm-gcc you can do this as the function pointer size is 4 bytes long and fits uit32_t.

It is a very common way of creating vector tables in C language on 32-bit Cortex-M targets.

https://godbolt.org/z/P3v77ah7K

#define STACK_START 0x2000000

void reset_handler(void);
const uint32_t vector_table[]  =
{
    STACK_START,
    (uint32_t)&reset_handler
};
void rest_handler(void)
{
}

and resulting code:

rest_handler:
        bx      lr
vector_table:
        .word   33554432
        .word   reset_handler
Demetrius answered 21/2, 2023 at 18:42 Comment(1)
Comments have been moved to chat; please do not continue the discussion here. Before posting a comment below this one, please review the purposes of comments. Comments that do not request clarification or suggest improvements usually belong as an answer, on Meta Stack Overflow, or in Stack Overflow Chat. Comments continuing discussion may be removed.Disseminate

© 2022 - 2024 — McMap. All rights reserved.