Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

structure and constant memebers

348 views
Skip to first unread message

ravinde...@gmail.com

unread,
Oct 4, 2005, 5:42:41 AM10/4/05
to
hi all experts,


i have a structure with the constant memebers such as one given below:

typedef struct {
const int cbcode;
int cberror;
} xtsetplatestaterec;

now in my function i want to create a stack based object for the same:

void CreateObjectAndUseIt{
xtsetplatestaterec plate;
xtsetplatestaterec plate2 = {0 , 0};
}


now this function is giving the compilation errors while compiling on
vc++ 6.0 since the
cbcode memeber is a constant. the error is


error C2512: 'xtsetbleedvaluesrec' : no appropriate default constructor
available
error C2552: 'tmpsetplatestaterec' : non-aggregates cannot be
initialized with initializer list

can anybody plz explain me what could be done to create instances of
these objects on stack ???


thanks
rt

usr....@gmail.com

unread,
Oct 4, 2005, 5:56:11 AM10/4/05
to

ravinde...@gmail.com 写道:


why you use const there,maybe you can write like this :

typedef struct {
const int cbcode=0;
int cberror;
} xtsetplatestaterec;

Martin Ambuhl

unread,
Oct 4, 2005, 6:08:38 AM10/4/05
to
ravinde...@gmail.com wrote:
> hi all experts,
>
>
> i have a structure with the constant memebers such as one given below:
>
> typedef struct {
> const int cbcode;
> int cberror;
> } xtsetplatestaterec;
>
> now in my function i want to create a stack based object for the same:
>
> void CreateObjectAndUseIt{
> xtsetplatestaterec plate;
> xtsetplatestaterec plate2 = {0 , 0};
> }

The above has nothing to do with "stack based object"s. You are (quite
legally) using local variables. There is not a sign of your use of a
stack in sight.


> now this function is giving the compilation errors while compiling on
> vc++ 6.0 since the
> cbcode memeber is a constant. the error is
>
>
> error C2512: 'xtsetbleedvaluesrec' : no appropriate default constructor
> available

The above error message suggests you are using a C++ compiler.

> error C2552: 'tmpsetplatestaterec' : non-aggregates cannot be
> initialized with initializer list

Since we can't see tmpsetplatestaterec or what you are trying to
initialize, it is impossible to tell what you are doing wrong.

> can anybody plz explain me what could be done to create instances of
> these objects on stack ???

If the code you are using is giving a problem (and you are confusing
local variables with "objects on stack", which means nothing in C unless
you create and maintain a stack), then stop using a C++ compiler. C and
C++ are different languages; compiling C code as if it were C++ is
asking for trouble.

If you are actually trying to modify (rather than to initialize) a const
member of a structure, then don't. Either don't modify the member or
remove the 'const' which, after all, is a lie.

Martin Ambuhl

unread,
Oct 4, 2005, 6:13:51 AM10/4/05
to
usr....@gmail.com wrote:

> why you use const there,maybe you can write like this :
>
> typedef struct {
> const int cbcode=0;
> int cberror;
> } xtsetplatestaterec;

Why would you think such a foolish thing?


Richard Tobin

unread,
Oct 4, 2005, 10:59:14 AM10/4/05
to
In article <1128418961.7...@g49g2000cwa.googlegroups.com>,
<ravinde...@gmail.com> wrote:

>error C2512: 'xtsetbleedvaluesrec' : no appropriate default constructor
>available

This appears to be a C++ error message. Probably there is some way to
persuade your compiler to compile your program as C, perhaps by giving
the file a name with a suitable extension.

-- Richard

Keith Thompson

unread,
Oct 4, 2005, 2:54:38 PM10/4/05
to
Martin Ambuhl <mam...@earthlink.net> writes:
> ravinde...@gmail.com wrote:
>> hi all experts,
>> i have a structure with the constant memebers such as one given
>> below:
>> typedef struct {
>> const int cbcode;
>> int cberror;
>> } xtsetplatestaterec;
>> now in my function i want to create a stack based object for the
>> same:
>> void CreateObjectAndUseIt{
>> xtsetplatestaterec plate;
>> xtsetplatestaterec plate2 = {0 , 0};
>> }
>
> The above has nothing to do with "stack based object"s. You are
> (quite legally) using local variables. There is not a sign of your
> use of a stack in sight.

