structure and constant memebers

R

ravinderthakur

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
 
U

usr.root

(e-mail address removed) 写é“:
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


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

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

Martin Ambuhl

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.
 
M

Martin Ambuhl

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?
 
R

Richard Tobin

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
 
K

Keith Thompson

Martin Ambuhl said:
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.
 
M

Martin Ambuhl

Keith said:
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?
 
K

Keith Thompson

Martin Ambuhl said:
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.
 
K

Keith Thompson

Martin Ambuhl said:
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?

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?
 
T

Tim Rentsch

[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.
 
D

Dave Thompson

On 05 Oct 2005 07:31:56 -0700, Tim Rentsch <[email protected]>
wrote:
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
 
T

Tim Rentsch

Dave Thompson said:
On 05 Oct 2005 07:31:56 -0700, Tim Rentsch <[email protected]>
wrote:

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.

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.

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 );
 
D

Dave Thompson

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.
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.

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
 
T

Tim Rentsch

Dave Thompson said:
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.

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.
 

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

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,156
Latest member
KetoBurnSupplement
Top