473,395 Members | 2,467 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Problem: assignment of read-only member

/* 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
Sep 14 '08 #1
16 19220
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.
Sep 14 '08 #2
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

Sep 14 '08 #3
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
Sep 14 '08 #4
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.
Sep 14 '08 #5
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
Sep 14 '08 #6
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;

Sep 14 '08 #7
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
Sep 14 '08 #8
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)
Sep 14 '08 #9
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.

Sep 14 '08 #10
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
Sep 14 '08 #11
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.

Sep 14 '08 #12
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;}}}
Sep 15 '08 #13
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.
Sep 15 '08 #14
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
Sep 15 '08 #15
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
Sep 15 '08 #16
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
Sep 15 '08 #17

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: kliczko | last post by:
I have php4 on system FreeBSD.I did think that php work very well (function phpinfo() work), if I didn't probe above script: <? if(!isset($name)&&!isset($password)) { ?> <h1>Please...
1
by: Guy_in_Wisconsin | last post by:
Hello. I'm trying out Python after being a novice Perl user. I'm having an unexpected result when I run this script: # test.py f = open("one.bin",'rb') n = open("two.bin",'wb') x =...
3
by: collinm | last post by:
hi i send a command to a led display, the led display is suppose to return me some character i write a string on a serial port void ledDisplayExist() { char msg={'\0', '\0', '\0', '\0',...
11
by: Gagan | last post by:
//Problem Statement // //You work for a company that sells mechanical bit counting devices. These devices //wear out when they do a lot of counting. You are going to see how much wear has...
1
by: Petterson Mikael | last post by:
Hi, When we read one version of the xml we had the following: <class name="Aal0TpVccTp"> <description>From Cello MIM. Ref. </description>
1
by: Quinn | last post by:
Hi all, I have some binary files in the following format: text line 1 text line 2 .... text line N end of text single in binary 1 single in binary 2 single N EOF
9
by: KWSW | last post by:
Got an assignment where I need to convert between pgm and ppm. Now I know about the homework guideline so i went ahead to try to do up everything first and I managed to get it right. Or so it seems....
4
by: kdsutaia | last post by:
hi! I am trying to read file line by line using BufferReader class.Following I have written to read but some how for few of the file it is not reading the whole file. Can any help me to resolve this...
1
by: Sachin Garg | last post by:
I have a program which opens a fstream in binary input+output mode, creating the file if it doesn't exists. But writing doesn't works after reading, it must be something obvious that I am not aware...
0
by: adydixit | last post by:
Hello Guys., we have making one print pooling application in .net. but thier is some problem read proper color of printer. e.g. if i will take Black/white print from printer but printer rturn...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.