To be fair, local variables are allocated on the system stack in most
C implementations, just as malloc()-allocated objects are allocated on
the "heap". Even though the C standard doesn't use the word "stack"
or "heap" (I just checked), both terms can be convenient shorthands
for automatic and allocated storage duration, respectively.

It's worth pointing out that the standard doesn't use the term
"stack", and that not all C implementations *necessarily* use a system
stack in the commonly understood sense, but I don't see the need to
pretend we don't know what it means.

--
Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.

Martin Ambuhl

unread,
Oct 4, 2005, 3:48:18 PM10/4/05
to
Keith Thompson wrote:

> It's worth pointing out that the standard doesn't use the term
> "stack", and that not all C implementations *necessarily* use a system
> stack in the commonly understood sense, but I don't see the need to
> pretend we don't know what it means.

Since I *do* know what it means to maintain a stack in program, and I
*do* know how to store objects in such a stack, it would be wrong to
pretend that I know that the OP's use of "stack based objects" is a
mistake for "local variables." Since I more than once allowed for the
possibility that he suffered from such confusion, it would be dishonest
for someone to claim that I pretended not know what that -- of more than
one possibility -- might be what the OP poster meant. Do you purposely
misread my posts so you can play the mis-directed anti-pedant?

Keith Thompson

unread,
Oct 4, 2005, 4:11:49 PM10/4/05
to
Martin Ambuhl <mam...@earthlink.net> writes:
[snip]

> Do you purposely misread my posts so you can play the mis-directed
> anti-pedant?

No. If I've misread your post (which is entirely possible), it's
unintentional.

Keith Thompson

unread,
Oct 4, 2005, 4:42:04 PM10/4/05
to

I should expand on what I wrote a moment ago.

I assumed that the OP was using the term "stack-based objects" to
refer to objects allocated locally to a function. I still think
that's likely, but I made that assumption without carefully reading
the previous articles. I also assumed that it should have been
obvious to you, and that you were being overly pedantic, an incorrect
assumption for which I apologize.

Now that I've re-read the previous article, it's less clear to me just
what the OP is asking -- especially since he seems to be using C++
rather than C.

Going off on a bit of a tangent, I realize I've never used, and rarely
seen, structs with const members. It looks like this is allowed, but
you can't provide an initial value within the struct declaration. If
I understand this correctly, a const member can be initialized by the
initialization of the enclosing object, but can't be re-assigned later
without invoking undefined behavior -- and there doesn't seem to be
any way to initialize a const member of a malloc()ed structure without
invoking UB. This would seem to make const members not very useful.
Perhaps they're allowed because it was easier than adding a rule to
forbid them. Am I missing something?

Tim Rentsch

unread,
Oct 5, 2005, 10:31:56 AM10/5/05
to
Keith Thompson <ks...@mib.org> writes:

[snip]


> Going off on a bit of a tangent, I realize I've never used, and rarely
> seen, structs with const members. It looks like this is allowed, but
> you can't provide an initial value within the struct declaration. If
> I understand this correctly, a const member can be initialized by the
> initialization of the enclosing object, but can't be re-assigned later
> without invoking undefined behavior -- and there doesn't seem to be
> any way to initialize a const member of a malloc()ed structure without
> invoking UB. This would seem to make const members not very useful.
> Perhaps they're allowed because it was easier than adding a rule to
> forbid them. Am I missing something?

It is possible to construct a struct with const members in a
malloc'ed space, without UB. (Disclaimer: code has not been
compiled.)

... #includes as needed ...

struct thing {
int a;
const int b;
int c;
};

struct thing *
malloc_thing( int a, int b, int c ){
void *v;
struct thing *r;

r = v = malloc( sizeof *r );
if( !r ) exit( EXIT_FAILURE ); /* whatever... */

r->a = a;
*(int*) ((char*)v + offsetof(struct thing, b)) = b;
r->c = c;
return r;
}

