# Pixel swapping trick [SOLVED]

This topic is 3836 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.

• ### What is your GameDev Story?

In 2019 we are celebrating 20 years of GameDev.net! Share your GameDev Story with us.

• 15
• 14
• 46
• 22
• 27
• ### Forum Statistics

• Total Topics
634048
• Total Posts
3015236
×