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?
I suspect that the strings are placed somewhere in memory and numerous_strings[] contains pointers to the strings.
I've never worked with 8051's, is there a way to to take the size of the array / the size of a pointer?
Specifically I am using version 7.5 of the C51 compiler (this stated for odd handling of const discussion later).
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. So it determined the array size as 0. This means 0/sizeof(char code *) is 0. As zero divided by any number is zero. I also tried using a const definition but the compiler allocates a const in data space. in the header for the module
const unsigned short number_of_numerous_strings;
in the module itself.
const unsigned short number_of_numerous_strings = (sizeof(numerous_strings)/sizeof(char *)));
is done by creating a unsigned short in data space ... as for where the actual constant is loaded I think startup had more code added (sigh). That's incorrect because it's not a variable it's a constant. It should be treated the same as 54 or 21 with the rest of the code (IE a literal) because it is a constant (IE it doesn't change it's static inflexible unchangeable). Unfortunately with using data space for storing a constant means that constant CAN change (which is by definition against the very definition of a constant) Unfortunately constants require a type and I suspect the point where a type is used makes the compiler do some interesting things. Is const ignored by the compiler or something? I tried const on an array type before and it also was allocated to data space. This is incorrect in my point of view, it should be in CONSTANT SPACE(IE code ) or become a literal depending on if it is an array (IE character string) or a singular value (IE 123). Literal string arrays appear to be treated correctly however other array types (const list of pointers to const strings) seem to become stuffed into Data space. In any case consts can't be changed, and allocating it to data space is a questionable practice. The behavior exhibited by typical X86 compilers is to use a literal (IE the const is treated the same as an EQU in assembly and not as a variable type) for a const.
Stephen
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.
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.
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!
View all questions in Keil forum