十个常见的C(愚蠢)错误

有很多常见的C错误。 我把我认为是C程序员制作的最简单的东西放在一起。 这些通常是流行的C编程眼泪的来源,记住此页上的内容将使您的C编程时代有所光彩。

(1)由数学函数返回的关于域错误的值是实现定义的。

处理此类域错误的最佳方法是确保绝对不会发生。 例如,在求平方根之前测试正值。 假设当数字为负数时编译器将返回某个值是一个愚蠢的错误。

(2)字符类型的最小保证值为零。

这意味着要让实现的字符表现为有符号或无符号字符取决于实现。 要获得您的字符的最小值,请使用limits.h中定义的CHAR_MIN。


(3)副作用也很愚蠢

如果评估该表达式更改了变量并且新值可能影响表达式的结果,则在表达式中多次使用同一变量是不安全的。

在编写包含递增/递减运算符的长表达式或通过引用调用函数的表达式时要小心。

甚至x = x ++; 是不安全的。

(4)不要跳过优先级表。

人们在阅读入门书籍时通常会跳过优先顺序表,但有时它们可​​能会回来并用愚蠢的标签打您。 如果您错过==(和!=)的优先级比?:高,那么您可能会期望c =(1?0:1 == 1?0:1); 将值1分配给c。 您的推理可能是==左边的内容与其右边的内容相同,因此结果应为true,并且c为1。 这种推理当然很愚蠢。 优先级表显示该表达式的计算结果为c =(1?0:(1 == 1)?0:1); 首先评估内括号,然后从左到右评估c的值为0。

关联也很重要,例如,当++和*具有相同的优先级时,它们从右到左关联,这意味着* p ++将被评估为*(p ++)。

(5)始终使用函数原型。

如果不这样做,则假定它们采用默认类型int。 您可能会开始认为,如果您知道默认值,那么您应该能够假定它们而不必显式指定它们。 这些想法很愚蠢,应立即从头脑中消除。 如果尚未将任何函数参数都转换为期望的类型,则也将其转换为期望的类型。


(6)函数参数的求值顺序未定义。

这意味着


int a () {
  printf("a\n");
  return 1;
}
int b () {
  printf("b\n");
  return 2;
}
int c () {
  printf("c\n");
  return 3;
}
int sum (int a, int b, int c) {
  return a + b + c;
}
int main(int argc, char** argv) {
  printf("%d", sum(a(), b(), c()));
  return (EXIT_SUCCESS);
} 

唯一保证的输出是6(总和),而不是a,b或c的打印顺序。

(7)类型T的sizeof指针仅是一个T元素的大小。

特别是在


T arr[10];
T *p = arr; 
sizeof(* p)!= sizeof(arr)。 而是sizeof(arr)= 10 *一个T元素的大小,而sizeof(* p)只是一个T元素的大小。

sizeof的大小也是实现定义的,应该使用size_t(在stdlib.h中定义)或unsigned long来保存其值。

(8)main必须返回一个int。

您不会在程序中调用main,对吗? 那么谁叫它呢? 如果他正在呼叫主电源,他怎么知道您如何定义主电源? 答案很简单。 调用您的main的家伙假设您的main返回一个int。 通常,调用者将使用该返回值来确定程序的成功状态。 如果您不给他钱,他将得到垃圾,并将其用于芦苇跳舞,并使用返回的值进行表演。

(9)闭眼混合有符号和无符号类型。

声明无符号类型的人每次在其他类型的表达式中使用它时,都必须打醒自己。 确实,任何编写涉及混合类型的表达式的人都必须保持警惕。 关于地精潜伏在从表达式评估中收集位的程序周围的故事是真实的,不应被认为是愚蠢的。

(10)数组界限。 需要我多说?

如果您的任何函数将数组作为参数,则也要传递该数组的长度。 避免在不占用数组长度的情况下接受数组的任何函数。 特别是永远不要使用gets()。

From: https://bytes.com/topic/c/insights/851424-ten-common-c-silly-mistakes

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值