Re: #defining an array within another in C language



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












.



Relevant Pages

  • Re: Generic programming in C
    ... struct tag$ArrayInterface; ...     unsigned int Flags; ... specific type as the contents of the array. ...
    (comp.lang.c)
  • Re: C, strcat
    ... Actually a 1-length array of char. ... >members (all char strings) contained in a structure. ... struct member_data ...
    (alt.comp.lang.learn.c-cpp)
  • Re: structure toupperlower?
    ... >> I need to properly format the case of a struct. ... Are you trying to iterate over the members of a struct? ... you probably can if you first build an array each element ... The toupperand tolowerfunctions apply to a single character: ...
    (comp.lang.c)
  • Static array with #defined # of "extra" members
    ... I need to create a static array of structures with the following ... The remaining members of the array are initialized to "zero" ... static struct { ... struct foo builtin; ...
    (comp.lang.c)
  • Re: void* passed as funtion parameters?
    ... You could use a union type to store the array and store the array ... You could also attach the type to the struct itself, ... having members with the same name, you could use a macro in place of a ...
    (microsoft.public.vc.language)