Question from "The Standard C Library" - create a program with this

J

John Reye

Hello,

Exercise 0.2 (page 16) from "The Standard C Library" is:
Create a program which contains this line
x : ((struct x *)x)->x = x(5);

An "easy" solution is given right at the bottom; but that is not the
main focus here...



I am interested in a solution where the ":"
is part of an inline if... () ? :

Thus the line will occur like this:
?
x : ((struct x *)x)->x = x(5);


Here is my attempt:

#include <stdio.h>
#include <stdlib.h>

struct y
{
struct y *num;
int a;
};

struct x
{
struct y *x;
};

#define x(num) (&(struct y){NULL, (num)})

int main(void)
{
int i;
struct y *tmp;
struct y *x = &(struct y) {&(struct y) {NULL, 2}, 1};
x = x(5);
((struct x *)x)->x = x(5);
for (i = 0; i < 2; ++i) {
tmp = i ?
x : ((struct x *)x)->x = x(5);
printf("%d\n", tmp->num->a);
}
return EXIT_SUCCESS;
}


The compiler (gcc) complains:
almost.c:30:31: error: lvalue required as left operand of assignment

I find this rather strange, since the following lines from above,
compile without error:
x = x(5);
((struct x *)x)->x = x(5);

How can one fix the compiler error????


Not even this works:
tmp = ((struct y*)(i ?
x : ((struct x *)x)->x) = x(5));

As an aside... Ironically if I dereference the inline if, then the
following compiles without problem:
*tmp = *(i ?
x : ((struct x *)x)->x) = *x(5);



My question:
1) Can one fix my above attempt, that results in the compiler error?
2) Can one have this line in a valid C program, as part of an inline-
if
/*... */ ? /*... */
x : ((struct x *)x)->x = x(5);

Thanks.





"Easy" solution:

#include <stdio.h>
#include <stdlib.h>

struct y
{
struct y *num;
int a;
};

struct x
{
struct y *x;
};

#define x(num) (&(struct y){NULL, (num)})

int main(void)
{
int i;
struct y *tmp;
struct y *x = &(struct y) {&(struct y) {NULL, 2}, 1};
// x is a goto-label
x : ((struct x *)x)->x = x(5);
printf("%d\n", x->num->a);
return EXIT_SUCCESS;
}
 
N

Nobody

Exercise 0.2 (page 16) from "The Standard C Library" is:
Create a program which contains this line
x : ((struct x *)x)->x = x(5);

An "easy" solution is given right at the bottom; but that is not the
main focus here...



I am interested in a solution where the ":"
is part of an inline if... () ? :

Thus the line will occur like this:
?
x : ((struct x *)x)->x = x(5);

1. The LHS of an assignment must be an lvalue.
2. a?b:c is not an lvalue, even if b and c are lvalues.
3. ?: has higher precedence than =, so a?b:c=d is parsed as (a?b:c)=d
rather than as a?b:(c=d).
2) Can one have this line in a valid C program, as part of an inline-
if
/*... */ ? /*... */
x : ((struct x *)x)->x = x(5);

No.
 
O

Old Wolf


What is this then:

struct x { int x; };
#define x(N) N

int main()
{
struct x y, *x = &y;
x : ((struct x *)x)->x = x(5);
return 0;
}

I am also suspicious of OP's x(5), is a
struct literal addressable?
 
J

James Kuyper

What is this then:

It is something that is not "part of an inline-if", by which the OP
apparently means an expression containing a conditional operator.
struct x { int x; };
#define x(N) N

int main()
{
struct x y, *x = &y;
x : ((struct x *)x)->x = x(5);
return 0;
}

I am also suspicious of OP's x(5), is a
struct literal addressable?

6.5.2.5p10 contains Example 3 of compound literals:
drawline(&(struct point){.x=1, .y=1},
&(struct point){.x=3, .y=4});

so I would say that the answer is "yes".
 
J

John Reye

Thanks for the helpful replies

I wrote
As an aside... Ironically if I dereference the inline if, then the
following compiles without problem:
    *tmp = *(i ?
             x : ((struct x *)x)->x) = *x(5);

This code is not nice, since tmp does not point to any allocated
memory.

But why does the above code work... but I not able to do this:
tmp = &(*(i ?
x : ((struct x *)x)->x) = *x(5));

Error-message from gcc:
almost.c:23:11: error: lvalue required as unary ‘&’ operand

(All I did was add the & operator.)

Does this mean that dereferencing an address, does non necessarily
yield an lvalue??
Surely I must have an lvalue above, because I can see that I have
storage that is either located at address x, or address x->x

Thanks.
 
J

John Reye

But why does the above code work... but I not able to do this:
    tmp = &(*(i ?
             x : ((struct x *)x)->x) = *x(5));

Error-message from gcc:
almost.c:23:11: error: lvalue required as unary ‘&’ operand

(All I did was add the & operator.)

The problem is that the unary address operator &, never yields an
lvalue.

Does this mean that dereferencing an address, does non necessarily
yield an lvalue??
Dereferencing an address (e.g. *x) does yield an lvalue, but taking
the unary address operator &, never yields an lvalue.
&(*x) is not a lvalue.
 
J

James Kuyper

The problem is that the unary address operator &, never yields an
lvalue.

While you're correct about the what unary & yields, that doesn't explain
the problem. The error message is complaining about the operand of unary
&, not what it yields.

I've avoided commenting on this question because, while it looks to me
like your code should be valid, I wasn't willing to swear to that. But
if it does contain a problem, the one you've identified isn't it.
 
J

James Kuyper

The problem is that the unary address operator &, never yields an
lvalue.

While you're correct about the what unary & yields, that doesn't explain
the problem. The error message is complaining about the operand of unary
&, not what it yields.

I've avoided commenting on this question because, while it looks to me
like your code should be valid, I wasn't willing to swear to that. But
if it does contain a problem, the one you've identified isn't it.
 
J

John Reye

While you're correct about the what unary & yields, that doesn't explain
the problem. The error message is complaining about the operand of unary
&, not what it yields.

Ah yes of course! You're right! Thanks.


The real problem above is that an assignment does not yield an lvalue.
Assignment is right associative, and yields the result rvalue at the
right-hand side of the =.


Example:

int main(void)
{
int* a, *b, *c;
a = &(*b); // ok
a = &(*b = *c); // gcc compilation error: lvalue required as
unary ‘&’ operand
return 0;
}
 

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,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top