Some people might squawk about the '(int*)' cast; they might want to
use

memcpy( (char*)v + offsetof(struct thing, b), &b, sizeof r->b );

instead.

Dave Thompson

unread,
Oct 16, 2005, 10:16:45 PM10/16/05
to
On 05 Oct 2005 07:31:56 -0700, Tim Rentsch <t...@alumnus.caltech.edu>
wrote:
<snip>

> It is possible to construct a struct with const members in a
> malloc'ed space, without UB. (Disclaimer: code has not been
> compiled.)
>
> ... #includes as needed ...
>
> struct thing {
> int a;
> const int b;
> int c;
> };
>
> struct thing *
> malloc_thing( int a, int b, int c ){
> void *v;
> struct thing *r;
>
> r = v = malloc( sizeof *r );
> if( !r ) exit( EXIT_FAILURE ); /* whatever... */
>
> r->a = a;
> *(int*) ((char*)v + offsetof(struct thing, b)) = b;
> r->c = c;
> return r;
> }
>
There's no need for v and offsetof; &r->b and (int*)&r->b are fine.

> Some people might squawk about the '(int*)' cast; they might want to
> use
>

No one should object to the cast as such, which is clearly a pointer
(value) to a correctly allocated and aligned object. What some might
object to is storing through that pointer, on the grounds the lvalue
being used is not suitable for the actual object, although I believe
in this case the "untypedness" of malloc-ed space saves us.

> memcpy( (char*)v + offsetof(struct thing, b), &b, sizeof r->b );
>
> instead.

Ditto, except (anynonconst*)&r->b is sufficient to pass to void* ,
and void* specifically might be considered good documentation.
Yes, this should squash the "wrong type for object" objection.

- David.Thompson1 at worldnet.att.net

Tim Rentsch

unread,
Oct 17, 2005, 10:36:13 PM10/17/05
to
Dave Thompson <david.t...@worldnet.att.net> writes:

> On 05 Oct 2005 07:31:56 -0700, Tim Rentsch <t...@alumnus.caltech.edu>
> wrote:
> <snip>
> > It is possible to construct a struct with const members in a
> > malloc'ed space, without UB. (Disclaimer: code has not been
> > compiled.)
> >
> > ... #includes as needed ...
> >
> > struct thing {
> > int a;
> > const int b;
> > int c;
> > };
> >
> > struct thing *
> > malloc_thing( int a, int b, int c ){
> > void *v;
> > struct thing *r;
> >
> > r = v = malloc( sizeof *r );
> > if( !r ) exit( EXIT_FAILURE ); /* whatever... */
> >
> > r->a = a;
> > *(int*) ((char*)v + offsetof(struct thing, b)) = b;
> > r->c = c;
> > return r;
> > }
> >
> There's no need for v and offsetof; &r->b and (int*)&r->b are fine.

Yes, good point. The truth is, I just forgot about these, because my
own development practices are so strongly predisposed to never
"casting away" const-ness.

Incidentally, why did you say "&r->b and (int*)&r->b"? Only
one expression (the second one) would be used.


> > Some people might squawk about the '(int*)' cast; they might want to
> > use
> >
> No one should object to the cast as such, which is clearly a pointer
> (value) to a correctly allocated and aligned object. What some might
> object to is storing through that pointer, on the grounds the lvalue
> being used is not suitable for the actual object, although I believe
> in this case the "untypedness" of malloc-ed space saves us.

I believe no reasonable person would object either to the '(int *)'
cast or to storing through the resultant pointer value. I put in
the alternative only to avoid an irrelevant tangential discussion
about the possible legalities or non-legalities. Not that such
nitpicking would ever occur in comp.lang.c.


> > memcpy( (char*)v + offsetof(struct thing, b), &b, sizeof r->b );
> >
> > instead.
>
> Ditto, except (anynonconst*)&r->b is sufficient to pass to void* ,
> and void* specifically might be considered good documentation.
> Yes, this should squash the "wrong type for object" objection.

Legally, you're right.

