Pixel swapping trick [SOLVED]

This topic is 3624 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

In the most recent NeHe lesson, TGA loading, they handle BGR -> RGB using this trick: color[0] ^= color[2] ^= color[0] ^= color[2]; What advantages does this approach have, when compared to a more general: temp = color[0]; color[0] = color[2]; color[2] = temp; Thanks for your input. [Edited by - n00body on July 16, 2008 8:56:07 PM]

Share on other sites
It has the advantage of being less readable and pretentiously clever... oh wait.

In other words, don't do what NeHe does here. It has no advantages.

Share on other sites
Quote:
 Original post by n00bodyIn the most recent NeHe lesson, TGA loading, they handle BGR -> RGB using this trick:color[0] ^= color[2] ^= color[0] ^= color[2];What advantages does this approach have, when compared to a more general:temp = color[0];color[0] = color[2];color[2] = temp;Thanks for your input.

Other than not having to allocate space for the temp variable (a minuscule amount), none.
If you're given a programming test and you're asked how to swap two variables without a third temporary variable, you'll know how. :)

Share on other sites
Quote:
 Original post by n00bodycolor[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.

The correct code for the XOR swap is the following:
color[0] ^= color[2];color[2] ^= color[0];color[0] ^= color[2];

Share on other sites
Quote:
Original post by Ra
Quote:
 Original post by n00bodycolor[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.

Mind elaborating for the less understanding [embarrass]? The way I see it, you get right-associativity and the behaviour is well-defined as a ^= (b ^= (a ^= b)).

Share on other sites
IRC logs just now, I'll edit this post to try and trim out the noise in a moment:

Quote:
 [18:20] color[0] ^= color[2] ^= color[0] ^= color[2]; <-- isn't this UB?[18:21] the variables are being modified multiple times between sequence points[18:21] because ^= is not a sequence point, right?[18:21] ra, fuck yes it isn't[18:21] So, yeah, UB.[18:21] <_kw> ...[18:22] Nope, you're wrong, _kw[18:22] <_kw> how is that wrong?[18:22] Operator precidence only affects how the expression is parsed[18:22] That is, color[0] ^= (color[2] ^= color[0]);[18:22] Indeed.[18:22] Modification of the same value multiple times between sequence points. Undefined.[18:23] * PlacidBox looks up a list of sequence points again[18:23] ^= does not count as a sequence point, however, and thus this statement violates the rule in C++ that an integral type such as int cannot be read in the same expression that it is modified without an intervening sequence point.[18:23] If you consider the expression:[18:23] a() = b() = c()[18:23] The C++ standard states that a, b, OR c can execute first.[18:23] Because there are no sequence points.[18:23] Thus, it's entirely valid for a() to be called first, then c(), then b()[18:24] And similar fucked up situations.

Quote:
 [18:24] <_kw> but for example, a = b = 7;[18:24] <_kw> there b=7 is executed first[18:24] <_kw> and returns 7[18:24] <_kw> or evaluates to 7 even[18:25] _kw, for a = b = 7; it's a = (b = 7);[18:25] But, the important part is that it results in 7[18:25] b = a = b = 7 is undefined behavior[18:25] Now, in that statement, b may or may not be assigned to 7 immediately.[18:26] As in, before a is assigned to it.[18:26] wtf, b = a = b = 7 is undefined behavior ???[18:26] <_kw> a=b=7; is defined, but b=a=b=7 is undefined? :-/[18:26] Yes.[18:26] notWtf: Two modifications of a single pod [simple types such as plain structs, ints, pointers, etc --MM] between sequence points, yes, very illegal[18:26] <_kw> wtf.....[18:26] MaulingMonkey: well if things work in the correct order, like left to right, whats wrong[18:27] notWtf: They don't always.[18:27] orly[18:27] notWtf: In fact, it usually varies by compiler.[18:27] Consider:[18:27] std::cout << ++i << ++i << ++i;[18:27] This tends to spit out different values depending on your compiler.[18:27] If i was 0, for example,[18:27] It may print 1 2 3[18:27] 3 3 3[18:27] 3 2 1[18:27] or 1 1 1

Full unedited logs in non-forum-breaky format

Share on other sites
color[0] ^= color[2] as a subexpression appears twice in that statement. That means color[0] is assigned to twice in that statement.

There are no sequence points in that statement but for the trailing semicolon.

Thus, color[0] is assigned (written) twice before any sequence point.

The C++ standard says that the modification of a value more than once between sequence points is undefined behavior.

Thus, the expression is undefined behavior.

Share on other sites
Quote:
Original post by agi_shi
Quote:
Original post by Ra
Quote:
 Original post by n00bodycolor[0] ^= color[2] ^= color[0] ^= color[2];

This is actually undefined behavior because you're modifying those variables multiple times between sequence points.

Mind elaborating for the less understanding [embarrass]? The way I see it, you get right-associativity and the behaviour is well-defined as a ^= (b ^= (a ^= b)).

Even with right-associative evaluation (which isn't necessarily the case per the standard) you're invoking undefined behavior because the values of a and b are modified more than once between sequence points (usually ;--there are other possible sequence points but none are present in this example unless a and b are user-defined types with overloaded ^= operators).

Share on other sites
Okay, thanks for the info guys. I'll just stick to the more generalized approach.

Share on other sites
A note I missed elaborating on:

I give some examples of what undefined behavior could do. Please be aware that in general, undefined behavior can be much worse. You know one of the most common security holes -- buffer overflows -- those things that silently crash your program hours later, or worse, let an attacker inject random code into your servers to be executed?

This happens because in C++, accessing beyond the end of an array constitutes -- you guessed it -- undefined behavior.

Executing a program compiled by a conforming C++ compiler (of which there are none that perfectly do) that invokes undefined behavior may legally launch nuclear missiles at a cow ranch in Alaska. I'm under the impression that, as half-joke, a version of GCC at one point would cause the program to launch the game nethack when invoking certain forms of undefined behavior.

• 37
• 12
• 10
• 10
• 9
• Forum Statistics

• Total Topics
631360
• Total Posts
2999554
×