• C语言细节笔记2


    C语言常见问题笔记:
        1. 指针的声明
         char * p1, p2;
      p1 是一个指向char类型的指针,而p2是一个char类型变量
      这是由于 * 并不是基本类型的一部分,而是包含被声明标识符的声明符的一部分。 
     
     2. 储存类型
         同一个静态函数或静态变量最好在所有的声明和定义出都包含(static)
      extern 作为一个格式上的提示,表明函数的定义可能出现在另一个源文件中
      关健字auto毫无用处,已经过时了
      
     3. 在一个文件中定义了一个extern数组,但在另一个文件中无法通过sizeof取到这个数
     组的大小。这是由于sizeof是在编译时产生作用,它不能获得在另一个文件中的数组大小
     
     4. 如何在一个文件中获得另一个文件中定义的数组的大小
         1. 在定义数组的文件中声明,定义,并初始化一个变量,保存数组的大小
      2. 使用define为数组定义一个确定的可见的长度
      3. 在数组后面加入一个元素作为哨兵值,(通常为 0,-1,NULL)
      
     5. 实现抽象数据类型时,让用户使用指向没有公开定义(也许还隐藏在类型定义后边)的
     结构类型的指针。客户使用结构指针(及调用输入和返回结构指针的函数)而不知道结构的
     成员是什么。
     
     6. 通常对结构进行传递和返回时,使用结构指针而非结构,这是由于当结构作为函数参数
     传递时,通常会把整个结构都推进栈,需要多少空间就使用多少空间,为了避免这个代价,
     经常使用指针而不是结构。
     
     7. 使用sizeof返回值大于结构的期望值,这可能是由于尾部填充,也可能是内部填充。
     
     8. 空指针不会指向任何地方,它不是任何对象或函数的地址,取地址操作符&永远也不会
     但会空指针。malloc函数调用失败会返回空指针,这是空指针的典型用法,表示未分配或
     尚未指向任何地方的特殊指针值。空指针并不等同于为初始化的指针,未初始化的指针可
     能指向任何地方。每种类型都有一个空指针,而不同类型的空指针的内部表示可能不尽相
     同。
     
     9. 使用未初始化的指针是非法的,因为此时不知道指针指向何处,且未初始化,通常包括
     垃圾信息,所以甚至都不能保证该指针是一个空指针
     int * p;
     scanf("%d", p);
     
     10. 声明一个指针变量时,编译器只分配了足够容纳指针本身的内存,并没有分配任何让
     指针指向的内存。
     
     11. 使用malloc动态分配内存后,如果再使用realloc来改动动态分配的内存大小,则使
     用malloc之后,realloc之前,指向该动态内存的指针的值也需要改变,这是因为realloc
     并不一定能在原地扩大内存区域,如果它必须到内存中其它地方找寻足够大的内存,则它
     会返回一个不同的指针,而原有的指针值就变为不可用的
     int * p, * q;
     p = (int *)malloc(LEN * sizeof(int));
     q = p;
     p = (int *)realloc((void *)p, LEN_MAX * sizeof(int));
     此时q指向的内存可能非法。
     
     12. 在C语言中,sizeof('a')的值不是sizeof(char),这是由于在C语言中,字符常量是int
     型,所以sizeof('a')的值是sizeof(int),这正是C语言与C++的一个不同的地方
      int main(void)
      {
       printf("%d ", (int)sizeof('a'));  // 输出结果为4
       
       return 0;
      }
     
     13. 作为一般规则
      a.将宏定义,结构 联合 枚举声明,typedef声明,外部函数声明,全局变量声明,放入 .h 的
      文件中。
      b.永远不要把外部函数原型放到 .c文件中。
      c.如果定义或声明为一个源文件私有,则最好留在该文件中,作用域限于单文件的私有函数和
      变量应该声明为static
      d.不能把实际的代码,如函数体,或全局变量定义,即定义和初始化实例放入头文件中。
      e.当用多个文件创建一个项目时,应单独编译每个文件,即使用特定的编译选项,只进行编译,
      然后再将生成的目标文件链接起来。
     
     14. 在C语言中,只有输入例程试图读取并失败之后才能得到EOF,通常C语言只要检查输入例程的返
     回值。
     while (!feof(infp))
     {
         fgets(buf, MAXLINE, infp);
         fputs(buf, outfp);
     }
     这些代码会把文件的最后一行复制两遍,就是上述的原因
     一般来说可以不使用feof,偶尔使用foef或ferror在stdio调用返回EOF或NULL之后判断是文件结束
     条件还是文件读取错误。
     上述代码可改为
     while (fgets(buf, MAXLINE, infp) != NULL)
         puts(buf, outfp);
      
     15. printf实现可变域宽度
     printf("%*d", width, x);
     格式说明符中的星号表示参数列表中的一个int值表示域宽度
     
     16. 作为一个一般性的规则,不能混用scanf和gets或任何其他输入例程的调用,scanf对换行符的
     特殊处理几乎一定会带来问题。要么就用scanf处理所有的输入,要么不用
     int n;
     char str[10];
     scanf("%d", &n);
     gets(str);
     上述代码中的gets读取到的只是一个换行符,甚至程序不会给你输入字符串的机会
     
     17. C语言的函数总是接收参数的副本,因此函数永远不能通过向参数赋值返回任何东西

  • 相关阅读:
    [LeetCode] Word Ladder II
    [LeetCode] Edit Distance
    [LeetCode] Merge Intervals
    内存分配与Segmentation fault
    结构体 指针 数组
    resolv.conf
    无法启动xwindow
    stopping NetworkManager daemon failed
    linux 挂载光盘:mount: you must specify the filesystem type
    修改主机hostname
  • 原文地址:https://www.cnblogs.com/lnlin/p/6896598.html
Copyright © 2020-2023  润新知