Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > Problem with enums, const char* and structs

Reply
Thread Tools

Problem with enums, const char* and structs

 
 
Esash
Guest
Posts: n/a
 
      10-31-2012
Hello all,

I am trying to compile this code with gcc. I wrote this sample code to test this pattern so that I can incorporate the same pattern in my project. But I am not able to compile this code. Here is the code.

#include <stdio.h>

#define EK "1"
#define DO "2"

const char *num[] = { EK, DO };

typedef enum data_t_ {
ONE,
TWO,
} data_t;

typedef struct dat_t {
char *ptr;
int len;
} dat_t;

const dat_t *dat[] = {
{ num[ONE], sizeof(num[ONE]) },
{ num[TWO], sizeof(num[TWO]) },
};

int main()
{
int i;
for ( i = 0; i < 2; i++ ) {
printf("%s\t%d\n", dat[i]->ptr, dat[i]->len);
}
return 0;
}

I get the following errors :

index.c:19:2: warning: braces around scalar initializer [enabled by default]
index.c:19:2: warning: (near initialization for 'dat[0]') [enabled by default]
index.c:19:2: error: initializer element is not constant
index.c:19:2: error: (near initialization for 'dat[0]')
index.c:19:2: warning: excess elements in scalar initializer [enabled by default
]
index.c:19:2: warning: (near initialization for 'dat[0]') [enabled by default]
index.c:20:2: warning: braces around scalar initializer [enabled by default]
index.c:20:2: warning: (near initialization for 'dat[1]') [enabled by default]
index.c:20:2: error: initializer element is not constant
index.c:20:2: error: (near initialization for 'dat[1]')
index.c:20:2: warning: excess elements in scalar initializer [enabled by default
]
index.c:20:2: warning: (near initialization for 'dat[1]') [enabled by default]

Please help.

Thanks,
Esash
 
Reply With Quote
 
 
 
 
Ben Bacarisse
Guest
Posts: n/a
 
      10-31-2012
Esash <(E-Mail Removed)> writes:

> I am trying to compile this code with gcc. I wrote this sample code to
> test this pattern so that I can incorporate the same pattern in my
> project. But I am not able to compile this code. Here is the code.
>
> #include <stdio.h>
>
> #define EK "1"
> #define DO "2"
>
> const char *num[] = { EK, DO };
>
> typedef enum data_t_ {
> ONE,
> TWO,
> } data_t;
>
> typedef struct dat_t {
> char *ptr;
> int len;
> } dat_t;
>
> const dat_t *dat[] = {
> { num[ONE], sizeof(num[ONE]) },
> { num[TWO], sizeof(num[TWO]) },
> };


One problem (probably not related to what you are trying to do) is that
you've got a spurious * there. If you really do want an array of
pointer to dat_t you will another level of initialisation.

Another detail is that sizeof num[ONE] is the size of a pointer and
that's probably not what you really want.

But the "main" problem is that num[ONE] does not meet the definition of
an allowable address constant. Basically, you can't access an array
element to get an address constant. The rules are a little fiddly but
for reference I've appended the paragraph below.