Stylistically, writing '(void*) &r->b' fails my "what reaction would I
expect during code review?" test. It works, but for reasons that are
deceptive or at best obscure. An alternative that might be better:

#define dangerous_memcpy(d,s,n) (memcpy( (void*)(d), (s), (n) ))

...

dangerous_memcpy( &r->b, &b, sizeof r->b );

Dave Thompson

unread,
Oct 24, 2005, 3:41:59 AM10/24/05
to
On 17 Oct 2005 19:36:13 -0700, Tim Rentsch <t...@alumnus.caltech.edu>
wrote:

> Dave Thompson <david.t...@worldnet.att.net> writes:
>
> > On 05 Oct 2005 07:31:56 -0700, Tim Rentsch <t...@alumnus.caltech.edu>

<snip>


> > > *(int*) ((char*)v + offsetof(struct thing, b)) = b;

<snip>


> > There's no need for v and offsetof; &r->b and (int*)&r->b are fine.
>
> Yes, good point. The truth is, I just forgot about these, because my
> own development practices are so strongly predisposed to never
> "casting away" const-ness.
>
> Incidentally, why did you say "&r->b and (int*)&r->b"? Only
> one expression (the second one) would be used.
>

Well, the latter includes the former so you're using both. <G> I have
a bias toward generalizing or noting related cases so as to avoid
implication that because I omitted something it isn't covered or isn't
the same, especially with my delay in reading and replying to news.
But I agree the latter is the one whose validity is (more) important.

>
> > > Some people might squawk about the '(int*)' cast; they might want to
> > > use
> > >
> > No one should object to the cast as such, which is clearly a pointer
> > (value) to a correctly allocated and aligned object. What some might
> > object to is storing through that pointer, on the grounds the lvalue
> > being used is not suitable for the actual object, although I believe
> > in this case the "untypedness" of malloc-ed space saves us.
>
> I believe no reasonable person would object either to the '(int *)'
> cast or to storing through the resultant pointer value. I put in
> the alternative only to avoid an irrelevant tangential discussion
> about the possible legalities or non-legalities. Not that such
> nitpicking would ever occur in comp.lang.c.
>

I think both objections are wrong, but distinguishable. The pointer
(value) cast is to my reading clearly allowed by direct positive
wording; I don't see _any_ counterargument. The store on its face
triggers the rules about storing into objects and particularly const
objects. In practice the fact that malloc space must be contiguous and
most of it writable means that an implementation couldn't enforce
constness of a subobject in it, and I _think_ the formal reflection of
this should be read to formally affirm it, but I can see that a
counterargument _could_ be made.

<snip: or memcpy>


> > Ditto, except (anynonconst*)&r->b is sufficient to pass to void* ,
> > and void* specifically might be considered good documentation.
> > Yes, this should squash the "wrong type for object" objection.
>
> Legally, you're right.
>
> Stylistically, writing '(void*) &r->b' fails my "what reaction would I
> expect during code review?" test. It works, but for reasons that are
> deceptive or at best obscure. An alternative that might be better:
>

I'm not sure about that. Semantically, I need to pass to memcpy a
pointer to the memory as nonconst but I don't otherwise care _here_
about the type. I think void* expresses that reasonably, and so does
char*. And so does int*, except it does care about the type. If there
were a shop or project style applicable to this I would conform, but I
don't see anything a priori bad about any of these.

> #define dangerous_memcpy(d,s,n) (memcpy( (void*)(d), (s), (n) ))
>

That's certainly an option, although I would probably go with a macro
only if this situation occurs more than a few times in the code --
which I hope it doesn't.

- David.Thompson1 at worldnet.att.net

Tim Rentsch

unread,
Oct 26, 2005, 6:11:30 AM10/26/05
to
Dave Thompson <david.t...@worldnet.att.net> writes:

Actually I think we might be closer on this than it might seem.
By my question, I don't mean that I think it would fail the code
review necessarily, only that it might be brought up; if I can
avoid spending code review capital on this line, there's more to
spend other places. So the code review test question can be seen
as overly stringent; but sometimes it's good to be more
stringent than is strictly necessary.

0 new messages