代码之家  ›  专栏  ›  技术社区  ›  Aillyn

从管理的OO语言学习C

  •  6
  • Aillyn  · 技术社区  · 15 年前

    我很喜欢用Java和C语言编写代码,但是我需要使用C来进行一个项目(因为操作系统API调用级别低),而且我处理指针和内存管理遇到了一些困难(如图所示)。 here )

    现在,我基本上是在输入代码并将其提供给编译器以查看它是否工作。这对我来说是不合适的。有人能给我指出好的资源,让我理解来自托管语言的指针和内存管理吗?

    5 回复  |  直到 15 年前
        1
  •  5
  •   cobbal    15 年前
        2
  •  3
  •   Jens Gustedt    15 年前

    你已经找到了一个很好的资源,所以。

    当然,您正在编译,所有警告都打开了,是吗?

    通过做来学习在很大程度上取决于编译器的质量和它提供给您的警告/错误。在这方面,我在Linux/POSIX世界中发现的最好之处是 clang . 很好地跟踪错误的来源,并很好地告诉您丢失的头文件。

        3
  •  1
  •   mikek3332002    15 年前

    一些提示:

    • 默认情况下,变量存储在堆栈中。
    • 变量按值传递给函数
    • 为了分配和释放内存,请遵循相同的过程。例如,在同一功能中分配和释放
    • C等价于

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

    int *p;
    
    p=malloc(sizeof(int));
    
    *p=5;
    
    • 内存分配(malloc)可能会失败,因此在使用指针之前,请检查它是否为空。
    • 操作系统功能可能会失败,这可以由返回值检测到。
        4
  •  1
  •   Burton Samograd    15 年前

    学习使用gdb单步执行代码并打印变量值(使用-g编译以启用调试符号)。

    使用valgrind检查内存泄漏和其他相关问题(如堆损坏)。

        5
  •  1
  •   nategoose    15 年前

    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
    

    尽量使代码看起来像这样会有所帮助,尽管这并不总是可能的。

    制作一组宏或内联函数来初始化对象是一个好主意。还可以创建另一组函数来分配对象的内存并将其传递给初始值设定项函数。这允许轻松初始化本地和动态分配的对象。类似于析构函数的操作也是一个好主意。

    在许多情况下,使用OO技术是很好的实践,而在C中这样做只需要多一点类型(但允许更多的控制)。如果可以保持接口不变,则推杆、getter和其他助手函数可以帮助保持对象处于一致状态,并减少在发现错误时必须进行的更改。

    你也应该看看 perror 函数和 errno “可变”。

    通常,你希望避免在C中使用类似的异常。我通常也试图避免在C++中使用它们,而只使用它们来处理非常糟糕的错误——那些不应该发生的错误。避免它们的一个主要原因是在C中没有神奇地进行析构函数调用,因此非本地goto经常会泄漏(或以其他方式搞砸)某种类型的资源。也就是说,在C中有一些东西提供了类似的功能。

    C中的主要异常机制是 setjmp longjmp 功能。 塞特姆 从代码中的一个位置调用,并传递一个(不透明)变量(jmp_buf),该变量稍后可以传递给 朗吉姆普 . 当一个电话 朗吉姆普 它不会实际返回到调用方,而是按以前调用的方式返回 塞特姆 和那个jmp-buf。 塞特姆 将返回由调用指定的值 朗吉姆普 . 定期呼叫 塞特姆 返回0。

    其他类似于异常的功能更特定于平台,但包括信号(它们有自己的gotchas)。

    其他需要注意的是:

    这个 assert 宏,可用于在参数(某种逻辑测试)失败时导致程序退出。呼叫 断言 当你离开的时候 #define NDEBUG 在你之前 #include <assert.h> ,因此在测试之后,您可以轻松地删除断言。这对于在取消引用前测试空指针以及其他几个条件非常有用。如果条件失败 断言 尝试打印失败测试的源文件名和行号。

    这个 abort 函数使程序退出时失败,而不执行调用的所有清除操作 exit 做。这可以通过一些平台上的信号来完成。 断言 电话 中止 .