2010-09-22 58 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