We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I take it using sizeof() on a array that is unbounded is a problem (I am getting sizeof returns size of type 0 warnings).
I have defined a constant array of pointers unbounded IE
#define CCHARPTR code char * CCHARPTR numerous_strings[] = { "string1", "string2", "string3.5" };
If I wished to know the number of entries in numerous_strings I thought I could do this
(sizeof(numerous_strings)/sizeof(CCHARPTR))
Obviously I was wrong since the compiler warns sizeof(numerous_strings) is zero. How can I get the size of this array because I would like to save time in having to write a 'magic' number for the number of numerous_strings. Sounds simple, unbounded arrays seem to be what it has issues with. Suggestions anyone?
Actually that is what I was doing the issue it was having that outside the scope of the module it decided that an unbounded array has no size.
Close but no cigar. The "it" that decided this is the C language definition, not Keil's compiler. And it would have helped if you had mentioned that you were trying to use sizeof() outside the scope of the array's definition right away.
That's incorrect because it's not a variable it's a constant.
Your idea of what is and isn't correct is based on incorrect assumptions. C variables qualified as 'const' don't stop being variables; in particular they don't stop having an address by which their value is accessed. A 'const'-qualified C variable is not the same as an asm EQU symbol.
Yes that is the unfortunate conclusion I came up with. It's hard to get around finding the size of an unbounded array outside the scope of the module. The work around I attempted was to use a const. This brings up the literal constant versus a variable constant issues you are referring too. I've seen it done BOTH ways (IE make a constant a literal and treat the constant as if it were a type defined literal). The latter is what I was expecting to happen I guess that is subjective to the compiler in the end.
--
So my real 'need' is to have a literal representing the number of elements of an unbounded array. This is not possible without using a const or doing some very ugly code. I was able to get around this problem in an clumsy annoying fashion (it's kind of ugly).
The include file
extern code uint8_t number_of_strings;
The module definition
code uint8_t number_of_strings = (sizeof(numerous_strings)/sizeof(char *));
As I said VERY ugly, it works but not like a literal would.
Stephen
Another way to approach the problem would be with a little bit of preprocessing. Here's what I mean:
1. List your numerous strings in a plain old text file, with one string on each line. To match the example you gave, the file would look like this:
"string1", "string2", "string3.5"
2. #include this file in your C program, thus:
CCHARPTR numerous_strings[] = { #include "mystrings.txt" };
3. Write a small program that counts the strings in the text file and spits out a tiny header file containing something like
#define NUMBER_OF_NUMEROUS_STRINGS 3
4. #include the header file wherever you need to.
5. Set up your build environment (makefile, batch files, IDE, or whatever) to run the C program just before each build.
This is probably overkill for what you are doing, but the general technique can be extremely useful in more complicated situations.
-- Russ
Stephen,
I've made this same argument before when I was flummoxed by this sort of array-size-as-a-constant problem. The problem is what the C standard allows to be considered a "true" constant (ie. one that is equivalent to a literal, can be used for sizing arrays, etc.). Here's the problem only addition and subtraction on other constants yield a constant result. Once you divide or multiply a constant by anything (including a literal), it is no longer considered a "true" constant, despite the const qualification.
-Jay Daniel
Here's the problem only addition and subtraction on other constants yield a constant result.
Whatever led you do that conclusion? It's wrong. Any expression involving only constants can be used in any place a constant is required. E.g.
int array[5*30+5<<3];
works just fine.
despite the const qualification.
That doesn't make any sense --- as const qualifiers don't make anything a constant. They make an object immutable.
So my real 'need' is to have a literal representing the number of elements of an unbounded array.
That can be done, but only indirectly. You have to define the array and the length (macro) separately, then rely on either a hack (compile-time Assert()) or external tools (e.g. Lint) to tell you if they ever run out of synch. Lint will warn you right away if NELEM in
int array[NELEM] = { /*...*/ }
doesn't correspond to the actual number of entries in the initializer.
That's very interesting regarding multiplication and division on constants. I can see why that might be a problem or compiler dependent at least. Interestingly enough my code uint8_t value comes out 27 (27 strings are size 81 / 3 bytes per string pointer == 27). C Side thought: Perhaps because of how varied C handles things an operator of elementsof() (IE return the number of elements) of something. This makes it sizeof(type) agnostic and implicitly does on the work. However again it won't work with unbounded arrays that are defined in a different module because the array size is unknown to anything but within that module. However
const my_array_size = elementsof(my_array);
would assign the const with the literal number of elements at least. I doubt that will ever happen however as it's not a common use to find out how many elements are in an array. The assumption is you should already know (this of course ignores unbounded arrays).
The enumeration system I see suggested is actually possibly the best way to handle the problem for me ironically, it's still a bit of work (add a string you have to add to that enumeration statement then). I was attempting to avoid having to redefine a #define statement every time I added a string to the array. It's used to do a sanity check when referencing the array of strings. The enumeration method may be necessary to begin with (for clarity of what string is being used as the strings are more like a series of drawing commands than just plain text.)
Hans-Bernhard,
You are correct in stating I'm wrong. I've managed to confuse issues from both C and C++ into one formulation of a wrong answer. Thanks for setting the OP right!
That's not different from the existing
const size_t my_array_size = sizeof(my_array)/sizeof(my_array[0]);
in any useful way.