1. 程式人生 > >用異或來交換兩個變數更耗時

用異或來交換兩個變數更耗時

FROM:陳碩 http://blog.csdn.net/solstice/article/details/5166912 

翻轉一個字串,例如把 "12345" 變成 "54321",這是一個最簡單的不過的編碼任務,即便是 C 語言初學者的也能毫不費力地寫出類似如下的程式碼:

// 版本一,用中間變數交換兩個數,好程式碼

void reverse_by_swap(char* str, int n)

{

  char* begin = str;

  char* end = str + n - 1;

  while (begin < end) {

    char tmp = *begin;

    *begin = *end;

    *end = tmp;

    ++begin;

    --end;

  }

}

這個程式碼清晰,直白,沒有任何高深的技巧。

不知從什麼時候開始,有人發明了不使用臨時變數交換兩個數的辦法,用“不用臨時變數交換兩個數”在 google 上能搜到很多文章。下面是一個典型的實現:

// 版本二,用異或運算交換兩個數,爛程式碼

void reverse_by_xor(char* str, int n)

{

  // WARNING: BAD code

  char* begin = str;

  char* end = str + n - 1;

  while (begin < end) {

    *begin ^= *end;

    *end ^= *begin;

    *begin ^= *end;

    ++begin;

    --end;

  }

}

受一些過時的教科書的誤導,有人認為程式裡少用一個變數,節省一個位元組的空間,會讓程式執行更快。這是不對的,至少在這裡不成立:

1.       這個所謂的“技巧”在現代的機器上只會更慢(我甚至懷疑它從來就不可能比原始辦法快)。原始辦法是兩次記憶體讀和寫,這個"技巧"是六讀三寫加三次異或(或許編譯器可以優化成兩讀三寫加三次異或)。

2.       同樣也不能節省記憶體,因為中間變數 tmp 通常會是暫存器(稍後有彙編程式碼供分析)。就算它在函式的區域性堆疊(stack)上,反正棧已經開在那兒了,也沒有進一步的函式呼叫,根本節約不了一丁點記憶體。

3.       相反,由於計算步驟較多,會使用更多的指令,編譯後的機器碼長度會增加。(這不是什麼大問題,短的程式碼不一定快,後面有另外一個例子。)

這個技巧的意義完全在於應付變態的面試,所以知道就行,但絕對不能放在產品程式碼中。我也想不出問這樣的面試題意義何在。

更有甚者,把其中三句:

    *begin ^= *end;

    *end ^= *begin;

    *begin ^= *end;

寫成一句:

    *begin ^= *end ^= *begin ^= *end; // WRONG

(a^=b^=a^=b;)

這更是大有問題,會導致未定義的行為(undefined behavior)。C 語言的一條語句中,一個變數的值只允許改變一次,像 x = x++ 這種程式碼都是未定義行為。在C語言裡沒有哪條規則保證這兩種寫法是等價的。
(致語言律師:我知道,黑話叫序列點,一個語句可能不止一個序列點,請允許我在這裡使用不精確的表述。)

這不是一個值得炫耀的技巧,只會醜化劣化程式碼。

相關推薦

交換變數耗時

FROM:陳碩 http://blog.csdn.net/solstice/article/details/5166912  翻轉一個字串,例如把 "12345" 變成 "54321",這是一個最簡單的不過的編碼任務,即便是 C 語言初學者的也能毫不費力地寫出類似如下的程式

交換變數是錯誤的

用異或來交換變數是錯誤的 翻轉一個字串,例如把 “12345” 變成 “54321”,這是一個最簡單的不過的編碼任務,即便是 C 語言初學者的也能毫不費力地寫出類似如下的程式碼: // 版本一,用中間變數交換兩個數,好程式碼 void reverse_

深思通過運算交換變數

平常程式設計的時候交換兩個數的需求很常見,比如說氣泡排序裡面的位置交換,我們一般都會使用下面這種方法: public void swap(int a, int b){ int temp = a; a = b; b = temp; } 最近右發現一個抖機靈的方法,看著逼格很

使用運算交換變數位置的演算法非常低!

看了很多程式設計方面的知識,在慕課網上的一個關於二進位制的視訊中,偶然聽見老師說採用異或運算的方法交換兩個數字的順序可以提高效率,原因是位運算是直接對二進位制位進行運算,而二進位制位更接近底層。 因此,我一直信誓旦旦的給朋友們普及異或運算的高效率,直到被別人反駁之後,我去網上搜了很多相關的文章。

