2011-03-09 13 views
2

我已經開始學習C和指針,並且一直在研究互聯網上的教程。我認爲代碼應該像在教程中一樣工作,對我來說似乎是正確的,但是我得到了一個分割錯誤。該代碼是:Mac上的C中的分段錯誤,從教程中直接複製

#include <stdio.h> 
#include <stdlib.h> 

/* 
* 
*/ 
int main(int argc, char** argv) { 
    float fl = 3.14; 
    unsigned int addr = (unsigned int) &fl; 
    printf("fl's address=%u\n", addr); 
    printf("addr's contents = %.2f\n", * (float*) addr); 
    return (EXIT_SUCCESS); 
} 

,我得到的是

/Applications/NetBeans/NetBeans  
6.9.1.app/Contents/Resources/NetBeans/ide/bin/nativeexecution/dorun.sh: line 33: 1626  
Segmentation fault  sh "${SHFILE}" 

這是否有使用Mac和我有什麼或有什麼錯誤的代碼中的錯誤?

非常感謝, NIEK

+0

你用什麼工具編譯它?如果你只是在終端上使用GCC,這應該可以正常工作。 – 2011-03-09 15:13:20

+0

@Chris我同時使用NetBeans和-gcc,都沒有工作。但sampblebias示例工作,所以我打算在此基礎上進行構建。 – 2011-03-09 17:27:26

+0

你是否正在使用雪豹? – 2011-03-09 17:39:10

回答

6

試試這個:

int main(int argc, char** argv) { 
    float fl = 3.14; 
    float *addr = &fl; 
    printf("fl's address=%p\n", addr); 
    printf("addr's contents = %.2f\n", *addr); 
    return (EXIT_SUCCESS); 
} 
+0

是的,這工作,謝謝。 – 2011-03-09 15:14:55

+0

'uintptr_t'也可以工作(通過強制轉換),因爲它保證足夠大以存儲指針類型。格式化字符串應該是'printf(「fl's address =%」PRIuPTR「\ n」,addr)' – 2011-03-09 15:21:37

+1

@samplebias,這是nit picking,但是要完全符合你的要求時你應該把指針指向'void *'它到'printf'。例如'gcc'會警告你。 – 2011-03-09 15:26:36

1

的代碼似乎是正確的,使用MinGW GCC和運行編譯給出了下面的輸出:

fl's address=2293528 
addr's contents = 3.14 
+0

當我使用GCC編譯我得到test.c:在函數'main'中: test.c:9:警告:從指針轉換爲不同大小的整數 test.c:11:錯誤:無效類型參數'一元*'。你知道爲什麼你的編譯和我的不能嗎? – 2011-03-09 15:17:05

+0

好吧,我甚至沒有用'-Wall'得到這個......看起來像是一個數據類型大小問題或32/64位問題,那麼,我在這裏是一個Windows 7 32位系統。 – schnaader 2011-03-09 15:18:21

+3

@Beorn - 你是64位的嗎?如果是這樣,那可能是問題所在。 – 2011-03-09 15:19:18

4

這可能是未定義的行爲。不能保證int和指針可以保持相同的值,並且不應該在它們之間進行投射。改爲使用float*

C99 6.3.2.3/5/6狀態:

5: An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

6: Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

+0

你可以使用'uintptr_t'。 – 2011-03-09 15:18:20

+0

@Chris,在技術上這是每個標準的可選類型,但可能在任何體面的環境中都可用。或者你可以使用'float *'讓你的生活變得更簡單:-) – paxdiablo 2011-03-09 15:20:30

+0

指針的'printf'格式對輸出格式沒有太多的控制。 – 2011-03-09 15:25:33

2

是,指針的地址空間不能保證是相同的一個int。實際上,這段代碼給我在Mac Pro上使用gcc提供了以下編譯警告:

test.c:9:warning:從指針轉換爲不同大小的整數 test.c:11:警告:轉換爲指針來自不同大小的整數

和seg故障。我會考慮samplebias的代碼。 win7下的mingw32 +

1

是,代碼編譯\執行corrrectly

fl's address=2293572 
addr's contents = 3.14 

我認爲這是問題的MacOS只

0

的問題是int大小。正如@paxdiablo所說,不能保證int的大小足以保存與指針相同的值。改爲嘗試long long,但要注意,代碼保留在未定義的行爲一角。

+0

不,不要試圖猜測將指針轉換爲整數的類型,*如果必須*。 'uintptr_t'是爲此做的。如果這在平臺上不存在,這是一個強烈的跡象表明你絕對不應該嘗試它。 – 2011-03-09 15:24:37

+0

@Jens - 指針轉換爲整數通常是安全的。這是(我相信)導致OP的段錯誤的轉換。 – 2011-03-09 15:29:54

+0

@Chris,通常,信息丟失處於轉換爲整數類型的位置。對我來說,分段錯誤只是一個症狀,原因是重要字節的丟失。 – 2011-03-09 15:40:01