Re: const keyword usage

From: Lawrence Kirby (lknews_at_netactive.co.uk)
Date: 12/23/04


Date: Thu, 23 Dec 2004 13:08:38 +0000

On Thu, 23 Dec 2004 00:25:18 -0800, Pavel wrote:

> 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



Relevant Pages