#defining an array within another in C language

P

prix prad

Hi All,
I am trying to create two arrays at compile time using the
#define statement.
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.

The code is :
****************************************************************************************************
typedef struct new_type_ new_type;

struct new_type_ {
int var;
const num_array arr[0];
};

#define START 0xABCDEF12;

#define MIDDLE(arr) const new_type M ## arr = {\
START,\
MIDDLE_OLD(arr)\
};

#define MIDDLE_OLD(arr) num_array arr[] = {
#define ELEM(a,b,c) {a, b, c},
#define ELEM_END {-1,-1,-1}};

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;
}
*******************************************************************************************************
 
M

Michael Mair

prix said:
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
 
P

prix prad

prix said:
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

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.var; i++)
{
*(file1_array.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.var; i++)
{
*(file1_array.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
 
B

Barry Schwarz

snip ~200 lines of "old code" Please trim your posts when replying.
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 = {

The first problem seems to be that the parameter of the macro is not
used in its expansion. This macro will expand into a syntax error
since num_array is a type. I think you meant
#define ARRAY(array_name) const num_array array_name[] = {

Hence the oft repeated advice to cut and paste your code and not
retype it.
#define MEMBER(variable, enum, text) {&variable, text},

And again the enum parameter does not appear in the expansion.
#define ARRAY_END { (boolean *)NULL, (char *) NULL } };

With the exception of non-prototyped function arguments, there is
probably never a need to cast NULL and certainly not in the
initialization list of an array.
*************************************************************************************

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

So this expands to
const num_array = {
{&file1_var1, "FILE 1's first variable"},
{&file1_var2, "FILE 1's second variable"},
{&file1_varN, "FILE 1's Nth variable"},
{ (boolean *)NULL, (char *) NULL } };

Note the missing name of the array and the missing brackets in line 1.

Note also that member num of each struct element will be set to zero
(because it is not explicitly initialized while the rest of the
aggregate is). Since the array is const you cannot change it in
subsequent code.
*************************************************************************************

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}

You fixed the missing brackets but not the missing array name.

Though not guaranteed by the standard, on most machines a char* can
accept any converted integer value within your program's address
space. Are you sure the two values #define-d above do? If not, some
systems will terminate your program at this point (merely calculating
a bad address is sufficient to signal a fatal error).

You have not shown us the declaration of boolean on your system. If
it is not char, it may have some alignment requirements. Do the two
addresses #define-d above meet those requirements. If not, then
attempting to convert an improperly aligned address to an aligned
pointer type invokes undefined behavior (or maybe the behavior is not
undefined until you store in the pointer object but this
initialization does both anyway).
#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.var; i++)


Defining your variables inside the for statement is not legal in C89
and I don't think it is in C99 either.
{
*(file1_array.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.var; i++)
{
*(file1_array.var) = TRUE;
}
*************************************************************************************

This will certainly solve the problem; however that code needs to be
unchanged.


Instead of using the arbitrary address values, you might try something
like:

Define two global variables (variables with file scope), one
boolean and the second either char or char[] (depending on how the
object pointed to is initialized).

Delete the two _DELIMETER macros and change ARRAY to
#define ARRAY(array_name) const num_array array_name[] =\
{ {&global_bool,&global_char}

snip a lot more code dealing with declarations and definitions.

At this point it dawned on me that I am re-engineering a solution with
no concept of the real problem you are trying to solve.

The arrays are obviously not dynamically allocated. If they are being
used in the function they are being defined in, then the normal
approach of
num_elements = array / *array;
will work. If they are being passed to your function, then you know
the starting address and can find the last element by looking for an
element with two NULL pointer values.

So instead of another 400 lines of code, try describing the problem
rather than the solution.


Remove del for email
 
P

prix prad

Hi Barry,
You have a main foo.h file having the #define statements.
Then there are many .h/.c file pairs. The .h files say file1.h
populates the array of structs using say
#define ARRAY(file1)
#define MEMBER(var1,txt1,num1)
#define MEMBER(var2,txt2,num2)
#define ARRAY_END

The corresponding .c file say file1.c does processing on the arrays;
say iterating through the
array and setting the 'var' member of each struct to TRUE.

My problem is that I can't modify the .h/.c files. I only want to
modify foo.h.

Member num of each struct is set to zero and thats fine. Also there
are no alignnment issues. I can't get the size in the foo.h file since
I don't know how many members each array defined will have since that
is done in fileN.h. Thus I don't know the starting address in foo.h ;
in fact the .c files use the exact same approach - they know the
starting address and then they continue processing until they hit an
element with 2 NULL pointers.


I know the END_DELIMITER since I can append it in a transparent manner
to the array. However I need to know either the START_DELIMITER or the
number of elements per array.

I was thinking of doing processing in the foo.h file itself to
calculate the number of elements by using the currently unused 'num'
field. However doing something like

define MEMBER(variable, enum, text) {&variable, text, i++},

will flag an error of 'Initializer element in not constant'

So I need to add the START_DELIMITER with it being oblivious to the
fileN[.h/.c] such that prepending the START_DELIMITER to the original
array in transparent the fileN[.h/.c] files.

So now if the new array is {START_DELIMITER, original_array} with the
START_DELIMITER being the 1st row of the new array then
when the .c file does

*(array_name1[0].var) = TRUE; it should not be doing

*(0xABCDEF12) = TRUE wherein

START_DELIMITER = {(boolean *)0xABCDEF12, (char *)0xABCDEF12,
(ulong)0xABCDEF12 }

So in a nutshell the problem definition is adding a START_DELIMITER(it
can be an int or same as num_array as above) such that this change is
oblivious to existing unchangeable
fileN[.h/.c] code.

Hence I was thinking of a wrapper struct which will include the
START_DELIMITER and the original array.

Hope this explains the problem better.

Thanks,
prix
 
B

Barry Schwarz

Hi Barry,
You have a main foo.h file having the #define statements.
Then there are many .h/.c file pairs. The .h files say file1.h
populates the array of structs using say
#define ARRAY(file1)
#define MEMBER(var1,txt1,num1)
#define MEMBER(var2,txt2,num2)
#define ARRAY_END

While file1.h can have define these macros, it should not populate any
arrays. Objects should never be defined in headers.
The corresponding .c file say file1.c does processing on the arrays;
say iterating through the
array and setting the 'var' member of each struct to TRUE.

Since the struct is const, you cannot set the var member. If I
remember you sample code, you are actually setting the object the var
member points to which is allowed.
My problem is that I can't modify the .h/.c files. I only want to
modify foo.h.

Believe it or not but even in supposedly intelligently run businesses
it is fairly common to hear "fix the problem but don't change
anything".

You haven't told us why you want to modify anything. What aspect of
the current code's performance do you think changing/adding foo.h will
improve/correct.

If you cannot modify either file1.h or file1.c, how or where is foo.h
ever going to be #include-d.
Member num of each struct is set to zero and thats fine. Also there
are no alignnment issues. I can't get the size in the foo.h file since
I don't know how many members each array defined will have since that
is done in fileN.h. Thus I don't know the starting address in foo.h ;

Nothing in foo.h should have a starting address.
in fact the .c files use the exact same approach - they know the
starting address and then they continue processing until they hit an
element with 2 NULL pointers.


I know the END_DELIMITER since I can append it in a transparent manner
to the array. However I need to know either the START_DELIMITER or the
number of elements per array.

You are not describing what you want to do. You are stating
assumptions about how you may chose to do it.
I was thinking of doing processing in the foo.h file itself to
calculate the number of elements by using the currently unused 'num'
field. However doing something like

There should not be any executable statements in foo.h
define MEMBER(variable, enum, text) {&variable, text, i++},

will flag an error of 'Initializer element in not constant'

Unless variable has static duration, &variable is not constant either
so your compiler is treating the two expressions differently.
So I need to add the START_DELIMITER with it being oblivious to the
fileN[.h/.c] such that prepending the START_DELIMITER to the original
array in transparent the fileN[.h/.c] files.

This is still a supposition about the solution. You need to define
the requirement before even considering possible solutions.
So now if the new array is {START_DELIMITER, original_array} with the
START_DELIMITER being the 1st row of the new array then
when the .c file does

*(array_name1[0].var) = TRUE; it should not be doing

*(0xABCDEF12) = TRUE wherein

I already told you how to avoid this.
START_DELIMITER = {(boolean *)0xABCDEF12, (char *)0xABCDEF12,
(ulong)0xABCDEF12 }

So in a nutshell the problem definition is adding a START_DELIMITER(it
can be an int or same as num_array as above) such that this change is
oblivious to existing unchangeable
fileN[.h/.c] code.

Hence I was thinking of a wrapper struct which will include the
START_DELIMITER and the original array.

Hope this explains the problem better.

Sorry but it doesn't. We still have no idea what you want to do. All
you have told us the problems you face trying to do a something we
only partially understand a particular way.


Remove del for email
 
P

prix prad

Hi Barry,

While file1.h can have define these macros, it should not populate any
arrays.  Objects should never be defined in headers.

My mistake in saying the #defines are in file.h; they are in foo.h.
Currently this is happenning:

There is an existing file foo.h
which has all the #defines of the ARRAY, MEMBER and ARRAY_END as
below:


#define ARRAY(array_name) const num_array array_name[] = {
#define MEMBER(var,txt,num) {&var, txt},
#define ARRAY_END {(boolean *)NULL, (char *)NULL} };

num_array is

struct num_array {
boolean *var;
char *txt;
int num;
};

Then there are multiple .h/.c file pairs. The .h file is including the
foo.h file and
creates the array say file1_array of say 2 members.

ARRAY(file1_array)
MEMBER(file1_var1,file1_txt1,file1_num1)
MEMBER(file1_var2,file1_txt2,file1_num2)
ARRAY_END

so that array gets created for file1.h


Then in file1.c we do something like

*(file1_array.var) = 1; for all the array members

Since the struct is const, you cannot set the var member.  If I
remember you sample code, you are actually setting the object the var
member points to which is allowed.

Oops ...correct....I am setting the object the var member points by
dereferencing the
var member first
Believe it or not but even in supposedly intelligently run businesses
it is fairly common to hear "fix the problem but don't change
anything".

You haven't told us why you want to modify anything.  What aspect of
the current code's performance do you think changing/adding foo.h will
improve/correct.

If you cannot modify either file1.h or file1.c, how or where is foo.h
ever going to be #include-d.
Forgot to mention I suppose; all fileN.h files include foo.h currently
in the above
format where we have #define of ARRAY, MEMBER and ARRAY_DONE.

So the issue is changing foo.h so that I know the length/number of
elements of the array
by adding a START_DELIMITER and END_DELIMITER. Adding these two
delimiters will be helpful
when I execute the program so that I can look for them in the
executable and store the location of all the MEMBERS of all the arrays
in a continuous location. Currently the arrays are there but in
a non-contiguous location and I don't know how big each array is ;
since I don't know the number of elements.

Nothing in foo.h should have a starting address.

Yes true; what I was alluding to is that I don't know the starting
address of each array in the executable since they are in non-
contiguous locations.
You are not describing what you want to do.  You are stating
assumptions about how you may chose to do it.




There should not be any executable statements in foo.h

Yes true, thats add to the difficulty of solving this. Hence was
thinking about preprocessor macros to arrive to a solution.
define MEMBER(variable, enum, text) {&variable, text, i++},
will flag an error of 'Initializer element in not constant'

Unless variable has static duration, &variable is not constant either
so your compiler is treating the two expressions differently.


So I need to add the START_DELIMITER with it being oblivious to the
fileN[.h/.c] such that prepending the START_DELIMITER to the original
array in transparent the fileN[.h/.c] files.

This is still a supposition about the solution.  You need to define
the requirement before even considering possible solutions.


So now if the new array is {START_DELIMITER, original_array} with the
START_DELIMITER being the 1st row of the new array then
when the .c file does
*(array_name1[0].var) = TRUE; it should not be doing
*(0xABCDEF12) = TRUE wherein

I already told you how to avoid this.

START_DELIMITER = {(boolean *)0xABCDEF12, (char *)0xABCDEF12,
(ulong)0xABCDEF12 }
So in a nutshell the problem definition is adding a START_DELIMITER(it
can be an int or same as num_array as above) such that this change is
oblivious to existing unchangeable
fileN[.h/.c] code.
Hence I was thinking of a wrapper struct which will include the
START_DELIMITER and the original array.
Hope this explains the problem better.

Sorry but it doesn't.  We still have no idea what you want to do.  All
you have told us the problems you face trying to do a something we
only partially understand a particular way.

Remove del for email


I want to find out the bounds of each of the arrays in the fileN.h
files so that I can group all the MEMBERS of all the array in one
contiguous location instead of having them in disparate memory
locations. I want to add any extra logic for doing this in foo.h file
as against in the fileN[.h/.c]
files.

So the problem is that I don't know where these arrays are stored in
memory during compilation, and i need to know their location at
runtime so that I can group them together.

Thanks,
prix
 
B

Barry Schwarz

Hi Barry,
I want to find out the bounds of each of the arrays in the fileN.h
files so that I can group all the MEMBERS of all the array in one
contiguous location instead of having them in disparate memory
locations. I want to add any extra logic for doing this in foo.h file
as against in the fileN[.h/.c]
files.

Again, you are giving us a potential solution, not a description of
what is required.
So the problem is that I don't know where these arrays are stored in
memory during compilation, and i need to know their location at
runtime so that I can group them together.

You cannot move an array once it has been defined. If they are in
different functions, they are going to stay there. Even if they are
in the same function they need not be contiguous.

Why do you need to know the location of any array? Do you have a new
function which is going to do something to the values in the array
(actually values pointed to by members of elements of the array since
the array itself is const)? If so, how is this function being called?
If not, how are you going to do anything with the data?


Remove del for email
 
P

prix prad

Hi Barry,
Again, you are giving us a potential solution, not a description of
what is required.  



You cannot move an array once it has been defined.  If they are in
different functions, they are going to stay there.  Even if they are
in the same function they need not be contiguous.

I should have been more specific. I want to group only specific
members of the
array......they being the address of the 'var' member and the 'txt'
string.
I will create a new array of structures using these 2 members with the
structure containing
2 members which are the first 2 members of struct num_array. So the
intention is to create a
new array of structs and this array will have all the MEMBERS of all
the ARRAYs defined
by all the fileN.h files; but this time in a contiguous order.
Why do you need to know the location of any array?  Do you have a new
function which is going to do something to the values in the array
(actually values pointed to by members of elements of the array since
the array itself is const)?  If so, how is this function being called?
If not, how are you going to do anything with the data?

Yes I intend to write a new function which will set/unset the boolean
value. I intend to give this
function the 'txt' string as a parameter and it will go and set the
corresponding boolean value by looking
up the new array that I will create using the address of var(the
boolean) and the txt string as pairs.

So here is the sequence of steps in short:
(1) I compile the program with modifications such that now every
fileN.h created array has the START and END
DELIMITERS in addition to the existing ARRAY, 'n' number of
MEMBERS and ARRAY_END.
(2) Now using (1) I add functionality to create a new array of structs
with the each structure containing the boolean address and
the text string.
(3) While running the program I manually enter statements to set/unset
some of the boolean vars (0 to 1).
Then I need to store info about which vars I have set to true and
store the corresponding string in some file 'X'.
(4) Then next time I run the program these vars will be set for me by
the program by reading the 'text' strings
from file 'X' and using the address info from the newly created
array of structures.

I am strongly believing now that I need to change the .h/.c files to
make this work and changing just foo.h isn't enough.

Regards,
prix
 
B

Barry Schwarz

snip
Yes I intend to write a new function which will set/unset the boolean
value. I intend to give this

How will this function be called if you don't change at least one of
the .c files?
function the 'txt' string as a parameter and it will go and set the
corresponding boolean value by looking
up the new array that I will create using the address of var(the
boolean) and the txt string as pairs.

As long as you are passing info to the function why not pass the
address of the array also?
So here is the sequence of steps in short:
snip

I am strongly believing now that I need to change the .h/.c files to
make this work and changing just foo.h isn't enough.

Good luck.


Remove del for email
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,756
Messages
2,569,535
Members
45,008
Latest member
obedient dusk

Latest Threads

Top