资讯专栏INFORMATION COLUMN

【带你刷系列】☝c陷阱与缺陷(一)

wpw / 3344人阅读

词法陷阱介绍

探讨符号和组成符号的字符间的关系,以及有关符号含义的一些常见误解

1 =不同于==

=:赋值操作符,将右操作数的值放到左操作数的空间里面。
==:关系操作符,用来比较左右两个数,若相等则为1,若不相等则为0。

  • 当 == 写成 = 的后果?

?栗子1:

if (x = y);//本来应该是x==ybreak;

写成这样意思就变成了将y的值放到x的空间里然后判断该值是否为0,这样就与我们原来的想法不一样了,所以程序运行结果就会跟我们想的不一样。

?栗子2:

while (c = " " || c == "/t" || c == "/n");c = gets(f);

因为 = 的优先级比 || 低,所以循环判断里面实际上是将表达式" " || c == "/t" || c == "/n"的值赋给了c,因为’ "不为0(ASCII值为32),所以" " || c == "/t" || c == "/n"的值始终为1,循环条件始终满足,结果导致程序死循环。

  • 当 = 写成 == 的后果?

?栗子1:

if ((filedesc == open(argv[i],0)) < 0)error();

在本例中如果函数open执行成功则返回0或者正数,如果执行失败将返回-1。这段代码是用来检测open函数是否执行成功。但是如果是 == 操作符,那么该表达式的值只有0和1两种可能(相等为1不等为0),条件始终都不会满足,所以就没有机会执行error函数,这个时候程序看上去没什么问题,但是执行的结果会跟我们设计的有偏差。

2 & 和 | 不同于 && 和 ||

1.运算符性质不同。

&是一个位运算符
&&是一个逻辑运算符

2.作用不同。

&是将两个二进制的数逐位相与,结果是相与之后的结果。
&&就是判断两个表达式的真假性,只有两个表达式同时为真才为真,有一个为假则为假,具有短路性质。

3.用途限制。

&除了是一个位运算符,也是取地址符。
&&就是一个单纯的逻辑运算符,没有任何其他含义。

?栗子1:

2 & 4;2 && 4;

分析:
2的二进制位:00000000000000000000000000000010
4的二进制位:00000000000000000000000000000100
&是位与操作符,每一位相与后结果为0。
&&是逻辑操作符,只要两边操作数都为真结果就为真,否则为0。

3 词法分析中的“贪心法”

什么叫“贪心法”:

每一个符号应该包含尽可能多的字符,也就是说编译器把程序分解为符号的方法是,从左到右一个字符一个字符的读入,如果该字符可能组成一个符号,那么再读入下一个字符,判断已经读入的两个字符组成的字符串是否可能是一个符号的组成部分,如果可能重复上述判断,直到读入的字符组成的字符串已不再可能组成一个有意义的符号,这个策略被称为“贪心法”

?举个栗子:

a---b;a -- - b;方法一a - -- b;方法二

结果是按方法一去进行计算的,编译器在读取—的时候先读取最左边的-,该字符可以组成一个符号,在读下一个字符,这时两个字符–仍然可以组成一个符号,再读最右边的字符发现此时三个字符不能组成一个符号,这个时候编译器就会把前两个字符作为一个符号,然后后面一个字符作为一个符号。

注意:如果/是为判断下一个字符而读入的第一个字符,而/后面跟着*,那么无论前后如何,这两个字符都被视作是符号/*,表示一段注释的开始。
在a =/* b中/是读入的第二个字符,由于在老版编译器有 =/这样的符号,所以这段代码会被编译器认为是 a =/ *b。

?栗子2:

y = x/*p;

这里/*被视作是一段注释的开始,编译器将不断读字符,直到遇到*/,所以这条语句的功能是将x的值赋给y,不会管后面的p。
如果我们需要这样计算可以写成y = x / (*p)。

4 整形常量问题

如果一个整形常量的第一个字符是0,那么该常量会被视作为八进制数。

?举个栗子:

#define _CRT_SECURE_NO_WARNINGS 1#include int main(){	int a = 10;	int b = 010;	printf("%d %d/n", a, b);	//printf("%d/n", 2 && 4);	return 0;}

结果:

这里的010被视作是八进制,所以结果是8。

5 字符与字符串问题

如果"yes"被写成了’yes’,编译器不会报错,但是运行结果会变得难以预料。

?举个栗子:

#define _CRT_SECURE_NO_WARNINGS 1#include int main(){	int a = "yes";	printf("%d/n", a);	return 0;}

结果:

大多数编译器会将’yes’视作为一个整数值,由’y’,‘e’,"s’所代表的的整数值按照特定编译器实现中定义的方式组合而成,所以最后的结果是我们不可预测的。

作者水平有限,若文章有任何问题欢迎私聊或留言,希望和大家一起学习进步!!!
创作不易,希望大家?支持下,谢谢大家?

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/118809.html

相关文章

  • 【手把手你刷好题】——29.从大到小输出(非力扣,作业)

    摘要:前言今天是刷题打卡第天加油啦。原题从大到小输出题目描述写代码将三个整数数按从大到小输出。 【前言】 今天是刷题打卡第29天! 加油啦。 原题:从大到小输出 题目描述: 写代码将三个整数数按从大到小输出。 示例: 输入:12 23 22输出:23 22 12 思路: 本题主要记住...

    不知名网友 评论0 收藏0
  • 【手把手你刷LeetCode】——15.剑指offer之不用加减乘除做加法(位运算)

    摘要:前言今天是力扣打卡第天天天做递归做烦了,换换脑子,嘿嘿。原题不用加减乘除做加法题目描述写一个函数,求两个整数之和,要求在函数体内不得使用四则运算符号。补码的优势加法减法可以统一处理只有加法器。 【前言】 今天是力扣打卡第15天! 天天做递归做烦了,换换脑子,嘿嘿。 原题: 不用加减...

    QLQ 评论0 收藏0
  • 【手把手你刷好题】——30.杨辉三角(作业)

    摘要:声明这里只是作业上面的内容,后续还会更新更好的方法。前言今天是刷题打卡第天芜湖,坚持一个月咯,蟹蟹大家的陪伴哈原题杨辉三角题目描述在屏幕上打印杨辉三角。 【声明】 这里只是作业上面的内容,后续还会更新更好的方法。  【前言】  今天是刷题打卡第30天! 芜湖,坚持一个月咯,蟹蟹大...

    不知名网友 评论0 收藏0
  • 【手把手你刷LeetCode】——11.二叉搜索树的范围和(DFS)

    摘要:大家简单看一下纯递归的解法原题二叉搜索树的范围和解法题目描述给定二叉搜索树的根结点,返回值位于范围之间的所有结点的值的和。 【前言】 今天是力扣打卡第11天! 感谢铁汁们的陪伴,一起加油鸭!! 在第9天的时候写过这道题的递归解题方法,其实DFS使用的解题思想就是递归,所以大同小异啦...

    HelKyle 评论0 收藏0
  • 【手把手你刷好题】——21.道笔试题(非力扣)

    摘要:前言今天是刷题打卡第天可能有铁汁会问,为什么变成刷好题,而不是刷了呢因为最近笔者遇到很多经典的笔试题,想着记录下来,方便大家和自己学习,所以今后笔者会在标题上注明是不是力扣题。 【前言】 今天是刷题打卡第21天! 可能有铁汁会问,为什么变成刷好题, 而不是刷LeetCode 了呢?因为...

    骞讳护 评论0 收藏0

发表评论

0条评论

wpw

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<