标题: C语言运算符优先级问题 [打印本页]

作者: lei848200    时间: 2023-11-7 23:01
标题: C语言运算符优先级问题

程序排查错误过程中发现tx=0,思考半天包括查运算符优先级也没搞明白为啥tx会是0,特来请教。

  1. #include <stdio.h>

  2. int main()
  3. {
  4.         float k=364.4;
  5.         float belta=2;
  6.         unsigned int tx;
  7.         tx=(unsigned int) -k*belta;
  8.    printf("tx= %d  \n",tx);
  9.    return 0;
  10. }
复制代码




作者: Y_G_G    时间: 2023-11-7 23:47
我到现在都还没有能完全记住C的运算优先等级,有事没事就是括号!
作者: Hephaestus    时间: 2023-11-8 01:10
我用MinGW验证了一下,结果是-512,所以根本就不是什么优先级的问题,而是不同类型格式转换的问题。
作者: npn    时间: 2023-11-8 08:10
你要搞清楚是多少位的编译器,不同的数据类型位宽可能不一样。
作者: 200404    时间: 2023-11-8 09:11
如果您在程序排查过程中发现了一个变量的值为0,那么可能有多种原因导致了这种情况。可能是您的代码将该变量初始化为0,也可能是您的代码在某个地方将该变量的值修改为0。以下是一些可能导致变量值为0的情况:  变量初始化:在很多编程语言中声明的变量默认为0. 如果在声明变量时未给定任何初始值,则该变量将被初始化为0。  赋值为0:如果变量在代码的某个位置被显式地赋值为0,则该变量的值将会变为0. 如果tx被赋值为0,会导致tx=0.  程序中的错误:tx被连续多次运算可能导致变量的值为0. 可以通过调试程序并添加日志来确定变量值为0的实际原因。  运算符优先级:如果tx变量是由某个表达式计算得出的,则可能是由于运算符的优先级错误,导致tx的计算结果为0. 可以检查代码的计算表达式是否含有错误的优先级,以及各个操作数是否正确。
作者: 200404    时间: 2023-11-8 09:12
如果您在程序排查过程中发现了一个变量的值为0,那么可能有多种原因导致了这种情况。可能是您的代码将该变量初始化为0,也可能是您的代码在某个地方将该变量的值修改为0。以下是一些可能导致变量值为0的情况:

变量初始化:在很多编程语言中声明的变量默认为0. 如果在声明变量时未给定任何初始值,则该变量将被初始化为0。

赋值为0:如果变量在代码的某个位置被显式地赋值为0,则该变量的值将会变为0. 如果tx被赋值为0,会导致tx=0.

程序中的错误:tx被连续多次运算可能导致变量的值为0. 可以通过调试程序并添加日志来确定变量值为0的实际原因。

运算符优先级:如果tx变量是由某个表达式计算得出的,则可能是由于运算符的优先级错误,导致tx的计算结果为0. 可以检查代码的计算表达式是否含有错误的优先级,以及各个操作数是否正确。

作者: 1600277881    时间: 2023-11-8 11:16
tx=(unsigned int) ((float)-k*belta);
作者: lei848200    时间: 2023-11-8 12:41
npn 发表于 2023-11-8 08:10
你要搞清楚是多少位的编译器,不同的数据类型位宽可能不一样。

keil 5.32   stm32运行结果是0.
作者: Hephaestus    时间: 2023-11-8 13:54
lei848200 发表于 2023-11-8 12:41
keil 5.32   stm32运行结果是0.

那么就可能是优化掉了,编译器认为你的代码没用,实际上未生成有效机器码。
作者: pdwdzz    时间: 2023-11-8 22:37
ARM平台的C语言是不支持吧负数浮点强制转换成无符号类型的。
作者: cnos    时间: 2023-11-9 09:56
我并没有发现什么问题。tx并不是0




