在 C 语言中,有许多常见的编程陷阱,即使是经验丰富的程序员也容易陷入其中:

  1. 混淆 "="(赋值运算符)与 "=="(等于运算符)
    例如:

    if (x = 1) { /* 错误! */ }
    

    for (x == 1; ... /* 错误! */ )
    

    正确的应该是:

    if (x == 1) { /* 正确。 */ }
    for (x = 1; ... /* 正确。 */ )
    
  2. 混淆表达式中的运算符优先级
    在不确定时,使用括号来强制运算符的优先级。使用一些额外的括号从来不会有坏处。

  3. 混淆结构体成员操作符
    如果 struct_val 是结构体,struct_ptr 是指向结构体的指针,那么:

    struct_val->myname  /* 错误 */
    struct_ptr.myname   /* 错误 */
    
  4. printf()scanf() 中使用错误的格式化代码
    例如,使用 %f 打印一个 int 类型的值,可能导致输出异常。

  5. 记住数组的实际基索引是 0,最终索引比声明的大小小 1
    例如:

    int data[20];
    ...
    for (x = 1; x <= 20; ++x)
    {
        printf("%d\n", data[x]);
    }
    

    x 为 20 时会给出无效的结果。由于 C 语言不进行边界检查,这个问题可能很难捕获。

  6. 混淆多维数组的语法
    如果 data[10][10] 是一个二维数组,那么:

    data[2][7]  /* 正确,选取数组中的元素 */
    

    然而:

    data[2, 7]  /* 错误,未标记为错误 */
    
  7. 混淆字符串和字符常量
    以下是一个字符串:

    "Y"
    

    与字符常量:

    'Y'
    

    在进行字符串与字符常量比较时,容易产生问题。

  8. 忘记字符串以空字符(\0)结束
    这意味着字符串总是比它存储的文本大一个字符。如果在逐字符创建字符串时,程序没有将空字符加到末尾,也会导致问题。

  9. 未分配足够的内存给字符串,或者如果使用了指针,完全没有为其分配内存

  10. 忽视库函数的返回值
    大多数库函数返回错误代码;虽然不需要检查每次调用 printf(),但在关键操作中不要忽视错误代码。

当然,忘记存储函数返回的值(当这是唯一获取该值的方式时)是非常低级的错误,但人们偶尔会犯这种错误。

  1. 有重复的库函数名称
    编译器通常不会捕获这种错误。

  2. 忘记为库函数指定头文件

  3. 在应该指定指针作为函数参数的地方指定了变量,反之亦然
    如果函数通过参数返回一个值,必须指定该参数为指针:

    myfunc( &myvar );
    

    以下是错误的:

    myfunc( myvar );
    

    记住,即使一个函数不返回值,它也可能需要一个指针作为参数,尽管作为规则,这不是一个好的编程实践。

  4. 使用嵌套的 ifelse 语句时混淆
    避免这个问题的最佳方法是始终使用大括号。避免复杂的 if 语句也很重要;如果有选择,使用 switch。即使是简单的 if 语句,使用 switch 也很有用,因为如果需要扩展结构时,它会更方便。

  5. 忘记分号(虽然编译器通常会捕获这个错误),或者在不应该有分号的地方加了一个分号(编译器通常不会捕获这个错误)
    例如:

    for (x = 1; x < 10; ++x);  /* 错误! */
    {
        printf("%d\n", x);  /* 不会打印任何东西 */
    }
    
  6. switch 语句中忘记 break 语句
    如前所述,忘记 break 会导致执行从一个 switch 子句流向下一个子句。

  7. 不小心混用签名和无符号值,或不同的数据类型
    这可能导致非常微妙的错误。特别需要注意的一点是将单字符变量声明为 unsigned char。许多 I/O 函数期望的是 unsigned int 类型的值,且无法正确标记 EOF。建议将函数参数强制转换为适当的类型,即使看似类型转换已经能够自动处理。

  8. 变量名混淆
    为了确保代码的可移植性,建议确保标识符的前六个字符是唯一的。

  9. 过于复杂和聪明的代码
    程序往往是棘手的,尽管它可能工作正常,但最终会被修改并迁移到不同的语言中。保持代码结构清晰,做简单直接的事情,除非这样做会带来无法接受的代价。

Last modified: Tuesday, 28 January 2025, 12:09 AM