【问题标题】:Incorrect multiplication of integers in CC中的整数乘法不正确
【发布时间】:2017-11-22 08:38:24
【问题描述】:

Simulink 中的 C 编码 S-Function 显示不正确的行为,我已设法将问题缩小到整数乘法不正确。

在代码的开头,我有类似的内容:

#define NRBF       21
#define NRBF1  NRBF+1

然后,在脚本中的一个函数中:

void function_name(SimStruct *S, const int_T a)
{
...
    int_T base;
    base = a*NRBF1;
    printf("%i\t", a);
    printf("%i\t", NRBF1);
    printf("%i\n", base);
..
}

现在,如果a=0NRBF=21,我有(而不是base=0

0  22  1

如果a=1NRBF=21,我有(如预期的base=22

1  22  22

如果a=2NRBF=21,我有(而不是base=44

2  22  43 

现在,我必须说我有点困惑。我试图将乘法的行更改为

base = a* (int_T)NRBF1;

但这并不能解决问题。

任何帮助将不胜感激!谢谢!

【问题讨论】:

标签: c c-preprocessor


【解决方案1】:

问题出在这里:

您可以这样定义宏:

#define NRBF       21
#define NRBF1  NRBF+1

当你写这个时:

base = a*NRBF1;

预处理器在文本上将NRBF1 替换为21+1,结果如下:

base = a*21+1;

但你的本意是:

base = a*(21+1);

因此你需要像这样定义你的宏:

#define NRBF1  (NRBF+1)

【讨论】:

  • 非常感谢!你是绝对正确的。我真傻。
【解决方案2】:

随着宏的展开,该行如下所示:

base = a*NRBF+1;
  • a 等于 0,表达式为 0 * 21 + 1,即 1。
  • a 等于 2,表达式为 2 * 21 + 1,即 43。

解决方法是在宏定义中加括号:

#define NRBF1 (NRBF + 1)

对于任何以表达式为右手边的宏来说,这是一个很好的规则。

请记住,宏只是被文本替换到代码中。

【讨论】:

  • 表达式结果为43,如果a等于2
  • @mch 谢谢,已更正。咖啡前的小整数运算对我来说什么都不是。
  • 非常感谢您的回答!完全正确!
【解决方案3】:

基本算好了

0*21+1 = 1

宏已展开,但* 优先于+。这就是发生这种情况的原因。

更详细的解释是

#define NRBF       21
#define NRBF1  NRBF+1

这是怎么回事

base = a*NRBF1;

base = a*NRBF+1

Now when a = 0 then base = 1
    when a = 1 then base = 21+1 ...so on.

正确的方法是用括号括起来。

#define NRBF1  (NRBF+1)

还有一些陷阱:

当你添加这样的宏时#define SQR(X) X*X

对于像这样的例子,如果相同的优先级运算符在 next 旁边,那么这将是有问题的。

int i = 100/SQR(10);

然后会展开为

int i = 100/10*10

现在相同的优先级运算符在这里从左到右执行。

所以它会导致i=100

解决方法相同#define SQR(X) (X*X)

同样,当传递像 SQR(i+1) 这样的表达式时,它会扩展为 i+1*i+1=2*i+1。所以更正确的是

#define SQR(X) ((X)*(X))

即使这样,如果您忘记一件事,您也无法避免几件事宏只是扩展 - 它什么都不做

你不能像这样使用宏

SQR(i++) 将扩展为 ((i++)*(i++))。因此,您将 i 增加了两次,这不是您的意思。此外,这将导致未定义的行为

【讨论】:

  • SQR(X) (X*X) 甚至SQR(X) ((X)*(X)) 问题有点棘手,因为X 可以是副作用表达式或函数,调用它两次可能会产生意想不到的结果。跨度>
  • @Jean-FrançoisFabre.: 是的,这就是为什么我要写它并将其放入以后的编辑中,否则它将被错误地解释
  • 看起来很像那里:stackoverflow.com/questions/3719150/…
  • @Jean-FrançoisFabre.:我在写。是的,当SQR(i++) 被扩展两次时会出现问题。
【解决方案4】:

定义不会创建单个值 22,而是表达式 21 + 1。我想知道如果您将第二个 #define 更改为,您的问题是否会消失 #define NBRF1 (NBRF + 1)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-02-24
    • 1970-01-01
    • 2020-06-12
    • 2015-10-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多