2010-09-22 61 views
6

我對Java和C#等語言的編程相當舒服,但我需要將C用於一個項目(由於低級別的OS API調用),我在處理指針和內存管理(看到here學習C來自託管面向對象的語言

現在我基本上是輸入代碼,並將其提供給編譯器,看看它是否工作。這對我來說並不合適。任何人都可以指點我,讓我理解來自託管語言的指針和內存管理嗎?

+5

當我工作的c - 這是很多年以前,對於C我最喜歡的參考 - Kernighan的裏奇 - http://www.amazon.com/gp/product/images/0131103628/ref=dp_image_0?ie=UTF8&n = 283155&s =書籍 – InSane 2010-09-22 04:44:04

+1

歡迎來到真棒世界。準備前所未有的性能和靈活性! – 2010-09-22 04:47:11

+0

我和你一樣,除了用Python和C++替換Java和C#。我已經通過檢查我們在Subversion中的代碼來處理它,並在我等待Richie的「C程序設計語言」副本到達時重新閱讀指針部分並在我的C++書籍中進行強制轉換。 – xnine 2010-09-22 04:53:34

回答

3

一個你已經找到好資源,SO。

當然,您正在編譯所有警告,不是嗎?

在做學習很大程度上取決於編譯器的質量和他提供的警告/錯誤。我在linux/POSIX世界中找到的最好的方面是clang。很好地追蹤錯誤的來源,並很好地告訴你關於丟失的頭文件。

+0

++用於「編譯所有警告」。 – AlcubierreDrive 2010-09-22 06:10:28

1

一些提示:

  • 默認情況下可變因素都存儲在堆棧中。
  • Varibles按值傳入函數
  • 堅持分配和釋放內存的相同過程。例如分配和釋放在相同功能
  • C'S等效的

    Integer i = new Integer(); 
    
    i=5; 
    

int *p; 

p=malloc(sizeof(int)); 

*p=5; 
  • 內存分配(malloc的)可能會失敗,因此檢查空指針在使用它之前。
  • OS功能可能會失敗,並且可以通過返回值檢測到。
1

學習如何使用gdb來遍歷代碼並打印變量值(使用-g編譯以啓用調試符號)。

使用valgrind檢查內存泄漏和其他相關問題(如堆損壞)。

1

C語言不會做任何你沒有明確告訴它做的事情。

沒有自動調用你的析構函數,這既好又壞(因爲析構函數中的錯誤可能是一種痛苦)。

獲得某種程度上自動析構函數行爲的一種簡單方法是使用範圍來構造和銷燬事物。這可能會變得很難看,因爲嵌套示波器將事物進一步向右移動。

if (var = malloc(SIZE)) { // try to keep this line 
    use_var(var); 
    free(var); // and this line close and with easy to comprehend code between them 
} else { 
    error_action(); 
} 
return; // try to limit the number of return statements so that you can ensure resources 
     // are freed for all code paths 

試圖儘可能地讓你的代碼看起來像這樣會有所幫助,儘管這並不總是可能的。

製作一組初始化對象宏或內聯函數是一個好主意。另外創建另一組函數來分配對象的內存並將其傳遞給初始化函數。這允許輕鬆地初始化本地和動態分配的對象。對類似析構函數類似的操作也是一個好主意。

使用面向對象技術在許多情況下很好的做法,並用C這樣做只是需要多一點點的打字(但允許更多的控制)。如果可以保持界面相同,則Putters,getters和其他幫助函數可以幫助保持對象處於一致狀態,並減少發現錯誤時必須進行的更改。

您還應該查看perror函數和errno「變量」。

通常你會希望避免使用類似的東西在C例外,我一般儘量避免它們C++爲好,只用它們來非常糟糕的錯誤 - 這是不應該發生的。避免這些問題的主要原因之一是,C中不存在任何析構函數調用,因此非本地GOTO經常會泄漏(或以其他方式搞砸)某種類型的資源。這就是說,C中有些東西提供了類似的功能。

主要的例外類似於C機構是setjmplongjmp功能。 setjmp從代碼中的一個位置被調用,並傳遞一個(不透明)變量(jmp_buf),該變量稍後可傳遞給longjmp。當撥打電話longjmp時,它實際上不會返回給調用者,但是會返回到之前調用setjmp與該jmp_buf。 setjmp將返回由longjmp調用指定的值。到setjmp回報定期拜訪0

類似功能的其他的例外是更具體的平臺,但包括信號(其中有自己的陷阱)。

其他要考慮有:

assert宏,它可以用來使程序退出時的參數(某種形式的邏輯測試)失敗。撥打電話assert當你#define NDEBUG之前你#include <assert.h>走開,所以經過測試,你可以很容易地刪除斷言。這對於在解引用它們之前測試NULL指針以及其他一些條件非常有用。如果條件失敗,assert將嘗試打印失敗測試的源文件名和行號。

abort函數會導致程序退出失敗,但不會執行所有調用exit的清理操作。這可以在某些平臺上用信號完成。 assert致電abort