/* test.c */
#include <stdlib.h>
void f() {
struct X { const int x; };
struct X* myx = malloc(sizeof(struct X));
myx->x = 42;
}
/* end of test.c */
$ gcc-4.3 -c test.c
test.c: In function 'f':
test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do
I initialize it? I looked in the C FAQ but did not see anything that
addressed this specifically.
Or perhaps I'm going about this the wrong way?
Adam 16 18489
On Sun, 14 Sep 2008 10:33:13 -0700, aburry wrote:
/* test.c */
#include <stdlib.h>
void f() {
struct X { const int x; };
struct X* myx = malloc(sizeof(struct X));
myx->x = 42;
}
/* end of test.c */
$ gcc-4.3 -c test.c
test.c: In function 'f':
test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do I
initialize it? I looked in the C FAQ but did not see anything that
addressed this specifically.
The only way to initialise a dynamically allocated structure is by using
calloc, and if you do that, you can't choose an initialiser value.
Or perhaps I'm going about this the wrong way?
The problem is that there is not really a sane right way. You may be able
to use this:
struct X { const int x; };
struct X *myx = malloc(sizeof *myx);
struct X myx_value = { 42 };
memcpy(myx, &myx_value, sizeof *myx);
but it's ugly.
On Sep 14, 12:53 pm, Harald van D©¦k <tr*****@gmail.comwrote:
The problem is that there is not really a sane right way. You may be able
to use this:
struct X { const int x; };
struct X *myx = malloc(sizeof *myx);
struct X myx_value = { 42 };
memcpy(myx, &myx_value, sizeof *myx);
but it's ugly.
Isn't it possible that the compiler has chosen to store the 'x' member
in some kind of read-only memory, making the call to memcpy() unsafe?
Sebastian
On Sep 14, 10:33*pm, abu...@ieee.org wrote:
/* test.c */
#include <stdlib.h>
void f() {
struct X { const int x; };
struct X* myx = malloc(sizeof(struct X));
myx->x = 42;}
/* end of test.c */
$ gcc-4.3 -c test.c
test.c: In function 'f':
test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do
I initialize it? I looked in the C FAQ but did not see anything that
addressed this specifically.
Or perhaps I'm going about this the wrong way?
Adam
please go through following discussions http://groups.google.com/group/comp....e80f24e3b00a40
--
vIpIn
On Sun, 14 Sep 2008 11:02:06 -0700, s0suk3 wrote:
On Sep 14, 12:53 pm, Harald van Dijk <tr*****@gmail.comwrote:
>The problem is that there is not really a sane right way. You may be able to use this:
struct X { const int x; }; struct X *myx = malloc(sizeof *myx); struct X myx_value = { 42 }; memcpy(myx, &myx_value, sizeof *myx);
but it's ugly.
Isn't it possible that the compiler has chosen to store the 'x' member
in some kind of read-only memory, making the call to memcpy() unsafe?
In general, yes, but here, no, that's not possible, since it's a member of
a dynamically allocated structure, and all bytes that malloc's result
points to must be writeable.
On Sun, 14 Sep 2008 10:33:13 -0700 (PDT), ab****@ieee.org wrote:
>/* test.c */ #include <stdlib.h>
void f() { struct X { const int x; }; struct X* myx = malloc(sizeof(struct X)); myx->x = 42; } /* end of test.c */
$ gcc-4.3 -c test.c test.c: In function 'f': test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do I initialize it? I looked in the C FAQ but did not see anything that addressed this specifically.
Or perhaps I'm going about this the wrong way?
Since the language doesn't have a "write once" concept (other than
initialization as part of the definition), you have to fake it. One
approach that might do what you want is
struct X {int x;};
const struct X *myptr;
struct X *ptr_used_only_to_initialize_x = malloc(sizeof *myptr);
/* obvious error check goes here */
ptr_used_only_to_initialize_x->x = 42;
myptr = ptr_used_only_to_initialize_x;
and never use ptr_used_only_to_initialize_x again. You might even add
something like
#define ptr_used_only_to_initialize_x text to cause compile error
after the above code just to catch the any such use.
Naturally this will work only if all the members of the struct are to
be treated as const.
--
Remove del for email
On Sep 14, 8:33 pm, abu...@ieee.org wrote:
/* test.c */
#include <stdlib.h>
void f() {
struct X { const int x; };
struct X* myx = malloc(sizeof(struct X));
myx->x = 42;}
/* end of test.c */
$ gcc-4.3 -c test.c
test.c: In function 'f':
test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do
I initialize it? I looked in the C FAQ but did not see anything that
addressed this specifically.
Or perhaps I'm going about this the wrong way?
Well, why would you want a const member in a struct?
Here's a way to do this:
#include <stdlib.h>
#include <stddef.h>
struct x { const int i; }
struct x *p;
void *q;
p = q = malloc(sizeof *x)
if(p)
*(int *)((unsigned char *)q + offsetof(struct x, i)) = yourvalue;
free(p);
another more simple one:
*(int *)&p->i = yourvalue;
Thank you for the answers. I did search the group, but did not find
helpful thread vipin found. Here's a solved test case:
/* test.c */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char* argv[] ) {
struct X { const int x; };
struct X* myx = malloc(sizeof *myx);
/* myx->x = 42; */ /* error: assignment of read-only member 'x'
*/
/* solution 1: */
#if 0
/* const initialization */
struct X myx_value = { 42 };
/* copy the const object */
memcpy(myx, &myx_value, sizeof *myx);
#endif
/* solution 2: */
#if 1
/* const cast */
*(int*)(&(myx->x)) = 42;
#endif
printf("%d\n", myx->x);
return 0;
}
/* test.c */
The const cast was what I wanted, but my attempts at coming up with an
lvalue failed.
Adam
On Sep 14, 9:56 pm, abu...@ieee.org wrote:
Thank you for the answers. I did search the group, but did not find
helpful thread vipin found. Here's a solved test case:
/* test.c */
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(int argc, char* argv[] ) {
struct X { const int x; };
struct X* myx = malloc(sizeof *myx);
/* myx->x = 42; */ /* error: assignment of read-only member 'x'
*/
/* solution 1: */
#if 0
/* const initialization */
struct X myx_value = { 42 };
/* copy the const object */
memcpy(myx, &myx_value, sizeof *myx);
#endif
Well, if you don't like the temporary variable, you can do this in
C99:
memcpy(myx, (struct X []){ /* .i = */ 42 }, sizeof *myx);
Or a C89/C99 solution
{ struct X temp_ = { 42 }; memcpy(...); }
(*with* the braces) vi******@gmail.com writes:
On Sep 14, 8:33 pm, abu...@ieee.org wrote:
>/* test.c */ #include <stdlib.h>
void f() { struct X { const int x; }; struct X* myx = malloc(sizeof(struct X)); myx->x = 42;}
/* end of test.c */
$ gcc-4.3 -c test.c test.c: In function 'f': test.c:7: error: assignment of read-only member 'x'
I would like x to be immutable once the struct is initialized. How do I initialize it? I looked in the C FAQ but did not see anything that addressed this specifically.
Or perhaps I'm going about this the wrong way?
Well, why would you want a const member in a struct?
Why is that your concern? Maybe each struct member has a different const
member value? Did you think about that? His reasons are non of your
concern.
Here's a way to do this:
#include <stdlib.h>
#include <stddef.h>
struct x { const int i; }
struct x *p;
void *q;
p = q = malloc(sizeof *x)
if(p)
*(int *)((unsigned char *)q + offsetof(struct x, i)) = yourvalue;
free(p);
another more simple one:
*(int *)&p->i = yourvalue;
Did you not see the other posts pointing to the solution that you then
reposted? They were posted quite a while before your solution ... http://groups.google.com/group/comp....e80f24e3b00a40
Interestingly enough you're spot on ....
The thread solution:
*(int*) ((char*)v + offsetof(struct thing, b)) = b;
Your solution:
*(int *)((unsigned char *)q + offsetof(struct x, i)) = yourvalue;
The reason I mention it is that I think its a travesty to keep
reinventing the wheel and posting the same thing when a good, well
explained solution is already out there.
On Sep 14, 5:01*pm, Richard<rgr...@gmail.comwrote:
vipps...@gmail.com writes:
On Sep 14, 8:33 pm, abu...@ieee.org wrote:
I would like x to be immutable once the struct is
initialized. How do I initialize it?
Well, why would you want a const member in a struct?
Why is that your concern? Maybe each struct member has a
different const member value? Did you think about that? His
reasons are non of your concern.
Unless he wanted to learn under what conditions someone would do a
thing like that? Did you think about that?
I actually do this kind of thing a lot. In C++ I can write:
class X {
public:
X(int val) : x(val) {}
private:
const int x;
};
And the compiler takes care of casting away the const during the
initialization. Similar to the following C example given elsewhere in
the thread:
struct X { const int x; } x = { 42 };
I like const members in situations where I want the object to be
parameterized at run-time, but where I do not expect/want the value to
change. I find that const members reduce the amount of thinking I have
to do. I can tell right away the member is not a variable I have to
really consider because it is a constant. Also, const allows me to say
what I mean; it is like extra documentation, only better.
In the particular case I was looking at today, I had an object that is
potentially shared. I want every object that has a reference to it to
know that their semantics are not going to change under their feet
(because the shared objects are const).
Hope that helps.
Did you not see the other posts pointing to the solution
that you then reposted? They were posted quite a while
before your solution ...
The reason I mention it is that I think its a travesty to
keep reinventing the wheel and posting the same thing when
a good, well explained solution is already out there.
Maybe his news server had not synced all the other responses yet. Did
you think about that?
The reason I mention it is that I think it's a travesty to chastise
someone for offering a helpful correct solution.
Adam ab****@ieee.org writes:
On Sep 14, 5:01Â*pm, Richard<rgr...@gmail.comwrote:
>vipps...@gmail.com writes:
On Sep 14, 8:33 pm, abu...@ieee.org wrote:
I would like x to be immutable once the struct is
initialized. How do I initialize it?
Well, why would you want a const member in a struct?
Why is that your concern? Maybe each struct member has a different const member value? Did you think about that? His reasons are non of your concern.
Unless he wanted to learn under what conditions someone would do a
thing like that? Did you think about that?
Yes. I gave an example.
However the reason is immaterial IMO in this case.
>
I actually do this kind of thing a lot. In C++ I can write:
class X {
public:
X(int val) : x(val) {}
private:
const int x;
};
And the compiler takes care of casting away the const during the
initialization. Similar to the following C example given elsewhere in
the thread:
struct X { const int x; } x = { 42 };
I like const members in situations where I want the object to be
parameterized at run-time, but where I do not expect/want the value to
change.
Yes. As I said. I agree. Hence I said:
,----
| Maybe each struct member has a
| different const member value?
`----
I find that const members reduce the amount of thinking I have
to do. I can tell right away the member is not a variable I have to
really consider because it is a constant. Also, const allows me to say
what I mean; it is like extra documentation, only better.
In the particular case I was looking at today, I had an object that is
potentially shared. I want every object that has a reference to it to
know that their semantics are not going to change under their feet
(because the shared objects are const).
Hope that helps.
>Did you not see the other posts pointing to the solution that you then reposted? They were posted quite a while before your solution ...
The reason I mention it is that I think its a travesty to keep reinventing the wheel and posting the same thing when a good, well explained solution is already out there.
Maybe his news server had not synced all the other responses yet. Did
you think about that?
Maybe. It seems certain c.l.c members have really slow news servers. Strange.
>
The reason I mention it is that I think it's a travesty to chastise
someone for offering a helpful correct solution.
Adam
I did not chastise him.
I stand by my statement that repeated answers are not a good
thing. Frankly I have my suspicions but there you go. c.l.c has caused
me to be suspicious of peoples motives. Not a good thing I know and
possibly I need to learn to be more forgiving. ab****@ieee.org writes:
void f() {
struct X { const int x; };
struct X* myx = malloc(sizeof(struct X));
myx->x = 42;
}
[...]
I would like x to be immutable once the struct is initialized. How do
I initialize it? I looked in the C FAQ but did not see anything that
addressed this specifically.
Are you sure that you really want to make the member immutable?
If it is good enough to make the whole structure immutable, you
can do something like this:
struct X { int x; };
const struct X *make_X(int value)
{
struct X *myx = malloc(sizeof *myx);
myx->x = value;
return myx;
}
--
char a[]="\n .CJacehknorstu";int putchar(int);int main(void){unsigned long b[]
={0x67dffdff,0x9aa9aa6a,0xa77ffda9,0x7da6aa6a,0xa6 7f6aaa,0xaa9aa9f6,0x11f6},*p
=b,i=24;for(;p+=!*p;*p/=4)switch(0[p]&3)case 0:{return 0;for(p--;i--;i--)case+
2:{i++;if(i)break;else default:continue;if(0)case 1:putchar(a[i&15]);break;}}}
In article <3c**********************************@2g2000hsn.go oglegroups.com>,
<ab****@ieee.orgwrote:
>struct X { const int x; }; struct X* myx = malloc(sizeof(struct X)); myx->x = 42;
What you want here is a struct with a member which is non-const until
you have set its value, and const thereafter. A fairly natural approach
would be to declare a modifiable version of the struct, and then
use a cast to get the non-modifiable version:
struct X { const int x; };
struct X *f(void)
{
struct modifiable_X { int x; };
struct modifiable_X *myx = malloc(sizeof(*myx));
myx->x = 42;
return (struct X *)myx;
}
What is the opinion of the group on the legality of this? Are the
two versions of the struct guaranteed to have the same representation?
Do the type-based aliasing rules make it undefined behaviour?
-- Richard
--
Please remember to mention me / in tapes you leave behind.
In article <06**********************************@z72g2000hsb. googlegroups.com>
<ab****@ieee.orgwrote:
>I like const members in situations where I want the object to be parameterized at run-time, but where I do not expect/want the value to change. ...
Unfortunately, as you have seen, const-qualified members are not
as well-supported in C as in other languages.
>In the particular case I was looking at today, I had an object that is potentially shared. I want every object that has a reference to it to know that their semantics are not going to change under their feet (because the shared objects are const).
In the general case, "const"-qualification does not tell you that
the object will not actually change. For instance, consider:
#include <stdio.h>
void f(int *ip, const int *xp) {
printf("*xp is %d\n", *xp);
*ip = 42;
printf("*xp is %d\n", *xp);
}
You might expect this to print the same value every time, but
in fact, the line:
*ip = 42;
is allowed to change *xp to 42, and does so in:
int main(void) {
int x = 0;
f(&x, &x);
return 0;
}
To make the general case work, we need C99's "restrict" qualifier
as well: a "const int *restrict xp" cannot have both ip and xp
pointing to main()'s "x", in f().
(In this particular case, though, if "xp" had type "pointer to
struct X", where "struct X" has a const-qualified member C, the
compiler *is* allowed to assume that xp->C does not change at any
time. So it would do what you wanted, if you could do what you
wanted in the first place. This is mostly just another way to say
that specific cases can be less general than general cases.)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
In article <ga**********@pc-news.cogsci.ed.ac.uk>
Richard Tobin <ri*****@cogsci.ed.ac.ukwrote:
>What you want here is a struct with a member which is non-const until you have set its value, and const thereafter. A fairly natural approach would be to declare a modifiable version of the struct, and then use a cast to get the non-modifiable version:
struct X { const int x; };
struct X *f(void) {
struct modifiable_X { int x; };
struct modifiable_X *myx = malloc(sizeof(*myx));
myx->x = 42;
return (struct X *)myx; }
What is the opinion of the group on the legality of this? Are the two versions of the struct guaranteed to have the same representation? Do the type-based aliasing rules make it undefined behaviour?
I think that there is enough wiggle room in the standard for an
"evil compiler" (DS9000 C) to cause it to fail, but I think that
it will actually work on all real implementations.
The main problem with this is that it is easy to goof up the
definition of the "struct modifiable_X", with negative consequences.
One can work around that by defining a macro for the contents of
"struct X":
/* this part probably goes in a header somewhere */
#define CONTENTS_OF_X \
int nonconst_int; \
char *nonconst_str; \
CONST int const_int; \
int another_int; \
double and_a_double;
#define CONST const
struct X {
CONTENTS_OF_X
};
/* while this part goes in x.c */
struct X new_x(... params ...) {
#undef CONST
#define CONST /*empty*/
struct modifiable_X { CONTENTS_OF_X };
... malloc and initialize and "return" as above ...
}
This has the advantage of continuing to work when the contents of
a "struct X" are modified, but the disadvantage of being quite
ugly ... almost as ugly as that other not-quite-C language. :-)
--
In-Real-Life: Chris Torek, Wind River Systems
Salt Lake City, UT, USA (40°39.22'N, 111°50.29'W) +1 801 277 2603
email: gmail (figure it out) http://web.torek.net/torek/index.html
On Sep 15, 10:29*am, Chris Torek <nos...@torek.netwrote:
In article <066e34c7-6070-4386-bba8-3cbed74ea...@z72g2000hsb.googlegroups..com>
Unfortunately, as you have seen, const-qualified members are not
as well-supported in C as in other languages.
In the particular case I was looking at today, I had an object that is
potentially shared. I want every object that has a reference to it to
know that their semantics are not going to change under their feet
(because the shared objects are const).
In the general case, "const"-qualification does not tell you that
the object will not actually change. *For instance, consider:
* * #include <stdio.h>
* * void f(int *ip, const int *xp) {
* * * * printf("*xp is %d\n", *xp);
* * * * *ip = 42;
* * * * printf("*xp is %d\n", *xp);
* * }
You might expect this to print the same value every time, but
in fact, the line:
* * * * *ip = 42;
is allowed to change *xp to 42, and does so in:
* * int main(void) {
* * * * int x = 0;
* * * * f(&x, &x);
* * * * return 0;
* * }
To make the general case work, we need C99's "restrict" qualifier
as well: a "const int *restrict xp" cannot have both ip and xp
pointing to main()'s "x", in f().
(In this particular case, though, if "xp" had type "pointer to
struct X", where "struct X" has a const-qualified member C, the
compiler *is* allowed to assume that xp->C does not change at any
time. *So it would do what you wanted, if you could do what you
wanted in the first place. *This is mostly just another way to say
that specific cases can be less general than general cases.)
Your example works exactly as I would expect. If I wanted x to be
immutable, in main() I would write:
const int x = 0; /* note the const */
Now the call to f() generates a warning (in GCC 4.3).
The fact that *xp can be modified through ip in your example is not a
surprise at all. I would say you put your const in the wrong place.
That
is why I wanted the struct members to be const rather than just
using const pointers in the referers.
As an aside, I didn't want to make the entire struct const because I
may
add reference counting or something later.
But this is a bit off-topic now. And just to reiterate, the thread
that
vipin pointed out had the const cast syntax I was looking for, so the
original problem is solved. What I did in the end was create a
CONST_CAST
macro that I could use in my struct factory methods.
Adam This discussion thread is closed Replies have been disabled for this discussion. Similar topics
2 posts
views
Thread by kliczko |
last post: by
| |
3 posts
views
Thread by collinm |
last post: by
|
11 posts
views
Thread by Gagan |
last post: by
|
1 post
views
Thread by Petterson Mikael |
last post: by
|
1 post
views
Thread by Quinn |
last post: by
| | |
1 post
views
Thread by Sachin Garg |
last post: by
| | | | | | | | | | | |