• 函数内部返回一个局部变量的地址给调用者是不安全的。因为函数执行完毕,局部变量不存在了。虽然使用这个地址(或者变量)可能没有出现bug,那是因为这个变量的内存还没有被其他程序使用。只是被标记为空闲的内存了。
  • 返回全局变量的地址或者静态局部变量(static)的地址是安全的。因为他们都是存储在全局区,生命周期是全局的。
  • 返回传入的指针是推荐的
  • 返回函数内malloc的地址是安全的,但会造成问题。(什么问题暂时不知道)
  • 不要使用全局变量在函数间传递参数或结果
  • 使用全局变量和静态局部变量的函数是线程不安全
  • 预处理语句不是C语言的成分,,,所以宏的后面不加分号。他不是C的语句。宏定义里如果包含其他宏,那么也会替换。但注释不会被替换
    #define  PI  3.14 // 注释不会被替换,会被忽略
    #define  PRT  printf("%d", PI); \    //连接下一行的符号
                  printf("%d", 50)  // 这里不加分号,在使用PRT的时候加分号 
    
    void main()
    {
        PRT;
    }

     

  • 宏 可以有值(上面那样),也可以没有值,没有值是为了条件编译的,后面有其他的编译预处理指令来检查这个宏是否已经被定义过了。
  • 带参数的宏为了避免出现错误,保险的方法是每个参数加上括号,整个宏的值加上括号
    #define   SUM(x,y)  ((x) * (y) + (x))   //参数加括号避免运算结果错误,整个也要加括号

     

  • #include 就是把头文件内容原封不动插入到所在行。
  • 对于标准库里的函数如printf,如果源代码文件里忘记引入了stdio.h (对于自定义的函数也是一样,如果没有引入头文件或者没有声明函数原型而直接使用了自定义函数),编译也能通过,那是因为编译器会引入所有的标准库,并且编译器会猜测你使用的未声明的这个函数(标准库里的函数或者自定义的函数都是如此)参数是int类型,并且返回值也是int类型。如果恰好是这样,那么可以正常执行。如果类型不是int,那么执行的结果就是未知的。
  • 不对外公开的函数:在函数前面加上static,这个函数只能在所在编译单元(所在文件)中使用。在全局变量前加上static,这个变量只能在所在编译单元中使用。
  • #include 引入头文件在函数定义的文件中要写,在使用函数的地方也要写。在定义的地方写是为了让编译器去检查使用的函数的类型和定义的函数的类型是不是一致。
  • a.c 中有一个全局变量,b.c中想使用这个全局变量,需要在a.h (a.c的头文件)中声明这个全局变量  extern int globalVar; b.c中引入头文件a.h。然后就可以使用了。
  • int i;//这是定义变量   extern  int i;//这是声明
  • 变量多次声明在编译时会报错,简单的程序中自然不会出现这个情况。在复杂的程序中会出现。比如
    // a.c 
    #include  "a.h"
    
    int max (int a, int b)
    {
        return a>b ? a : b;
    }
    
    // a.h
    int max (int, int);
    
    // b.h
    #include "a.h"
    #include  "sum.h"   //
    
    // main.c
    #include "a.h"
    #include "b.h"  //因为b.h中还包括很多其他声明
    
    // 这时候max 声明就引入两次。会报错
    
    //解决方法 使用条件编译和宏
    
    // a.h
    
    #ifndef  _MAX_H_
    #define _MAX_H_
    int max (int, int);
    #endif
    View Code