As discussed in [Access symbols defined in the linker script by application](https://stackoverflow.com/questions/8398755/access-symbols-defined-in-the-linker-script-by-application), "Accessing a linker script defined variable from source code is not intuitive" - essentially, accessing their *value* usually isn't what you want (since they don't really have a block of memory assigned, as a true compiler variable), and only their accessed by their *address*. Is there an attribute that can be applied to the variable upon declaration, or perhaps a PC-Lint/static-analysis property/rule which can be applied to the variables?

```
/* Linker config (.icf) file */
define symbol __ICFEDIT_region_ROM_start__  = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__    = 0x080FFFFF;

define symbol __ICFEDIT_region_ROM_size__ = (__ICFEDIT_region_ROM_end__ - __ICFEDIT_region_ROM_start__) + 1;
export symbol __ICFEDIT_region_ROM_start__;
export symbol __ICFEDIT_region_ROM_size__;

```

```c
/* main.c */
void OS_SetROM(uint32_t start, uint32_t size){} // empty for demonstration only
int main(void)
{
  extern unsigned int __ICFEDIT_region_ROM_start__;
  extern unsigned int __ICFEDIT_region_ROM_size__;

  // INCORRECT - both probably read as '0', depending on what's actually in those locations
  // Can I get a warning or error about this usage?
  OS_SetROM(__ICFEDIT_region_ROM_start__, __ICFEDIT_region_ROM_size__);
  // CORRECT - *addresses of* linker-defined variables read
  OS_SetROM((uint32_t)&__ICFEDIT_region_ROM_start__, (uint32_t)&__ICFEDIT_region_ROM_size__);

```

It would be *nice* to have the addresses declared and behave as pointers (as below), i.e. where you can use the value of the pointer variable to represent the *address*, and 'value-of' semantics make more sense (at least logically - more obvious that you wouldn't dereference in this case), but this isn't how they work - for that, the linker would have to assign a memory location as well and store the address *there*, or some special semantics of the compiler/linker, which doesn't appear to be possible...

```c
void void OS_SetROM(uint32_t * const start, uint32_t size){} // empty for demonstration only
int main(void)
{
  // would be nice, but not how it works
  extern unsigned int * const __ICFEDIT_region_ROM_start__;
  extern unsigned int const __ICFEDIT_region_ROM_size__;

  OS_SetROM(__ICFEDIT_region_ROM_start__, __ICFEDIT_region_ROM_size__);

```

A compromise of-sorts could be to redefine these variables with an appropriate type, ala:

```c
unsigned int * const p_rom_start = &__ICFEDIT_region_ROM_start__;
unsigned int const rom_size = (unsigned int)&__ICFEDIT_region_ROM_size__;

void OS_SetROM(unsigned int * const p_start, unsigned int size);

OS_SetROM(p_rom_start, rom_size);

```

which helps collect the 'unintuitive' accesses into one place and type-safe accesses thereafter, but that isn't possible in this case as the API is predefined to require uint32\_t's.

I realize this is probably uncommon (and probably only used a few times within a project, if at all), and I realize this also depends on using the attribute (e.g. when creating a new project), but I'm curious if there are guards that can be put in place to protect against accidental misuse - or against incorrect 'simplification' (e.g. by some maintainer later who doesn't understand the implications)... I also can't think of another scenario where enforcing 'address-only' access makes sense, so the solution may not exist...