最近在學習資料結構和演算法,發現使用到swap()函式,於是重新看了一下swap函式的各種實現,發現我對函式實參和形參理解不夠透徹,現在分享我對swap的一些見解。
void swap(int *a,int *b)
而以下兩種是不能實現交換的:
void swap1(int a,int b)
void swap2(int *a,int *b)
對於swap1,不能實現交換的理由是,c語言中函式的傳的是形參,也就是乙個副本,雖然在函式內體內交換了,但對真實的資料沒影響。就如以下**:
a和b並沒有因此交換,交換的只是編譯器自動生成的臨時變數ta(形參)和tb!
而對於swap2,執行過程如下**:
printf("a=%d,b=%d",a,b);
pirintf("a'=%d,b'=%d\n",*ta,*tb);可以看到交換了由副本指向的內容,但a,b內容不會變,即原本是ta指向a(ta = &a),tb指向b(tb = &b),交換後,變為ta指向b(ta = &b),tb指向a(tb = &a),相當於換乙個指標變數指向a、b的位址,對a和b的值並無影響。
而
void swap3(char **a,char**b)
//使用如下方式呼叫:
char *pa=&a,*pb=&b;
swap1(&pa,&pb);
呼叫前和呼叫後分別列印printf("a=%d,b=%d,a'=%x,b'=%x\n",a,b,&a,&b);可以看到:並沒有交換a和b由編譯器分配的位址,交換的是指標pa和pb的值,所以a和b的值還是沒變。其實跟上面的swap2()函式很類似,不同的是swap2()交換的是由編譯器為實現函式形參功能而隱式生成的臨時指標變數ta和tb,swap3函式則是交換呼叫swap3前顯式定義好的指標變數pa和pb。
最後關於c語言的泛型程式設計,上面的swap()只能處理整型變數,但我們需要同時可以處理char、double、long型的變數,我們可以使用void*和size_t這些型別來達到。如下
void swap(void *a,void *b,size_t size)
}
使用這樣的形式呼叫:
int c = 1000;
int d = -18;
swap(&c,&d,sizeof(int));
或float a = -4.6;
float b = -2.1;
swap(&a,&b,sizeof(float));
等
但要注意的是彼此之間應該是同種型別,否則會出現錯誤的結果或記憶體越界。 溫故而知新
堆排 建立堆,維護堆的屬性 一次拿掉乙個,然後維護屬性,二分的結構 使得維護屬性只要logn的時間 冒泡也是一次拿走乙個 但是線性的結構 每次沒有節省時間 快排 一次確定 乙個值的位置,然後二分,縮小問題的範圍。floyd找最短 一次更新 將狀態改為經過固定點的 最短距離 迴圈 遍歷每個點,則結果為...
溫故而知新 C語言 遞迴
遞迴。是的,差不多就是這種感覺。上面就是類似遞迴的顯示表現。2017 10 24更新 遞迴這個問題放了很久。也沒有寫。大概是自己還沒有好好理解吧。在這裡寫下自己理解的全部。一 何為遞迴。字面意義,分開看。有傳遞。有回歸。或者歸還。淺顯的理解就是呼叫自己。那麼遞迴可以呼叫自己,肯定是有一些約束的條件。...
溫故而知新 JS函式
1 var total distance 1,3 distance 2,3 2 當方法不需要返回值時,最好直接返回this o.m f o.m var calculator calculator.add 返回this var check 3 儘管建構函式看起來像乙個方法呼叫,它依然會使用這個新物件作...