Vars in flash not visible from another translation unit

I have encountered a C++ issue that I am seeking some advice on. For the arm architecture, I can declare a const, specifically a character string, in one translation unit (file) and ensure that the const is put into flash memory. However, I cannot access the const from another translation unit. Here is an example.

The following declaration will create a constant character string "hello" and it will be located in flash memory:

file1.h:

const char str[] = "hello";

To access the variable name from another translation unit, I try to use extern as follows:
file2.h:

extern const char * str;

However, this generates an error indicating that the declarations are different:

error: conflicting declaration 'const char str []'
 const char str[] = "hello";
note: previous declaration as 'const char* str'
 extern const char * str;

If the declaration is changed to:
file1.h:

static const char * str = "hello"

Then the variable cannot be accessed outside of the scope it was declared in (because of the static keyword).

So, I cannot find the correct way to access a const stored in flash from another translation unit. Does anyone have any suggestions regarding how to do so?

put
const char str[] = "hello";
in .cpp

I still get the error. The compiler is complaining that the two definitions are conflicting:

const char str[] vs const char * str

sslupsky:
I still get the error. The compiler is complaining that the two definitions are conflicting:

const char str[] vs const char * str

what two definitions. you should have

const char str[] = {...}
in cpp

and

extern const char str[];
in .h

sslupsky:
I still get the error. The compiler is complaining that the two definitions are conflicting:
const char str[] vs const char * str

The definitions ARE conflicting. In one place you say 'str' it the address of the first character in an array of characters and in the other you say that 'str' is the address of a pointer that contains the address of a character. They are not the same thing and thus you can't have the name declared both ways at the same time.

@Juraj,

Thanks. I had earlier tried the opposite combination but that doesn't put the string into flash memory.

Reversing it, as you showed, solved the problem. I thought I did that at one point but I must have had another issue and mistakenly thought it didn't solve the problem.

Thank you :slight_smile:

@johnwasser

You are exactly correct, which is why I was scratching my head on this one. @Juraj helped me get my thinking straight on this and resolved it.

Thanks for taking the time to provide some feedback.

I do have one other conundrum. I am trying to determine if the strings in the following struct are stored in flash memory or not with the following declaration:

const struct cliCmd_t {
    const char * helpCmd  = "help";
    const char * loglevelCmd  = "loglevel";
} cliCmd;

I used the nm tool to look at the memory but I cannot find anything resembling any of the names used so I cannot tell. Does this look correct to you? My suspicion is they are not.

what MCU is it? on AVR and esp you must use the PROGMEM macro to put the strings in macro and on you must handle the progmem strings with dedicated functions
on AMR (SAM(D), nRF5) architectures there is no special progmem string handling

@Juraj,

MCU is SAMD21. My understanding when using ARM is you can put strings into flash memory as follows:

const char someString[] = "Some String";

static const char * anotherString = "Another String";

However,

const char * yetAnotherString = "Yet Another String";

does not cause the string to be located in flash.

Moreover, the form const char someString[] when in the global namespace puts the string into global flash. What I think I am seeing with the struct{} is that even if the struct{} is defined const in the global namespace, when you use a struct member it in a member function, the string is allocated to flash local to the member. So, if the same string is used in multiple places, it is replicated in flash multiple times within the flash for each member function that uses it.

I would like to direct the compiler to store the strings within the struct to be located in global flash.

on SAMD21 I don't care. there is much more RAM then I need.
but this are the same rules as for PROGMEM on AVR

why don't you use?:

const struct cliCmd_t {
const char helpCmd[] = "help";
const char loglevelCmd[] = "loglevel";
} cliCmd;

btw: it is not about 'putting' in flash or not. they are there as part of the application. it is about using them from flash without loading them to RAM at start

Agreed, "putting" is probably the wrong way to describe it.

I think I have been able to confirm that the strings within the global struct{} are being store in global flash. For some reason the global struct{} does not appear in the nm output so it is difficult to discern where the strings were put and if there are any pointers in ram referencing the strings.