It's not clear what the best course of action is because I am not sure
what the essential elements are. You've not made any of the data static
so I have to assume that everything is being accessed from everywhere
(though I know that's probably not what you intended).

You make be happy with:

const dat_t dat[] = {
{ EK, sizeof EK },
{ DO, sizeof DO },
};

From the recent C11 draft (it did not change from C99):

An address constant is a null pointer, a pointer to an lvalue
designating an object of static storage duration, or a pointer to a
function designator; it shall be created explicitly using the unary &
operator or an integer constant cast to pointer type, or implicitly by
the use of an expression of array or function type. The
array-subscript [] and member-access . and -> operators, the address
& and indirection * unary operators, and pointer casts may be used in
the creation of an address constant, but the value of an object shall
not be accessed by use of these operators.

<snip>
--
Ben.
 
Reply With Quote
 
 
 
 
Joe Pfeiffer
Guest
Posts: n/a
 
      10-31-2012
Esash <(E-Mail Removed)> writes:

> Hello all,
>
> I am trying to compile this code with gcc. I wrote this sample code to test this pattern so that I can incorporate the same pattern in my project. But I am not able to compile this code. Here is the code.
>
> #include <stdio.h>
>
> #define EK "1"
> #define DO "2"
>
> const char *num[] = { EK, DO };
>
> typedef enum data_t_ {
> ONE,
> TWO,
> } data_t;
>
> typedef struct dat_t {
> char *ptr;
> int len;
> } dat_t;
>
> const dat_t *dat[] = {
> { num[ONE], sizeof(num[ONE]) },
> { num[TWO], sizeof(num[TWO]) },
> };
>
> int main()
> {
> int i;
> for ( i = 0; i < 2; i++ ) {
> printf("%s\t%d\n", dat[i]->ptr, dat[i]->len);
> }
> return 0;
> }
>
> I get the following errors :
>
> index.c:19:2: warning: braces around scalar initializer [enabled by default]
> index.c:19:2: warning: (near initialization for 'dat[0]') [enabled by default]
> index.c:19:2: error: initializer element is not constant
> index.c:19:2: error: (near initialization for 'dat[0]')
> index.c:19:2: warning: excess elements in scalar initializer [enabled by default
> ]
> index.c:19:2: warning: (near initialization for 'dat[0]') [enabled by default]
> index.c:20:2: warning: braces around scalar initializer [enabled by default]
> index.c:20:2: warning: (near initialization for 'dat[1]') [enabled by default]
> index.c:20:2: error: initializer element is not constant
> index.c:20:2: error: (near initialization for 'dat[1]')
> index.c:20:2: warning: excess elements in scalar initializer [enabled by default
> ]
> index.c:20:2: warning: (near initialization for 'dat[1]') [enabled by default]


You've declared dat[] as an array of pointers to dat_t, but are
initializing the array as if it were an array of dat_t. Changing the
declaration and initialization to

const dat_t dat[] = {
{ num[ONE], sizeof(num[ONE]) },
{ num[TWO], sizeof(num[TWO]) },
};

will clear up that problem, but will expose other errors.

Something that I notice isn't an error per se, but is likely to cause
significant confusion, is in your data_t_ enumeration -- ONE will have
the value 0, and TWO will have the value 1. Also, in a program longer
than about 10 lines, having various types, enums, and variables with
names data_t_, data_t, dat_t, and dat will cause you to pull your hair
out trying to figure out your own code.
 
Reply With Quote
 
Esash
Guest
Posts: n/a
 
      10-31-2012
On Wednesday, October 31, 2012 7:28:40 PM UTC+5:30, Ben Bacarisse wrote:
> Esash <(E-Mail Removed)> writes:
>
>
>
> > I am trying to compile this code with gcc. I wrote this sample code to

>
> > test this pattern so that I can incorporate the same pattern in my

>
> > project. But I am not able to compile this code. Here is the code.

>
> >

>
> > #include <stdio.h>

>
> >

>
> > #define EK "1"

>
> > #define DO "2"

>
> >

>
> > const char *num[] = { EK, DO };

>
> >

>
> > typedef enum data_t_ {

>
> > ONE,

>
> > TWO,

>
> > } data_t;

>
> >

>
> > typedef struct dat_t {

>
> > char *ptr;

>
> > int len;

>
> > } dat_t;

>
> >

>
> > const dat_t *dat[] = {

>
> > { num[ONE], sizeof(num[ONE]) },

>
> > { num[TWO], sizeof(num[TWO]) },

>
> > };

>
>
>
> One problem (probably not related to what you are trying to do) is that
>
> you've got a spurious * there. If you really do want an array of
>
> pointer to dat_t you will another level of initialisation.
>
>
>
> Another detail is that sizeof num[ONE] is the size of a pointer and
>
> that's probably not what you really want.
>
>
>
> But the "main" problem is that num[ONE] does not meet the definition of
>
> an allowable address constant. Basically, you can't access an array
>
> element to get an address constant. The rules are a little fiddly but
>
> for reference I've appended the paragraph below.
>
>
>
> It's not clear what the best course of action is because I am not sure
>
> what the essential elements are. You've not made any of the data static
>
> so I have to assume that everything is being accessed from everywhere
>
> (though I know that's probably not what you intended).
>
>
>
> You make be happy with:
>
>
>
> const dat_t dat[] = {
>
> { EK, sizeof EK },
>
> { DO, sizeof DO },
>
> };
>
>
>
> From the recent C11 draft (it did not change from C99):
>
>
>
> An address constant is a null pointer, a pointer to an lvalue
>
> designating an object of static storage duration, or a pointer to a
>
> function designator; it shall be created explicitly using the unary &
>
> operator or an integer constant cast to pointer type, or implicitly by
>
> the use of an expression of array or function type. The
>
> array-subscript [] and member-access . and -> operators, the address
>
> & and indirection * unary operators, and pointer casts may be used in
>
> the creation of an address constant, but the value of an object shall
>
> not be accessed by use of these operators.
>
>
>
> <snip>
>
> --
>
> Ben.


Thanks a lot Ben. I got the point why I got those errors. But actually whatI need is the initialization of char* member here :

const dat_t *dat[] = {
{ num[ONE], sizeof(num[ONE]) },
{ num[TWO], sizeof(num[TWO]) },
};

As you said, this had to be :

const dat_t dat[] = {
{ num[ONE], strlen(num[ONE]) },
{ num[TWO], strlen(num[TWO]) },
};

But the problem lies in num[ONE] and num[TWO]. So, is there no way to initialize a structure member with a variable even if it is a const ? I understand that the compiler cannot be sure of such initializations since they might be subject to changes in the future. But any workaround ? Here is the modified code..

const char *num[] = { "this" , "that" };

typedef enum data_t_ {
ONE,
TWO,
} data_t;

typedef struct dat_t {
char *ptr;
int len;
} dat_t;

const dat_t dat[2] = {
{ num[ONE], strlen(num[ONE])},
{ num[ONE], strlen(num[TWO])},
};

int main()
{
int i;
for (i=0; i<2; i++) {
printf("%s\t%d\n", dat[i].ptr, dat[i].len);
}
return 0;
}
 
Reply With Quote
 
Esash
Guest
Posts: n/a
 
      10-31-2012
On Wednesday, October 31, 2012 10:57:57 PM UTC+5:30, Esash wrote:
> On Wednesday, October 31, 2012 7:28:40 PM UTC+5:30, Ben Bacarisse wrote:
>
> > Esash <(E-Mail Removed)> writes:

>
> >

>
> >

>
> >

>
> > > I am trying to compile this code with gcc. I wrote this sample code to

>
> >

>
> > > test this pattern so that I can incorporate the same pattern in my

>
> >

>
> > > project. But I am not able to compile this code. Here is the code.

>
> >

>
> > >

>
> >

>
> > > #include <stdio.h>

>
> >

>
> > >

>
> >

>
> > > #define EK "1"

>
> >

>
> > > #define DO "2"

>
> >

>
> > >

>
> >

>
> > > const char *num[] = { EK, DO };

>
> >

>
> > >

>
> >

>
> > > typedef enum data_t_ {

>
> >

>
> > > ONE,

>
> >

>
> > > TWO,

>
> >

>
> > > } data_t;

>
> >

>
> > >

>
> >

>
> > > typedef struct dat_t {

>
> >

>
> > > char *ptr;

>
> >

>
> > > int len;

>
> >

>
> > > } dat_t;

>
> >

>
> > >

>
> >

>
> > > const dat_t *dat[] = {

>
> >

>
> > > { num[ONE], sizeof(num[ONE]) },

>
> >

>
> > > { num[TWO], sizeof(num[TWO]) },

>
> >

>
> > > };

>
> >

>
> >

>
> >

>
> > One problem (probably not related to what you are trying to do) is that

>
> >

>
> > you've got a spurious * there. If you really do want an array of

>
> >

>
> > pointer to dat_t you will another level of initialisation.

>
> >

>
> >

>
> >

>
> > Another detail is that sizeof num[ONE] is the size of a pointer and

>
> >

>
> > that's probably not what you really want.

>
> >

>
> >

>
> >

>
> > But the "main" problem is that num[ONE] does not meet the definition of

>
> >

>
> > an allowable address constant. Basically, you can't access an array

>
> >

>
> > element to get an address constant. The rules are a little fiddly but

>
> >

>
> > for reference I've appended the paragraph below.

>
> >

>
> >

>
> >

>
> > It's not clear what the best course of action is because I am not sure

>
> >

>
> > what the essential elements are. You've not made any of the data static

>
> >

>
> > so I have to assume that everything is being accessed from everywhere

>
> >

>
> > (though I know that's probably not what you intended).

>
> >

>
> >

>
> >

>
> > You make be happy with:

>
> >

>
> >

>
> >

>
> > const dat_t dat[] = {

>
> >

>
> > { EK, sizeof EK },

>
> >

>
> > { DO, sizeof DO },

>
> >

>
> > };

>
> >

>
> >

>
> >

>
> > From the recent C11 draft (it did not change from C99):

>
> >

>
> >

>
> >

>
> > An address constant is a null pointer, a pointer to an lvalue

>
> >

>
> > designating an object of static storage duration, or a pointer to a

>
> >

>
> > function designator; it shall be created explicitly using the unary &

>
> >

>
> > operator or an integer constant cast to pointer type, or implicitly by

>
> >

>
> > the use of an expression of array or function type. The

>
> >

>
> > array-subscript [] and member-access . and -> operators, the address

>
> >

>
> > & and indirection * unary operators, and pointer casts may be used in

>
> >

>
> > the creation of an address constant, but the value of an object shall

>
> >

>
> > not be accessed by use of these operators.

>
> >

>
> >

>
> >

>
> > <snip>

>
> >

>
> > --

>
> >

>
> > Ben.

>
>
>
> Thanks a lot Ben. I got the point why I got those errors. But actually what I need is the initialization of char* member here :
>
>
>
> const dat_t *dat[] = {
>
> { num[ONE], sizeof(num[ONE]) },
>
> { num[TWO], sizeof(num[TWO]) },
>
> };
>
>
>
> As you said, this had to be :
>
>
>
> const dat_t dat[] = {
>
> { num[ONE], strlen(num[ONE]) },
>
> { num[TWO], strlen(num[TWO]) },
>
> };
>
>
>
> But the problem lies in num[ONE] and num[TWO]. So, is there no way to initialize a structure member with a variable even if it is a const ? I understand that the compiler cannot be sure of such initializations since they might be subject to changes in the future. But any workaround ? Here is the modified code..
>
>
>
> const char *num[] = { "this" , "that" };
>
>
>
> typedef enum data_t_ {
>
> ONE,
>
> TWO,
>
> } data_t;
>
>
>
> typedef struct dat_t {
>
> char *ptr;
>
> int len;
>
> } dat_t;
>
>
>
> const dat_t dat[2] = {
>
> { num[ONE], strlen(num[ONE])},
>
> { num[ONE], strlen(num[TWO])},
>
> };
>
>
>
> int main()
>
> {
>
> int i;
>
> for (i=0; i<2; i++) {
>
> printf("%s\t%d\n", dat[i].ptr, dat[i].len);
>
> }
>
> return 0;
>
> }


And the problems posed here with this revised code are the same as Joe's quoted in his reply.

index.c:54:2: error: initializer element is not constant
index.c:54:2: error: (near initialization for 'dat[0].ptr')
index.c:55:2: error: initializer element is not constant
index.c:55:2: error: (near initialization for 'dat[1].ptr')

So is there any workaround ? I got the point that replacing #defined valueswould solve the problem but in my case I cannot give the #defined values since the actual value in place of num[ONE] and num[TWO] are functions. These are big functions which cannot be written as a macro or inline functions.So they cannot be #defined.

Please advise.

Thanks,
Esash
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      10-31-2012
Esash <(E-Mail Removed)> writes:
> I am trying to compile this code with gcc. I wrote this sample code to
> test this pattern so that I can incorporate the same pattern in my
> project. But I am not able to compile this code. Here is the code.
>
> #include <stdio.h>
>
> #define EK "1"
> #define DO "2"
>
> const char *num[] = { EK, DO };
>
> typedef enum data_t_ {
> ONE,
> TWO,
> } data_t;
>
> typedef struct dat_t {
> char *ptr;
> int len;
> } dat_t;


None of the following is relevant to the problem you're asking about.

For an enum, struct, or union type, there's really no benefit in using
distinct identifiers for the tag and the typedef. You're using
different identifiers "data_t_" and "dat_t" for your enum type, and the
same identifier, "dat_t" for your struct type. Since tags are in a
separate namespace, appending "_" to get a unique name is neither
necessary nor helpful.

If you want to have a single identifier as the name of your type, you
can just omit the tag:

typedef enum { ONE, TWO } data_t;

Or you can omit the typedef:

enum data_t { ONE, TWO };

and refer to the type as "enum data_t". The same applies to struct
and union types, except that things get a little more complicated
for self-referential types (e.g., if a struct type contains a
pointer to itself).

And even for this example, using names like "dat_t" and "data_t" is
unnecessarily confusing.

[...]

> int main()


I suggest writing this as "int main(void)", since it's more explicit.

Another thing: Google Groups has completely messed up its Usenet
interface. In your followups in this thread, quoted text is
double-spaced, or even quadruple- or octuple-spaced. I don't know
what Google did to cause this problem, or why, but you can work
around it by copy-and-pasting your article into your favorite text
editor, deleting the extra lines, and then copy-and-pasting it back
into your browser before posting. It's also helpful to wrap your
lines to 72 columns or so. Or you could consider using a real Usenet
server (I use news.eternal-september.org) and client (I use Gnus,
which runs inside Emacs; there are a number of other free clients).

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Will write code for food.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
Barry Schwarz
Guest
Posts: n/a
 
      10-31-2012
On Wed, 31 Oct 2012 10:27:57 -0700 (PDT), Esash
<(E-Mail Removed)> wrote:

>
>Thanks a lot Ben. I got the point why I got those errors. But actually what I need is the initialization of char* member here :
>
>const dat_t *dat[] = {
> { num[ONE], sizeof(num[ONE]) },
> { num[TWO], sizeof(num[TWO]) },
>};
>
>As you said, this had to be :
>
>const dat_t dat[] = {
> { num[ONE], strlen(num[ONE]) },
> { num[TWO], strlen(num[TWO]) },
>};
>
>But the problem lies in num[ONE] and num[TWO]. So, is there no way to initialize a structure member with a variable even if it is a const ? I understand that the compiler cannot be sure of such initializations since they might be subject to changes in the future. But any workaround ? Here is the modified code..
>
>const char *num[] = { "this" , "that" };
>
>typedef enum data_t_ {
> ONE,
> TWO,
>} data_t;
>
>typedef struct dat_t {
> char *ptr;
> int len;
>} dat_t;
>
>const dat_t dat[2] = {
> { num[ONE], strlen(num[ONE])},
> { num[ONE], strlen(num[TWO])},
>};
>
>int main()
>{
> int i;
> for (i=0; i<2; i++) {
> printf("%s\t%d\n", dat[i].ptr, dat[i].len);
> }
> return 0;
>}


First, you need to realize that const and constant are two different
things. Even though the value of num[0] is const, it is not a compile
time constant. This is the same reason
const int x = 2;
static int y[x];
cannot be used.

Other than the fact that you are attempting to use num in the
initialization of dat, is there any reason it needs to be at file
scope or for that matter even exist? Could you use
const dat_t dat[2] = {
{ "this", sizeof "this" -1},
{ "that", sizeof "that" -1},
};

If you really need num at file scope with external linkage, consider
moving dat inside main. Once it no longer has static duration, you
have a lot more flexibility with the initialization. If you need dat
to be "global", add a global pointer to it that you assign in main.
Other source files will still be able to access dat and as long as you
don't call main recursively, it is effectively static. Something like

const char *num[] = { "this" , "that" };

typedef enum data_t_ {
ONE,
TWO,
} data_t;

typedef struct dat_t {
char *ptr;
int len;
} dat_t;

dat_t *dat_ptr; /* <================ */

int main()
{
const dat_t dat[2] = {
{ num[ONE], strlen(num[ONE])},
{ num[ONE], strlen(num[TWO])},
};

int i;
dat_ptr = dat; /* <================= */
for (i=0; i<2; i++) {
printf("%s\t%d\n", dat[i].ptr, dat[i].len);
}
return 0;
}

May I suggest that ONE being 0 and TWO being 1 is not the most
readable choice you could make.

--
Remove del for email
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      10-31-2012
On 10/31/2012 01:27 PM, Esash wrote:
> On Wednesday, October 31, 2012 7:28:40 PM UTC+5:30, Ben Bacarisse wrote:

....
>> You make be happy with:
>>
>>
>>
>> const dat_t dat[] = {
>>
>> { EK, sizeof EK },
>>
>> { DO, sizeof DO },
>>
>> };
>>
>>
>>
>> From the recent C11 draft (it did not change from C99):
>>
>>
>>
>> An address constant is a null pointer, a pointer to an lvalue
>> designating an object of static storage duration, or a pointer to a
>> function designator; it shall be created explicitly using the unary &
>> operator or an integer constant cast to pointer type, or implicitly by
>> the use of an expression of array or function type. The
>> array-subscript [] and member-access . and -> operators, the address
>> & and indirection * unary operators, and pointer casts may be used in
>> the creation of an address constant, but the value of an object shall
>> not be accessed by use of these operators.
>>
>>
>>
>> <snip>
>>
>> --
>>
>> Ben.

>
> Thanks a lot Ben. I got the point why I got those errors. But actually
> what I need is the initialization of char* member here :


Could you explain in more detail why you can't use Ben's suggestion?
The char* member does get initialized with his suggestion.

> const dat_t *dat[] = {
> { num[ONE], sizeof(num[ONE]) },
> { num[TWO], sizeof(num[TWO]) },
> };
>
> As you said, this had to be :
>
> const dat_t dat[] = {
> { num[ONE], strlen(num[ONE]) },
> { num[TWO], strlen(num[TWO]) },
> };
>


> But the problem lies in num[ONE] and num[TWO]. So, is there no way
> to initialize a structure member with a variable even if it is a const ?


Correct, at least for objects with static or thread storage duration.
Note that strlen() is also a problem here, for the same reason - it's
not a constant expression.

> I understand that the compiler cannot be sure of such initializations > since they might be subject to changes in the future. But any workaround?


The simplest solution is to give this array automatic storage duration,
by defining it inside a function. The restriction that the initializers
must be constant expressions applies only for objects with static or
thread storage duration.

If you need to refer to that array from multiple different functions,
pass around a pointer to the first element of the array, rather than
referring to the array directly. In general, I don't recommend using
global variables. However, if you must use one, if you replaced the
global array with a global pointer to the first element of an
automatically allocated array array, most uses of the pointer would use
the same exact syntax as for an array, so very little code would need to
be re-written.

If you need C90 compatibility, one work-around would be to remove the
'const' from the declaration of dat, explicitly set the length of the
array, and set the values explicitly, rather than using initialization
syntax:

dat[0].ptr = num[ONE];
dat[0].len = strlen(dat[0].ptr);
// etc.

You can still pass the array around using a pointer that retains the
'const', that you had to remove from 'dat' itself.

> Here is the modified code..
>
> const char *num[] = { "this" , "that" };
>
> typedef enum data_t_ {
> ONE,
> TWO,
> } data_t;
>
> typedef struct dat_t {
> char *ptr;


In most contexts, including this one, a string literal causes the
creation of an anonymous char array, and has a value which is a pointer
to the first element of that array. Code which attempts to modify any
element of that array has undefined behavior. That's why you were right
to declare 'num' using 'const'. However, since ptr will end up
containing copies of those same pointers, it should also be declared as

const char *ptr;

so that any code which attempts to modify those arrays through that
pointer will force the compiler to issue a diagnostic message.

> int len;
> } dat_t;


 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      10-31-2012
Esash <(E-Mail Removed)> writes:

> On Wednesday, October 31, 2012 10:57:57 PM UTC+5:30, Esash wrote:
>> On Wednesday, October 31, 2012 7:28:40 PM UTC+5:30, Ben Bacarisse wrote:
>>
>> > Esash <(E-Mail Removed)> writes:

>>
>> >

>>
>> >

>>
>> >

>>
>> > > I am trying to compile this code with gcc. I wrote this sample code to

>>
>> >


You might want to consider using another new reader; it's Google's
awful interface that's adding all the extra blank lines. If that's not
possible, please consider snipping some of your replies. You don't need
all of this text to make the point below.

<snip>
> And the problems posed here with this revised code are the same as Joe's quoted in his reply.
>
> index.c:54:2: error: initializer element is not constant
> index.c:54:2: error: (near initialization for 'dat[0].ptr')
> index.c:55:2: error: initializer element is not constant
> index.c:55:2: error: (near initialization for 'dat[1].ptr')
>
> So is there any workaround ?


Not without more information. What can and can not be changed? How
complex is the real situation?

> I got the point that replacing #defined
> values would solve the problem but in my case I cannot give the
> #defined values since the actual value in place of num[ONE] and
> num[TWO] are functions. These are big functions which cannot be
> written as a macro or inline functions. So they cannot be #defined.


I don't understand because you are being a little loose with your terms.
Do you really mean the values are function, or do you mean function
calls? When you say "in place of" surely you don't mean you posted code
that uses array elements when the "real" situation does not? maybe you
mean the values *in* num[ONE] and num[TWO] are the result of function
calls? If so, the situation is even worse than the example you
posted -- in C no functions can be called during the initialisation of a
file-scope object. But, as I said, maybe that's not what you mean.

But fear not: we all understand C so post the real code, not an
approximation to it, and you will get more realistic answers. In
addition, you need to say what can be sacrificed. If your code does not
work, something has to change so what can be changed and what can't be?

--
Ben.
 
Reply With Quote
 
James Kuyper
Guest
Posts: n/a
 
      11-01-2012
On 10/31/2012 01:32 PM, Esash wrote:
> On Wednesday, October 31, 2012 10:57:57 PM UTC+5:30, Esash wrote:

....
> And the problems posed here with this revised code are the same as
> Joe's quoted in his reply.
>
> index.c:54:2: error: initializer element is not constant


> index.c:54:2: error: (near initialization for 'dat[0].ptr')


> index.c:55:2: error: initializer element is not constant


> index.c:55:2: error: (near initialization for 'dat[1].ptr')
>
> So is there any workaround ? I got the point that replacing #defined
> values would solve the problem but in my case I cannot give the
> #defined values since the actual value in place of num[ONE] and
> num[TWO] are functions. These are big functions which cannot be
> written as a macro or inline functions. So they cannot be #defined.


If the expressions you're actually using where you wrote num[ONE] and
num[TWO] are actually the result of function calls, you certainly cannot
use them to initialize a statically allocated array. I've already told
you how you can deal with this, but I'll fill in the details below.

I'll assume that the pointers returned by that function point to
unmodifiable memory, just like num[ONE] and num[TWO]; if that's not the
case, the first and third uses of 'const' below can be removed.

I'll assume that you know the maximum number of elements in your array
(that's implied by your use of enumerations constants in the
initialization), and that you have a justified reason for needing global
access to it (which seems less likely to be true). I recommend against
using type names ending with _t, at least if your code might ever need
to be ported to a POSIX-compliant system. POSIX has reserved all such
names (other than those already reserved by C) for it's own use.

data.h:
enum {
ZERO,
ONE,
NUM_DATA
};

typedef struct {
const char *ptr;
int len;
} mydata;

extern const mydata *data_list;

main.c:
#include <string.h>
#include "data.h"
extern const char*get_string(int);
const mydata *data_list;

int main(void)
{
const mydata data_array[NUM_DATA] = {
{get_string(ZERO), strlen(get_string(ZERO)) },
{get_string(ONE), strlen(get_string(ONE)) },
};
data_list = data_array;
// The rest of your program
return 0;
}

Any module that needs access to the array should #include "data.h", and
access it through data_list.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
is const necessary in eg int compar(const void *, const void *) lovecreatesbeauty@gmail.c0m C Programming 26 11-10-2008 09:47 PM
const correctness - should C++ prefer const member over non-const? fungus C++ 13 10-31-2008 05:33 AM
const vector<A> vs vector<const A> vs const vector<const A> Javier C++ 2 09-04-2007 08:46 PM
Casting int'** to 'const int * const * const' dosn't work, why? Jonas.Holmsten@gmail.com C Programming 11 07-01-2007 06:16 PM
const structs in other structs Chris Hauxwell C Programming 6 04-27-2004 07:03 PM



Advertisments