Index Home About Blog
Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@osdl.org>
Subject: Re: GCC 3.4 Heads-up
Original-Message-ID: <Pine.LNX.4.58.0401041232440.2162@home.osdl.org>
Date: Sun, 4 Jan 2004 21:01:06 GMT
Message-ID: <fa.j4s0ql6.1eickgo@ifi.uio.no>

On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
> Since that's a matter of taste I can't disagree. The point was that the
> original post used
>    *(a ? &b : &c) = d;
> which generates either warnings or errors if b or c is a register
> variable, because you are not allowed to take the address of a register.

The thing is, the above case is the _only_ case where there is any point
to using a conditional expression and an assignment to the result in the
same expression.

If you have local variables (register or not), the sane thing to do is

	if (a)
		b = d;
	else
		c = d;

or variations on that. That's the readable code.

The only case where conditional assignment expressions are useful is when
you are literally trying to avoid doing branches, and the compiler isn't
smart enough to avoid them otherwise.

Check the compiler output some day. Try out what

	int a, b;

	void test_assignment_1(int val)
	{
		*(val ? &a : &b) = 1;
	}

	void test_assignment_2(int val)
	{
		if (val)
			a = 1;
		else
			b = 1;
	}

	void test_assignment_3(int val)
	{
		(val ? a : b) = 1;
	}

actually generate.

Hint: only the first one generates code without any jumps (on
architectures that have conditional moves and with "normal" compilers).

In short: the "*(a?&b:&c) = x" format actually has some advantages. It
also happens to be standard C. The "(a ? b : c) = x" format is not only
not real C code, but it has _zero_ advantages.

		Linus

Newsgroups: fa.linux.kernel
From: Linus Torvalds <torvalds@osdl.org>
Subject: Re: GCC 3.4 Heads-up
Original-Message-ID: <Pine.LNX.4.58.0401042028140.2162@home.osdl.org>
Date: Mon, 5 Jan 2004 04:38:06 GMT
Message-ID: <fa.j3rsqdc.1di8koi@ifi.uio.no>

On Sun, 4 Jan 2004, Bill Davidsen wrote:
>
> Your example, which I quoted, *is* standard C. And it avoids duplication
> of code without extra variables, and is readable. We both agreed it was
> standard, why have you changed your mind?

Oh, that one. I thought you were talking about the gcc extension.

My version is not what I'd call really readable unless you actually have
an agenda to access the variable though a pointer. In fact, the only case
where I have actually seen constructs like that is literally when you want
to avoid a branch for some specific reason, and you do something like
this:

	int branchless_code(int *ptr)
	{
		int dummy;

		...
		*(ptr ? ptr : &dummy) = value;
		...
	}

it you'd rather do a unconditional store through a conditional pointer
than have a conditional store, and you use a dummy "sink" variable to take
the store if the condition isn't true.

Some compilers apparently generate this kind of code internally from
conditional statements. I've never seen gcc do it, though.

		Linus


Index Home About Blog