作者: aayon1979    时间: 2023-11-9 10:30
最简单的方法就是带括号,而且不出错
作者: ppcbug    时间: 2023-11-9 14:35
KEIL 5 , ARM 版本 实际运行结果 :
void tttt(void)
{
        float k=364.4;
        float belta=2;
        unsigned int tx;
        tx=(unsigned int) -k*belta;
   DebugOut("tx= %d",tx);

}
结果:
=======  Ready.  =======
tx= 728

我怀疑是 你的编译器 配置 【禁止】 浮点 计算, 所以导致 所有浮点数 都视为0.

作者: gwa    时间: 2023-11-9 15:59
一个是输出类型是整型的,还有一个    tx=(unsigned int) (-k*belta);然后输出
作者: 会飞的鱼KKK    时间: 2023-11-10 16:15
tx定义的是无符号的整型,后面计算结果是负的,强制类型转换把负的转成了无符号整型0
作者: chxelc    时间: 2023-11-10 17:10
Y_G_G 发表于 2023-11-7 23:47
我到现在都还没有能完全记住C的运算优先等级,有事没事就是括号!

俺也一样
作者: pdwdzz    时间: 2023-11-12 15:04
cnos 发表于 2023-11-9 09:56
我并没有发现什么问题。tx并不是0

ARM平台的问题,X86,C51是可以的。
作者: Hephaestus    时间: 2023-11-12 20:31
pdwdzz 发表于 2023-11-12 15:04
ARM平台的问题,X86,C51是可以的。

ARM平台不知道比51高到哪里去了,怎么可能会有这种低级错误。
作者: pdwdzz    时间: 2023-11-12 22:31
Hephaestus 发表于 2023-11-12 20:31
ARM平台不知道比51高到哪里去了,怎么可能会有这种低级错误。

这又不是什么bug,一个编译器特性而已。ARM的编译器是不能直接吧负浮点数转无符号的,官方文档有说明的。
作者: coody_sz    时间: 2023-11-13 11:30
不要吝啬括号。
作者: 3038838599    时间: 2023-11-13 17:47
coody_sz 发表于 2023-11-13 11:30
不要吝啬括号。

我在VS2020试过了,为什么加括号就可以呢?
加括号改变了什么,把flaot类型转换成int或者unsigned int 类型了吗?
作者: 3038838599    时间: 2023-11-13 17:49
Hephaestus 发表于 2023-11-8 01:10
我用MinGW验证了一下,结果是-512,所以根本就不是什么优先级的问题,而是不同类型格式转换的问题。

那为什么是加了括号就正常了呢?
tx=(unsigned int) (-k*belta);
作者: 大漠落日    时间: 2023-11-15 10:48
加上万能的括号,完工
作者: Hephaestus    时间: 2023-11-15 22:03
pdwdzz 发表于 2023-11-12 22:31
这又不是什么bug,一个编译器特性而已。ARM的编译器是不能直接吧负浮点数转无符号的,官方文档有说明的。

我用RVMDK试了一下,不支持你的说法,这是从哪个文档看来的?
作者: 3038838599    时间: 2023-11-20 20:13
我想说一下这确实是运算符优先级的问题,强制类型转换也是一个运算符,所以先强制类型转换-K,再算*belta
作者: suncat0504    时间: 2023-11-20 22:54
好家伙,硬要把负的浮点数据转换为无符号整形,那结果不是0还是啥数据?
作者: suncat0504    时间: 2023-11-20 22:55
无符号数据是从0开始的,负的数据咋转换成无符号数呢?
作者: Hephaestus    时间: 2023-11-21 14:05
suncat0504 发表于 2023-11-20 22:54
好家伙,硬要把负的浮点数据转换为无符号整形,那结果不是0还是啥数据?

你亲自验证一下,不要拍脑袋乱说。
作者: Hephaestus    时间: 2023-11-21 14:06
suncat0504 发表于 2023-11-20 22:55
无符号数据是从0开始的,负的数据咋转换成无符号数呢?

65535+1=0
这又是怎么回事???




欢迎光临 (http://www.51hei.com/bbs/) Powered by Discuz! X3.1