C and const - bewildered

Thread Starter

ApacheKid

Joined Jan 12, 2015
1,762
I've often been bewildered I recall, by the "const" keyword in C. I know what it's supposed to do but it sometimes appears to be ignored.

look:

Code:
struct nrf_hal_support_interface
{
    const void (*init_spi)(SPI_HandleTypeDef * spi_ptr);
    void (*init_control_pins)();
    void (*spi_ce_lo)(void *);
    void (*spi_ce_hi)(void *);
    void (*spi_cs_lo)(void *);
    void (*spi_cs_hi)(void *);
    void (*exchange_bytes)(void *, uint8_t[], uint8_t[], uint8_t);
    void (*read_bytes)(void *, uint8_t bytes_in_ptr[], uint8_t count);
    void (*write_bytes)(void *, uint8_t bytes_out_ptr[], uint8_t count);
    void(*init_device)(SPI_HandleTypeDef * spi_ptr, NrfSpiDevice_ptr device_ptr, NrfIoDescriptor_ptr descriptor_ptr);
    void(*flash_led_forever)(uint32_t interval);

};
Then look:

Code:
const nrf_hal_support NrfHalSupport =
{
    .init_spi = init_spi,
    .init_control_pins = init_control_pins,
    .spi_ce_lo = spi_ce_lo,
    .spi_ce_hi = spi_ce_hi,
    .spi_cs_lo = spi_cs_lo,
    .spi_cs_hi = spi_cs_hi,
    .exchange_bytes = exchange_bytes,
    .read_bytes = read_bytes,
    .write_bytes = write_bytes,
    .init_device = init_device,
    .flash_led_forever = flash_led_forever
};
Yet this other code compiles:

Code:
NrfHalSupport.init_spi = NULL;
If the member "init_spi" has been declared as const why am I able to change it? but in this case its worse, because the declared struct instance is also const!

Furthermore, this compiles but why? it's meaningless surely?

Code:
static const void init_spi(SPI_HandleTypeDef * spi_ptr);
 

Thread Starter

ApacheKid

Joined Jan 12, 2015
1,762
Actually I kind of answered my own question. The code that is modifying the "init_spi" member actually declares the struct as:

Code:
extern nrf_hal_support NrfHalSupport;
changing that to

Code:
extern const nrf_hal_support NrfHalSupport;
fixed, it now no longer compiles as desired.
 

Thread Starter

ApacheKid

Joined Jan 12, 2015
1,762
This is kind of weak, I can declare a global variable as const but then declare it outside as extern with or without the const.

I'd expect the const on the global declaration to dominate, so that I can't gain the ability to modify it just by omitting const from the extern declaration. I guess this is all to do with the fact that everything is compile time, so the compiler has no idea that some extern is actually defined in another file as const, this makes sense I suppose.

I'm too used to working with .Net where the compiler when compiling source has full awareness of the metadata for all externally defined types, just as Java does.
 

Thread Starter

ApacheKid

Joined Jan 12, 2015
1,762
Ahhh - this is solved, very neatly too. The struct is defined in a typedef and if I add const to that typedef (which unlike globals and externs, all code sees at compile time) it works and I don't need const anywhere else, just in the typedef is enough!

Code:
typedef struct nrf_hal_support_interface const nrf_hal_support;
 

nsaspook

Joined Aug 27, 2009
16,251
Yes, you're creating a separate variable with the extern statement that linker will later share pointers with.

1667504007798.png
The compiler simply follows your command for all access until you command it not to.
1667505569167.png
 
Last edited:
Top