Re: #defining an array within another in C language
- From: prix prad <maalage@xxxxxxxxx>
- Date: Sat, 8 Mar 2008 02:42:31 -0800 (PST)
On Mar 8, 12:10 am, Michael Mair <Michael.M...@xxxxxxxxxxxxxxx> wrote:
prix prad wrote:
Hi All,
I am trying to create two arrays at compile time using the
#define statement.
I am seeing only one, that may be part of the problem.
I am getting a compilation errors due to this;
***************************************************************************************************
debug_flag_size.c: In function `main':
debug_flag_size.c:32: error: syntax error before ';' token
debug_flag_size.c:33: error: syntax error before '}' token
debug_flag_size.c: At top level:
debug_flag_size.c:44: error: syntax error before string constant
debug_flag_size.c:44: error: conflicting types for 'printf'
debug_flag_size.c:44: note: a parameter list with an ellipsis can't
match an empty parameter name list declaration
debug_flag_size.c:44: error: conflicting types for 'printf'
debug_flag_size.c:44: note: a parameter list with an ellipsis can't
match an empty parameter name list declaration
debug_flag_size.c:44: warning: data definition has no type or storage
class
***************************************************************************************************
How can I do the defining of this such arrays. I don't know how many
ELEM types are there.
You mean, you do not know the number of elements of the array.
The code is :
****************************************************************************************************
typedef struct new_type_ new_type;
struct new_type_ {
int var;
const num_array arr[0];
num_array? I'll assume
typedef int num_array[3];
};
Note that this is not standard C; you may want to look either at
C99 flexible array members or the plain old "struct hack".
#define START 0xABCDEF12;
Note that ";" seldom is a good idea at the end of a macro --
you change a couple of things and everything will break.
#define MIDDLE(arr) const new_type M ## arr = {\
START,\
And here it breaks.
MIDDLE_OLD(arr)\
};
And here is another semicolon that will break things
if MIDDLE is abused (im)properly.
#define MIDDLE_OLD(arr) num_array arr[] = {
Think about how this expands -- this would never compile
when written out but inside macros it should work?
#define ELEM(a,b,c) {a, b, c},
For "," similar things apply; if you use the above in
the wrong context, you may end up with a , operator, or
something separating a list of init values from another
declared variable or ...
#define ELEM_END {-1,-1,-1}};
How is this supposed to work?
Note that it is potentially wasteful to have this large
"terminating array".
main() {
MIDDLE(abc)
ELEM(2,3,5)
ELEM(8,9,15)
ELEM(15,30,50)
ELEM(10,11,12)
ELEM_END
printf("\n Hi");
return 1;
I suggest
#include <stdio.h>
#include <stdlib.h>
at the beginning of the "file" and
return EXIT_FAILURE;
here.
Note that not outputting a '\n' as last character may lead
to your not seeing any output at all.
}
*******************************************************************************************************
What you want to have is a struct type containing an array that
is exactly as large as needed.
That is not possible in C.
What you can have is
struct myArrStruct {
int var;
size_t arrSize;
const num_array *arr;
};
num_array myArray[] = {
ELEM(1,2,3),
ELEM(4,5,6),
ELEM(7,8,9)
};
struct myArrStruct myStruct = { ID, ARR_DESC(myArray)};
where
#define ARR_DESC(A) ((sizeof (A))/(sizeof (A[0]))), A
#define ELEM(a, b, c) {(a), (b), (c)}
If you really do not want to type "," in your init lists,
then I'd suggest
#define START_ELEM(a, b, c) {(a), (b), (c)}
#define ELEM(a, b, c) , {(a), (b), (c)}
rather than using an END_ELEM. It often is easier to keep
track of the first element.
num_array myArray[] = {
START_ELEM()
ELEM()
ELEM()
};
The above approach has the advantage that you also can
allocate storage dynamically and assign it to the arr member.
If you really, really want to hide the num_Array, you can
try to get creative.
The opposite way, doing everything explicitly, usually is
an even better idea.
Here is the complete programme; I did not check it thoroughly.
#include <stdio.h>
#include <stdlib.h>
typedef int num_array[3];
struct myArrStruct {
int var;
size_t arrSize;
num_array *arr;
};
#define ARR_DESC(A) ((sizeof (A))/(sizeof (A[0]))), A
#define START_ELEM(a, b, c) {(a), (b), (c)}
#define ELEM(a, b, c) , {(a), (b), (c)}
#define ID 0xABCDEF12
int main (void) {
num_array myArray[] = {
START_ELEM(1, 2, 3)
ELEM(4, 5, 6)
ELEM(7, 8, 9)
};
struct myArrStruct myStruct = { ID, ARR_DESC(myArray)};
puts("\n Hi");
return EXIT_FAILURE;
}
Cheers
Michael
--
E-Mail: Mine is an /at/ gmx /dot/ de address.- Hide quoted text -
- Show quoted text -
Hi All,
First of all, thanks Michael for the reply. I shouldn't
have ended the
#define START 0xABCDEF12 with a semicolon. Removing that fixed one
error though I am hitting others.
Let me be more specific here about what I am trying to
achieve. The above program posted here is a demo one; the actual
specifics are a little different. I am working with a few things here
that cannot be changed.
The structure of each ELEM is of the form
**************************************************************************************
typedef struct num_array_ num_array;
struct num_array_{
boolean *var;
char *txt;
int num;
}
**************************************************************************************
in a header file say foo.h. This is a structure in the pre-existing
code. Using this structure we construct an array like :
*************************************************************************************
#define ARRAY(array_name) const num_array = {
#define MEMBER(variable, enum, text) {&variable, text},
#define ARRAY_END { (boolean *)NULL, (char *) NULL } };
*************************************************************************************
Now many .c files include foo.h and define something like this for
file1.c:
*************************************************************************************
ARRAY(file1_array)
MEMBER(file1_var1, ENUM_1, "FILE 1's first variable")
MEMBER(file1_var2, ENUM_2, "FILE 1's second variable")
.
.
.
MEMBER(file1_varN, ENUM_N, "FILE 1's Nth variable")
ARRAY_END
*************************************************************************************
A file can have any number of members; hence I said that 'I don't know
the number of elements of the array'
Now I want to do add a START and an END delimiter for each array
defined in this way.
I can do:
*********************************************************************************************
#define START_DELIMITER 0xABCDEF12
#define END_DELIMITER 0xFEDCBA21
#define ARRAY(array_name) const num_array[] = {\
{(boolean *)START_DELIMITER,
(char *) START_DELIMITER}
#define MEMBER(variable, enum, text) ,{&variable, text}
#define ARRAY_END ,{(boolean *)NULL, (char *)
NULL }\
,{(boolean *)END_DELIMITER,
(char *) END_DELIMITER};
*********************************************************************************************
After 'bounding' each array in this way; when the program gets
executed I can use these 2 delimiters to locate 'each' of such arrays
so that I can do processing on them.
However I am unable to add the START_DELIMITER as the .c files do
something like this:
Say for file1.c
******************************************************************************************
for(int i=0; file1_array[i].var; i++)
{
*(file1_array[i].var) = TRUE;
}
******************************************************************************************
Adding the START_DELIMITER would push the other members down by 1
row and
dereferencing the var member of the file1_array[0] would crah the
program since we are trying to do *(0xABCDEF12).
The simple approach would have been that the .c files now change
their code to start processing from the first element of the
array......say
*************************************************************************************
for(int i=1; file1_array[i].var; i++)
{
*(file1_array[i].var) = TRUE;
}
*************************************************************************************
This will certainly solve the problem; however that code needs to be
unchanged.
However just inserting the END_DELIMITER is not enough as I don't know
how many members each array has unless I do some processing in the
header file itself (don't want to do that)
So my intention is to 'wrap' the original array with the
START_DELIMITER and the END_DELIMITER or just the START_DELIMITER
(since I can embed the END_DELIMITER as shown above).
Hence how could one do that?
I was trying to do:
#define START { (boolean *)START_DELIMITER, (char *)START_DELIMITER}
typedef new_type_ new_type;
struct new_type_ {
num_array start;
num_array data[]; /* The flexible array member */
}
However using the flexible array member gives the error:
'non-static initialization of a flexible array member'
Hence used :
struct new_type_ {
num_array start;
num_array data[0];
}
#define ARRAY(array_name) const new_type NEW ## array_name = {
START
#define ARRAY_INTERNAL(array_name) const num_array array_name[] = {
#define MEMBER(variable, enum, text) ,{&variable, text}
#define ARRAY_END ,{(boolean *)NULL, (char *)
NULL }\
,{(boolean *)END_DELIMITER,
(char *) END_DELIMITER};
};
so that when the .c code calls say the ARRAY(file1_array) I have the
START_DELIMITER prepended
to the array whose 'var' members will be dereferenced by that .c file.
This is the
original array array_name[]. array_name[] and START will provide me
with the wrapper
NEW_array_name which is transparent to the .c files including foo.h
However #defining original array inside the wrapper struct does not
seem to work as the above expansion is of the form........say file1.c
having 2 members:
******************************************************************************************
NEW_file1_array = {
{ (boolean *)START_DELIMITER, (char *)START_DELIMITER}
const num_array array_name[] = {
,{&file1_var1, "FILE1's variable 1"}
,{&file1_var2, "FILE1's variable 2"}
,{(boolean *)NULL, (char *) NULL }\
,{(boolean *)END_DELIMITER, (char *) END_DELIMITER};
};
while what I wanted was:
NEW_file1_array = {
{ (boolean *)START_DELIMITER, (char *)START_DELIMITER}
,{&file1_var1, "FILE1's variable 1"}
,{&file1_var2, "FILE1's variable 2"}
,{(boolean *)NULL, (char *) NULL }\
,{(boolean *)END_DELIMITER, (char *) END_DELIMITER}};
Also I suppose using a definition like :
struct new_type_ {
num_array start;
num_array *data;
}
would not help as then the ARRAY_INTERNAL would need to be defined
like:
#define ARRAY_INTERNAL(array_name) const num_array *array_name = {
and this would again be incompatible with what the .c files expect as
they operate on an array; also above expansion issues remain.
Can anyone suggest be what I am missing here or maybe suggest a
completely different solution to tackle such that the solution is
implementable in the header file itself and is transparent to the .c
files?
Thanks,
prix
.
- Follow-Ups:
- Re: #defining an array within another in C language
- From: Barry Schwarz
- Re: #defining an array within another in C language
- References:
- #defining an array within another in C language
- From: prix prad
- Re: #defining an array within another in C language
- From: Michael Mair
- #defining an array within another in C language
- Prev by Date: Re: OK folks, corrected
- Next by Date: Re: OK folks, corrected
- Previous by thread: Re: #defining an array within another in C language
- Next by thread: Re: #defining an array within another in C language
- Index(es):
Relevant Pages
|