const keyword usage

P

Pavel

I am writing software for an embedded application and here is the
question.

GCC would emit data declared like
const char text[] = "abc";
to .rodata (i.e. "read only data") section. I can put this section to
flash memory and that would be OK.

I have a structure with one member of it being
const char** array;
This 'array` holds a number of pointers like 'text` described above.
Suppose the structure name is 'str', than the typical declaration I
use is:

const char* arr[] = {text, text, text};
str s = {..., arr, ...};

Those objects ('arr' and 's') are declared global and GCC places them
in .data section;

But the rub is that sometimes I need to assign elements of 'arr' array
dynamically. I have the following declaration:

char* dyn_arr[5]; /*And the real values are assigned in the
program;*/
str dyn_s = {..., dyn_arr, ...};

When compiling this GCC says
'initialization from incompatible pointer type'

When assigning:
dyn_arr[0] = text;

GCC says: 'assignment discards qualifiers from pointer target type'.

Those things with const are to avoid copying read-only data from flash
memory where whole program is stored to RAM as it is done with .data
section which contains "rw" variables;

I see the following solutions:
1) ignore GCC warnings (I wouldn't like doing that)
2) remove 'const' keyword and place read-only data to separate section
which I would not copy to RAM

Your suggestions?

Thanks,
Pavel
 
D

dandelion

Pavel said:
I am writing software for an embedded application and here is the
question.

But the rub is that sometimes I need to assign elements of 'arr' array
dynamically. I have the following declaration:

char* dyn_arr[5]; /*And the real values are assigned in the
program;*/
str dyn_s = {..., dyn_arr, ...};

When compiling this GCC says
'initialization from incompatible pointer type'

And it should. The 'const' keyword is saying to the compute "This won't
change" so it can (safely) be optimized and stuffed in (for instance) flash
or (more specifically) in a read-only output segment.

If you *do* assign values to it, do not use the const keyword. You'd be
lying to the compiler, which is *really* pathetic.
When assigning:
dyn_arr[0] = text;

GCC says: 'assignment discards qualifiers from pointer target type'.

Those things with const are to avoid copying read-only data from flash
memory where whole program is stored to RAM as it is done with .data
section which contains "rw" variables;

I see the following solutions:
1) ignore GCC warnings (I wouldn't like doing that)

I fully agree with that sentiment.
2) remove 'const' keyword and place read-only data to separate section
which I would not copy to RAM

Sounds OK.
Your suggestions?

Split up your texts into a *really* const char[] part and a non-const char[]
part. That way, you have the advantages of const where applicable and the
char array[] where neccesary. I do not know how your data is structured
internally, so I can't really judge if this is realistic, but it would be
the cleanest solution IMO.

HTH,

dandelion
 
L

Lawrence Kirby

I am writing software for an embedded application and here is the
question.

GCC would emit data declared like
const char text[] = "abc";
to .rodata (i.e. "read only data") section. I can put this section to
flash memory and that would be OK.

I have a structure with one member of it being
const char** array;
This 'array` holds a number of pointers like 'text` described above.
Suppose the structure name is 'str', than the typical declaration I
use is:

const char* arr[] = {text, text, text};

The error below is highlighting a possible design problem here. text is
read-only, an attempt to write to it is an error. The type of arr reflects
this, you can't write to text through arr without doing something very
deliberate like a cast.
str s = {..., arr, ...};

OK, arr is an initialiser for the .array member of type const char **.
Similarly this is OK and s.array can't be used to write to the read-only
data without some skullduggery.
Those objects ('arr' and 's') are declared global and GCC places them
in .data section;

IOW they are writable, which is fine because those objects
themselves aren't const.
But the rub is that sometimes I need to assign elements of 'arr' array
dynamically. I have the following declaration:

char* dyn_arr[5]; /*And the real values are assigned in the
program;*/
str dyn_s = {..., dyn_arr, ...};

You can view this as trying to make dyn_array part of a datastructre that
can't write to the underlying strings, but you can do so through dyn_arr
itself which is inconsistent. There would also be "holes" in the const
system if the language didn't enforce the rules that apply to this case.
When compiling this GCC says
'initialization from incompatible pointer type'

When assigning:
dyn_arr[0] = text;

GCC says: 'assignment discards qualifiers from pointer target type'.

Those things with const are to avoid copying read-only data from flash
memory where whole program is stored to RAM as it is done with .data
section which contains "rw" variables;

I see the following solutions:
1) ignore GCC warnings (I wouldn't like doing that)

You could use a cast here. In fact that may not silence the warnings but
at least it avoids a constraint violation. Casts should be avoided where
possible, but are there to be used when you can show that no problem
results and there isn't a better way. There may still be a better way here.
2) remove 'const' keyword and place read-only data to separate section
which I would not copy to RAM

You don't need to do that. I'd use a cast if that was the only other
option.

Consider defining dyn_arr as

const char *dyn_arr[5];

That is consistent with the rest of your datastructure and resolves the
type conflicts. This means that you can't use dyn_arr to modify the
strings its elements point to. That's a good thing if they point to
things like text that are read-only. You can still write to dyn_arr itself
i.e. make its elements point to different strings.

The question is really how you manage the strings. If you can set up a
string and then set dyn_arr[x] to point to it then no problem:

const char *dyn_arr[5];
char mystr[10];
strcpy(mystr, "A string");
dyn_arr[1] = mystr;


is fine. What you can't do directly is use dyn_arr[1] to modify mystr. You
can of course create a new string in a different object and change dyn_arr
to point to that. And you can still modify mystr directly or through a
different datastructure that doesn't reference it as const, and then
access that modified string through dyn_arr[1].

Lawrence
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top