to determine the number of elements in an array. The compiler now says:
Invalid application of 'sizeof' to incomeplete type 'int []'
The advantage was that the macro could determine the size of any array, and did not require a specified type to be present in the macro; it was "typeless". I've tried this with a void pointer, but still no joy. What am I doing wrong or have the rules changed?
I can't post the file because of an NDA. I've tried to write a short program to illustrate the issue, but those all work fine. I'll keep trying to duplicate the error with a short section of code. Until then, I'll have to assume it's something I'm doing in the project. I'm using the 1.8.10 version of the IDE.
Then take your existing function and start stripping unnecessary things out (making sure the error still happens) until you're comfortable posting that. I have a suspicion about what you're doing, but I can't confirm that until I see what you're doing. My tests have given a different warning message than what you posted.
I took an earlier version of the code, which was all lumped together into one big INO file, and broke it out into CPP files, mainly along lines of functionality. That's the version that doesn't compile. The single INO file compiles just fine, so it is something I did when I broke up the file. I'll try to track it down tomorrow and report what I find...when I find it. Sorry for the false alarm.
The first rank is left empty on all array declarations in the header file. Those ranks are filled in when those same arrays are defined in the INO file. If the arrays are multidimensional, only the 2nd and higher ranks are supplied in the data declarations (i.e., in the header file using extern). There are no dynamic array definitions in the code.
You have to understand how your code is compiled: Each CPP file* is compiled separately, and header files are just pasted into the CPP file before compilation. After the CPP files have been compiled into object files, they are linked together into the final binary.
There is no interaction between two CPP files at compile time, so there is no way your INO file can know the array size, unless you declare it in the header file.
(*) The Arduino builder stitches all INO files into a single CPP file.
sketch/stuff.cpp: In function 'void printSize()':
stuff.cpp:6:25: error: invalid application of 'sizeof' to incomplete type 'int []'
Serial.println(sizeof stuff / sizeof stuff[0]);
^~~~~
exit status 1
invalid application of 'sizeof' to incomplete type 'int []'
The .cpp file has no way of knowing how the external int array was declared in the .ino. All it gets is the address from the linker.
To work around this limitation of C++, make a global 'size_t stuffSize' in the .ino and reference it in the .cpp. Although it is a compile-time constant you can't declare it 'const' since that, apparently, implies 'static' which mean it can't be seen in other "compilation units" (source files).
PieterP:
You have to understand how your code is compiled: Each CPP file* is compiled separately, and header files are just pasted into the CPP file before compilation. After the CPP files have been compiled into object files, they are linked together into the final binary.
There is no interaction between two CPP files at compile time, so there is no way your INO file can know the array size, unless you declare it in the header file.
(*) The Arduino builder stitches all INO files into a single CPP file.
Pieter
I am well aware of how compiles are handled by the GCC compiler. I owned a small software company for almost 20 years and one of our lines was programming tools. We wrote and marketed our own MSDOS C compiler back in the '80's.
In the current project, I used the standard preprocessor directive (e.g., #ifndef) in each CPP file to include the necessary declarations, function prototypes, and definitions as required in each of the source files.
@John: Doesn't that approach destroy the "typelessness" of the macro? Also, you aren't passing the array to the macro, so you're limited to the named array, which isn't very flexible.
First, thanks to everyone who took the time to read/post.
I'm not sure exactly what fixed it, but I deleted and retyped the preprocessor directives at the top of each file (*.ino, *.cpp, and *.h) which were used to toggle the reading of the header file which controlled the data declarations (e.g., function prototypes and extern data declarations). All I did was retype what was there in the first place. None of the directives were misspelled, or the compiler would have caught it. I'm starting to think there may have been some non-printing character somewhere near the top of the file. I have no other explanation, but the macro is now working as it should.