2013-07-02 60 views
1

我正在測試比較器功能的實現。因此,這裏是我的代碼,工作正確執行C中的比較器功能不能按預期工作

#include <stdio.h> 
#include <string.h> 

int compare_names(const void* a, const void* b) 
{ 
    char* sa = (char*) a; 
    char* sb = (char*) b; 
    return strcmp(sa, sb); 
} 

int main() 
{ 
    char *a = "Bianca"; 
    char *b = "Ana"; 
    printf("Comparing %s with %s returns: %i\n", a, b, compare_names(a, b)); 
    return 0; 
} 

但我不認爲這是在compare_names功能如右圖ab參數應該變成是一個字符指針的指針。作爲一本書我讀過指出,爲compare_names功能正確的代碼將

int compare_names(const void* a, const void* b) 
{ 
    char** sa = (char**) a; 
    char** sb = (char**) b; 
    return strcmp(*sa, *sb); 
} 

但是,當我跑的代碼,我得到了一個分段錯誤(核心轉儲)。

我在這裏錯過了什麼?

編輯:我在Linux x64上使用gcc。

+1

可能您書中代碼的上下文有所不同。使用不同的上下文(例如其他數據類型,其他數據關係和嵌套等),您可以(並將)獲得不同的代碼。 – glglgl

+1

假設書中的代碼出現在qsort比較器或類似的環境中,那麼這是有道理的。在這種情況下,它應該被稱爲'compare_names(&a,&b)'。 –

+0

@glglgl這就是我的想法。 – kaneda

回答

1
#include <stdio.h> 
#include <string.h> 

int compare_names(const void* a, const void* b) 
{ 
    char** sa = (char**) a; 
    char** sb = (char**) b; 
    return strcmp(*sa, *sb); 
} 

int main() 
{ 
    char *a = "Bianca"; 
    char *b = "Ana"; 
    printf("Comparing %s with %s returns: %i\n", a, b, compare_names(&a, &b)); 
    return 0; 
} 

現在沒關係。您必須將ab的地址放在printf參數中,因爲這些參數已被鑄造爲char**

+0

這有效,但我的第一次實施是瑕疵?如果不是的話,修正後的第二個解決方案要冗長得多。 – kaneda

+1

@kaneda你的第一個實現是正確的。這兩個函數將產生相同的輸出。在這種情況下,第二個在你的書中使用?第二個的唯一好處是你可以改變'a'和'b'的值。在你的情況下選擇更方便。 – nouney

+0

帶有void指針的版本看起來像是用於qsort();如果是這樣的話,它的比較函數需要指向要排序的數組元素的原因,所以如果你有一個字符串數組,它將需要一個指針字符串(字符串是指向字符的指針) – loreb

1

char** sa = (char**) a;此行說:「如果你direference兩次你sa你會最終有一個char」問題是,既然你a是字符指針不能direference兩次。所以你所做的演員一般都是錯誤的。

鑄造時,編譯器改掉解釋你的*a在進行轉換你的*sa最後成了一個BadPtr,因爲它未能從轉換到charchar *char作爲字符指針等等。

所以在你的strcmp()你有兩個BadPtr。

1

您正在傳遞char *參數,而不是char **參數。您發佈顯示字符**的示例代碼執行以下操作:

1. Change generic pointer to a pointer to a string. 
2. Compare the strings by dereferencing the char** arguments, meaning you're passing char* arguments to strcmp and return the result. 

但你傳遞的char *參數的比較功能,所以反引用最終傳遞char類型的參數到strcmp。由於它需要指針,所以char被解釋爲內存地址。將「hello」與「bye」比較實際上將地址0x67處的字符串與地址0x62處的字符串進行比較,這將會發生segfault。

通過& a和& b您的比較功能,使其不會段錯誤。

0

然而,這兩個版本都適用於第二版「campare_names」函數,因此在調用函數時應該傳遞一個指向每個char指針的指針。

但是,您的函數版本是正確的,只有在您期望函數將改變指針位置或指向的數據時,纔會使用雙指針參數。在這種情況下,由於strcmp函數只讀取char *數據並且不作任何更改,所以不需要附加指針。