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

function that returns a const struct: kosher C?

326 views
Skip to first unread message

Eric Rose

unread,
Jul 19, 2001, 11:02:36 AM7/19/01
to
The following C code comes from code in an open-source project.
I was not able to get it to compile using the C compiler on my platform.

It looks like the compiler rejects returning a const struct from a function,
the error message is rather cryptic. The line commented out also does not
compile. Needless to say, gcc swallows both without peep.

"test.c", line 20: left operand must be modifiable lvalue: op "="

Does anyone have an idea what the C standard says about this? Should
I contact my compiler vendor? Is there a workaround?

-Eric


--x Snip x--------------------------------

typedef struct {
int i;
} view ;

typedef struct {
const int i;
} const_view;

view mkview (int j)
{
view w;
w.i = j;
return w;
}

const_view mkcview (int j)
{
view w;
w.i = j;
return *(const_view*)&w;
}

int main()
{
view v = mkview(12);
/* const_view cv = mkcview(12); */
return 0;
}
--
comp.lang.c.moderated - moderation address: cl...@plethora.net

Michael Herrmann

unread,
Jul 19, 2001, 8:41:28 PM7/19/01
to
hy,

> The following C code comes from code in an open-source project.
> I was not able to get it to compile using the C compiler on my platform.

> It looks like the compiler rejects returning a const struct from a
function,
> the error message is rather cryptic. The line commented out also does
not
> compile. Needless to say, gcc swallows both without peep.

> "test.c", line 20: left operand must be modifiable lvalue: op "="

> Does anyone have an idea what the C standard says about this? Should
> I contact my compiler vendor? Is there a workaround?

i dont know what you mean. your codefragment compiled with these one/two
warnings:

micha@trom:~$ gcc -Wall c.c
c.c: In function `main':
c.c:27: warning: unused variable `v'
micha@trom:~$ gcc -Wall c.c
c.c: In function `main':
c.c:28: warning: unused variable `cv'
c.c:27: warning: unused variable `v'
micha@trom:~$ gcc -v
Reading specs from /usr/lib/gcc-lib/i386-linux/2.95.4/specs
gcc version 2.95.4 20010703 (Debian prerelease)


i just copied your code inserted one #include and compiled.

greetings
micha

Douglas A. Gwyn

unread,
Jul 19, 2001, 8:41:25 PM7/19/01
to
Eric Rose wrote:
> Does anyone have an idea what the C standard says about this? Should
> I contact my compiler vendor? Is there a workaround?

I answered this in another thread. The compiler is okay.
The workaround is to remove the "const". You should be
able to #define const /*nothing*/ as a global workaround
in case the problem is more pervasive.

Hans-Bernhard Broeker

unread,
Jul 19, 2001, 8:39:51 PM7/19/01
to
Eric Rose <eric...@yahoo.com> wrote:
> The following C code comes from code in an open-source project.
> I was not able to get it to compile using the C compiler on my platform.

> It looks like the compiler rejects returning a const struct from a
> function, the error message is rather cryptic.

Note that the source line reference in your error message has nothing
to do with returning a struct, constant or otherwise, from a function.

> "test.c", line 20: left operand must be modifiable lvalue: op "="

The referenced line 20 is this one:

> w.i = j;

where w is of type const_view, so w.i is a const int. It's perfectly
obvious why this doesn't compile: you're trying to violate the
const-ness of w.i
--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Michael Farnham

unread,
Jul 20, 2001, 11:55:09 AM7/20/01
to
"Eric Rose" <eric...@yahoo.com> wrote in message
news:clcm-2001...@plethora.net...

The OP says that this is not his code. It is
from an open source project that he is trying
to compile using his own compiler. He also says
that gcc compiles this code with no complaints.

I think Hans must have miscounted lines. The
twentieth line is the line that says

return *(const_view*)&w;

The code does not try to assign a value to a
constant. mkcview creates an object of type
view, assigns a value to the non-constant member
i, and finally returns the view object casted to
a const_view object.

I do not know enough about the standard to know
if *(const_view*)&w is an lvalue. I do know that
after I removed the comments from the line in main
that calls mkcview I compiled the program using
DJGPP 2.95.2, BCB 5.0, and MSVC 6.0. The only
complaints were warnings of usused variables.

Interestingly further testing showed that BCB and
DJGPP compile the line cv.i = 5; with only a
warning about assigning to a constant while MSVC
calls that an error.

The OP does not say what compiler or what platform
he is using to compile the code.

Regards
Mike Farnham

--
Honesty is the best policy. If you
can fake that, you've got it made.
-- George Burns

Hans-Bernhard Broeker

unread,
Jul 21, 2001, 11:38:18 AM7/21/01
to
Michael Farnham <mcfarnh...@prodigy.net> wrote:
[...]

>> const_view mkcview (int j)
>> {
>> view w;
>> w.i = j;
>> return *(const_view*)&w;
>> }
[...]

> I think Hans must have miscounted lines. The twentieth line is the
> line that says

> return *(const_view*)&w;

No it isn't. It's the one above it. You may have forgotten to count
the blank line at the start of the snippet.

Anyway, the error message he showed complained the "left operand" of
some "op=" that was not modifiable. I would have to be very much
mistaken if that's not the '=' operator in the line

w.i=j;

it's talking about, and indeed, the left side of it is not a
modifiable lvalue, since this struct element is flagged 'const'.

--
Hans-Bernhard Broeker (bro...@physik.rwth-aachen.de)
Even if all the snow were burnt, ashes would remain.

Michael Farnham

unread,
Jul 23, 2001, 11:22:38 AM7/23/01
to
"Hans-Bernhard Broeker" <bro...@physik.rwth-aachen.de> wrote in
message news:clcm-2001...@plethora.net...

> Michael Farnham <mcfarnh...@prodigy.net> wrote:
> [...]
> >> const_view mkcview (int j)
> >> {
> >> view w;
> >> w.i = j;
> >> return *(const_view*)&w;
> >> }
> [...]
>
> > I think Hans must have miscounted lines. The twentieth line is the
> > line that says
>
> > return *(const_view*)&w;
>
> No it isn't. It's the one above it. You may have forgotten to count
> the blank line at the start of the snippet.
>
> Anyway, the error message he showed complained the "left operand" of
> some "op=" that was not modifiable. I would have to be very much
> mistaken if that's not the '=' operator in the line
>
> w.i=j;
>
> it's talking about, and indeed, the left side of it is not a
> modifiable lvalue, since this struct element is flagged 'const'.

But it is not flagged const. The w is of type view not of
type const_view. The i member in the view object is not const.

This piece of code makes a view object, sets the non-const member
i of the view object, then returns the view object casted to a
const_view object.

Richard Bos

unread,
Jul 23, 2001, 11:26:32 AM7/23/01
to
Hans-Bernhard Broeker <bro...@physik.rwth-aachen.de> wrote:

> Michael Farnham <mcfarnh...@prodigy.net> wrote:
> [...]
> >> const_view mkcview (int j)
> >> {
> >> view w;
> >> w.i = j;
> >> return *(const_view*)&w;
> >> }
>

> Anyway, the error message he showed complained the "left operand" of
> some "op=" that was not modifiable. I would have to be very much
> mistaken if that's not the '=' operator in the line
>
> w.i=j;
>
> it's talking about, and indeed, the left side of it is not a
> modifiable lvalue, since this struct element is flagged 'const'.

No, it's not; the w in question is a view, not a const_view. It's only
cast to a const_view when returned.

Richard

Bruce G. Stewart

unread,
Jul 24, 2001, 6:52:49 PM7/24/01
to
Eric Rose wrote:
> "test.c", line 20: left operand must be modifiable lvalue: op "="
[...]

> --x Snip x--------------------------------
>
> typedef struct {
> int i;
> } view ;
>
> typedef struct {
> const int i;
> } const_view;
>
> view mkview (int j)
> {
> view w;
> w.i = j;
> return w;
> }
>
> const_view mkcview (int j)
> {
> view w;
> w.i = j;
> return *(const_view*)&w;
> }
>
> int main()
> {
> view v = mkview(12);
> /* const_view cv = mkcview(12); */
> return 0;
> }

It is almost as if the compiler is confusing the two structure member
i's, in the manner of old k&r c. I wonder if the fact that both structs
are anonymouse confuses it. Does it behave any differently if you add
structure tags? for example:

typedef struct view {
int i;
} view ;

typedef struct const_view {
const int i;
} const_view;

Brian J. Gough

unread,
Jul 28, 2001, 12:12:52 PM7/28/01
to
On 24 Jul 2001 22:52:49 GMT, Bruce G. Stewart

<bruce.g...@worldnet.att.net> wrote:
>
> It is almost as if the compiler is confusing the two structure member
> i's, in the manner of old k&r c. I wonder if the fact that both structs
> are anonymouse confuses it. Does it behave any differently if you add
> structure tags? for example:
>
> typedef struct view {
> int i;
> } view ;
>
> typedef struct const_view {
> const int i;
> } const_view;

Still gives the same error, unfortunately. (I am the author of the
initial code in question here).

Below is a simpler program which shows the same behaviour. My goal is
to dynamically initialize a struct which has a const-qualified element.

bash-2.03$ more test.c
#include <stdio.h>

typedef struct {
int k;
int kmax;
} A;

typedef struct {
int k;
const int kmax;
} B;

B create_B (int k, int kmax)
{
A a;
a.k = k;
a.kmax = kmax;
return *((B *)(&a));
}

int main (void)
{
B b = create_B (0, 10);
printf("b.k=%d\n", b.k);
printf("b.kmax=%d\n", b.kmax);
return 0;
}

Compiling with gcc,

bash-2.03$ gcc -Wall -ansi -pedantic -O2 test.c
bash-2.03$ ./a.out
b.k=0
b.kmax=10

With Sun's Workshop Pro cc (the C-compiler cc=c89, not the C++ compiler),

bash-2.03$ cc -V test.c
cc: Sun WorkShop 6 update 1 C 5.2 2000/09/11
acomp: Sun WorkShop 6 update 1 C 5.2 2000/09/11
"test.c", line 18: left operand must be modifiable lvalue: op "="
"test.c", line 23: left operand must be modifiable lvalue: op "="
cc: acomp failed for test.c

It seems that Sun's compiler won't allow a function that returns a
struct with a const element. I can see that would be valid if it was
used in assignments, but it is only used for initialization.

What part of the standard forbids this and, if so is there a legal way
to achieve the goal?

regards
Brian
--
remove the spam trap 123 to reply

CBFalconer

unread,
Jul 29, 2001, 11:53:16 PM7/29/01
to
"Brian J. Gough" wrote:
>
.... snip...

>
> It seems that Sun's compiler won't allow a function that returns a
> struct with a const element. I can see that would be valid if it was
> used in assignments, but it is only used for initialization.
>
> What part of the standard forbids this and, if so is there a legal way
> to achieve the goal?

Seems quite reasonable to me. You can assign structs bodily with
the = operator, so what is the compiler to do with such a struct?
The only reasonable thing is to mark the whole thing const if any
component is marked const. Having done that, the return value of
the function is useless, because it can't be assigned anywhere
without tortuous casting.

--
Chuck F (cbfal...@my-deja.com) (cbfal...@XXXXworldnet.att.net)
(Remove "XXXX" from reply address. my-deja works unmodified)
mailto:u...@ftc.gov (for spambots to harvest)

Greg Law

unread,
Jul 31, 2001, 3:16:43 PM7/31/01
to
CBFalconer wrote:
>
> "Brian J. Gough" wrote:
> >
> .... snip...
> >
> > It seems that Sun's compiler won't allow a function that returns a
> > struct with a const element. I can see that would be valid if it was
> > used in assignments, but it is only used for initialization.
> >
> > What part of the standard forbids this and, if so is there a legal way
> > to achieve the goal?
>
> Seems quite reasonable to me. You can assign structs bodily with
> the = operator, so what is the compiler to do with such a struct?
> The only reasonable thing is to mark the whole thing const if any
> component is marked const. Having done that, the return value of
> the function is useless, because it can't be assigned anywhere
> without tortuous casting.

I'm lost :-( The return value is a constant structure right? So why
can't it be used to initialise another constant structure of the same
type? The returned structure in this case is an rvalue, and we're
initialising a const lvalue with it.

Or have I totally missed the point (as usual)?

Greg

Brian Gough

unread,
Jul 31, 2001, 3:17:49 PM7/31/01
to
On 30 Jul 2001 03:53:16 GMT, CBFalconer <cbfal...@my-deja.com> wrote:
> Seems quite reasonable to me. You can assign structs bodily with
> the = operator, so what is the compiler to do with such a struct?

It could be used as an initializer I would have thought. I would
expect an error if I had tried to do assignments with it though.

--
remove the spam trap 123 to reply

Bruce G. Stewart

unread,
Jul 31, 2001, 3:18:10 PM7/31/01
to
CBFalconer wrote:
>
> "Brian J. Gough" wrote:
> >
> .... snip...
> >
> > It seems that Sun's compiler won't allow a function that returns a
> > struct with a const element. I can see that would be valid if it was
> > used in assignments, but it is only used for initialization.
> >
> > What part of the standard forbids this and, if so is there a legal way
> > to achieve the goal?
>
> Seems quite reasonable to me. You can assign structs bodily with
> the = operator, so what is the compiler to do with such a struct?
> The only reasonable thing is to mark the whole thing const if any
> component is marked const. Having done that, the return value of
> the function is useless, because it can't be assigned anywhere
> without tortuous casting.

In Eric's example, the return value of the function is being used to
initialize the struct, rather than assign to it. It appears he has
already done the required casting in the function mkcview().

0 new messages