一道簡單的演算法題:不借助第三變數交換變數的值

今天做筆試碰到一道簡單的演算法題:不借助第三變數來交換兩個變數的值,記錄一下。 交換兩個變數的值的普遍做法都是藉助第三變數,這樣具有較高的可讀性。 a = 3 b = 5 t = a a = b b = t 但是,如果記憶體有限,只允許用2個變數呢? 強大的CS當然有辦法解決

採用位方式將變數數值調換

1 package debug; 2 3 class Demo2 { 4 public static void main(String[] args){ 5 int a = 1; 6 int b = 2; 7 System.out.

操作符交換整數

異或:相同為0 不同為1 例:一位二進位制異或取值表 取值 取值 結果 0 0 0 0 1 1 1 0 1 1 1 0 那麼我們交換一個兩個整數值就不需要使用中間值了 public static void main(String[] args) { int a = 2; //二進

php使用xor調換變數的值的原理

1、首先,我們要知道什麼是異或,異或,簡單來說就是:相同的兩個數,異或的結果是0;不同的兩個數,異或的結果是1。 2、0和0,異或的結果是0。1和1,異或的結果是0。0和1,異或的結果是1。於是我們發現,在0和1的世界裡:A和B異或,結果是C;B和C異或的結果

運算交換個數

平常交換兩個數一般是利用一箇中間變數,其實可以利用異或^也可以實現交換,而且效率更快哦! 程式碼如下: void Swap(int& a,int& b){ if(a!=b){ a^=b; b^=a; a

在C# 中不使用 第三方變數 交換變數的值

1) 算術運算 簡單來說,就是通過普通的+和-運算來實現。程式碼如下: int a,b; a=10;b=12; a=b-a; //a=2;b=12 b=b-a; //a=2;b=10 a=b+a; //a=10;b=10 通過以上運算,a和b中的值就進行了交換。表面上看起來

運算實現變數互換

        一般情況下,如果我們要實現兩個變數互換需要藉助於一個第三方臨時變數,這個臨時變數可以臨時存放某一個變數的值,幫助我們完成值的交換。有沒有不需要其他變數、直接實現值互換的方法呢?  答案是:當然有。     &n

交換變數的值

通常做法 #include<stdio.h> #include<stdlib.h> int main() {     int a=10, b=20,temp;     temp=a;     a=b;

關於交換變數的不用第三變數 的問題

void my_swa22p(int &a, int &b) {     a = a^b;     b = a^b;     a = a^b;} 這個是經典的 不用第三個變數進行交換的方式; 但是這個有個 問題··· int a = 3; my_swa2

方式將變量數值調換

clas 兩個 rgs package 異或 dem int span [] 1 package debug; 2 3 class Demo2 { 4 public static void main(String[] args){ 5

Java中運算實現整數的交換以及其功能函式實現

       今天學習到一種超酷炫的交換兩個整數的方法,給各位分享一下。異或運算屬於位運算的一種,首先簡單介紹一下異或預算的語法規則。 假設a與b為不相等的兩個整數。 (1)a^a=0; (2)a^b

通過位交換a,b的值和通過中間變量交換a,b的值

[] printf urn %d include ret std char har //通過位異或來交換a,b的值 #include <stdio.h> int main(int argc, const char * argv[]) { int a=20,

交換變數的值,不使用第三變數的方法

  Q1: 我們都知道交換兩個數的數值可以用三行程式碼解決,這是在C語言中就學過的: int c; c = a; a = b; b = c;   數學老師可能會給我們這個建議: a = a + b; b = a - b; //b=a+b-b=a a =

交換變數的三種方式

這裡我們介紹三種交換變數的方式: 第一種: 這也是最為常用的一種,引入第三個變數: a=1; b=2; 引入第三個變數c交換: c=a; a=b; b=c; 此時a=2,b=1; 第二種:不用引入第三個變數,利用加減法實現 a=1; b=2; 交換

【C語言】使用運算子交換個數

異或交換兩個數: #include<stdio.h> #include<stdlib.h> int main() { int a, b; a = 10; b = 20; a= a^b; b =a^b; a =a^b; printf("%d\n%d\n", a

一行python程式碼寫九九乘法表,1,2,3…到100的和,交換變數的值

用一行程式碼輸出九九乘法表: 第一種方法: print('\n'.join([' '.join(["%d*%d=%d"%(i,j,i*j) for i in range(1,j+1)])for j in range(1,10)])) 第二種方法: print('\n'.join