问题表达式

2023-12-19 20:58:22

问题表达式





一. 概述

??表达式的求值部分由操作符的优先级决定。但有时会由于编码的不规范,会导致表达式执行顺序混乱,出现问题。以下对于一些情况进行举例。


二. 例题

1. 例子一

a*b + c*d + e*f

例子一在计算的时候,由于*比+的优先级高,只能保证,*的计算是比+早,但是优先级并不
能决定第三个*比第一个+早执行。

所以表达式执行顺序可能是:((a*b) + (c*d)) + (e*f) 或者是:((a*b) + (c*d) + (e*f))


2. 例子二

c + --c

同上,操作符的优先级只能决定自减–的运算在+的运算的前面,但是我们并没有办法得
知,+操作符的左操作数的获取在右操作数之前还是之后求值,所以结果是不可预测的,是有歧义的。

假设c为2时,表达式可能是2+1也可能是1+1


3. 例子三

int main()
{
 int i = 10;
 i = i-- - --i * ( i = -3 ) * i++ + ++i;
 printf("i = %d\n", i);
 return 0;
} 

非法表达式程序的结果:

编译器
—128Tandy 6000 Xenix 3.2
—95Think C 5.02(Macintosh)
—86IBM PowerPC AIX 3.2.5
—85Sun Sparc cc(K&C编译器)
—63gcc,HP_UX 9.0,Power C 2.0.0
4Sun Sparc acc(K&C编译器)
21Turbo C/C++ 4.5
22FreeBSD 2.1 R
30Dec Alpha OSF1 2.0
36Dec VAX/VMS
42Microsoft C 5.1

这段非法表达式在不同的编译器中,会有不同结果,这是极其危险的。


4. 例子四

#include<stdio.h>
int fun()
{
    static int count = 1;
    return ++count;
}
int main()
{
    int answer;
    answer = fun() - fun() * fun();
    printf("%d\n", answer);//输出多少?
    return 0;
}

因为count在创建的时候用static修饰过,所以每次调用后不会销毁。这时结果依然无法预测的,虽然在大多数的编译器上求得结果都是相同的。但是上述代码 answer = fun() - fun() * fun(); 中我们只能通过操作符的优先级得知:先算乘法,再算减法。函数的调用先后顺序无法通过操作符的优先级确定。

所以,可能是2-3*4也可能是4-2*3。


三. 分析

代码如下:

#include <stdio.h>
int main()
{
	int i = 1;
	int ret = (++i) + (++i) + (++i);
	printf("%d\n", ret);
	printf("%d\n", i);
	return 0;
}

  1. 直接f10上反汇编

在这里插入图片描述


  1. 这里的i的地址与ebp-8地址相同,所以这里的意思就是把1放到i里面。

在这里插入图片描述

在这里插入图片描述


  1. 下图第一行,将ebp-8的值放到eax中,也就是说eax现在值为1。下图第二行,将eax增加1,现在eax值为2。下图第三行,将eax的值放到ebp-8中,现在ebp-8的值是2,所以i的值是2。由此可见这三行完成的是++i。

在这里插入图片描述

此时监听到的值:

在这里插入图片描述


  1. 同上,又完成了一次++i操作。这次用到的寄存器是ecx。

在这里插入图片描述

此时监听到的值:

在这里插入图片描述


  1. 同上,又完成了一次++i操作。这次用到的寄存器是edx。

在这里插入图片描述

此时监听到的值:

在这里插入图片描述


  1. 将ebp-8的值赋给eax。

在这里插入图片描述

此时监听到的值:

在这里插入图片描述


  1. 两次加法

在这里插入图片描述

此时监听到的值:

在这里插入图片描述

在这里插入图片描述


  1. 将最后的算出的值放到ret中。

在这里插入图片描述

此时监听到的值:

在这里插入图片描述


  1. 由此可见,在vs2019编译器中的算法是4+4+4,最后得出12。此处也可对gcc编译器中算法进行一个猜测,即3+3+4。
    vs2019运行结果:

在这里插入图片描述

gcc运行结果:

在这里插入图片描述


四. 总结

??我们写出的表达式如果不能通过操作符的属性确定唯一的计算路径,那这个表达式就是存在问题的。



本篇博客为本人学习C语言时的详细笔记,如有错误之处,还望各位指正。
文章为原创,如要转载请注明出处

文章来源:https://blog.csdn.net/m0_59188912/article/details/135083672
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。