C宏列表大小解析但不进入for循环

huangapple go评论62阅读模式
英文:

C Macro List size resolving but not entering for loop

问题

我有以下代码,当我尝试在for循环中使用 sizeof 列表 a 作为条件时,它不进入循环,但如果我硬编码它,它会进入循环。为什么会发生这种行为?

#include <limits.h>
#include <malloc.h>
#include <stdio.h>

#define MY_VAL (sizeof(a) / sizeof(a[0]))
#define MY_NEW_VAL 5

int a[] = {1, 2, 3, 4, 5, 6, 7};

int main() {
  int i;
  for (i = -1; i <= (MY_VAL - 2); i++) {
    printf("In loop 1\n");
  }
  for (i = -1; i <= MY_NEW_VAL; i++) {
    printf("In loop 2\n");
  }
}

输出 -->

In loop 2
In loop 2
In loop 2
In loop 2
In loop 2
In loop 2
In loop 2

我的编译器是 clang 版本 15.0.7,在 Linux 操作系统上运行。以防这是编译器特定的行为。

我知道这不是一个在实际应用中使用的东西,只是发现这种行为很奇怪。请解释。

这种行为发生的原因是 MY_VAL 的定义中存在一个问题。在宏定义 MY_VAL 中,你使用了 sizeof(a) / sizeof(a[0]) 来计算数组 a 的元素数量。然而,你在宏定义的末尾多了一个右括号 ),导致 MY_VAL 的值不是你预期的值。

要修复这个问题,只需删除 MY_VAL 定义中的多余右括号,如下所示:

#define MY_VAL (sizeof(a) / sizeof(a[0]))

这将允许 MY_VAL 正确计算数组 a 的元素数量,使第一个循环正常工作。然后,两个循环都将以正确的条件运行,输出预期的结果。修复后的代码如下:

#include <limits.h>
#include <malloc.h>
#include <stdio.h>

#define MY_VAL (sizeof(a) / sizeof(a[0]))
#define MY_NEW_VAL 5

int a[] = {1, 2, 3, 4, 5, 6, 7};

int main() {
  int i;
  for (i = -1; i <= (MY_VAL - 2); i++) {
    printf("In loop 1\n");
  }
  for (i = -1; i <= MY_NEW_VAL; i++) {
    printf("In loop 2\n");
  }
}
英文:

I have the following code and when I try to use the sizeof list a as a condition in for loop it does not enter it, but if I hard code it, it enters the loop. Why is this behaviour happening?

#include &lt;limits.h&gt;
#include &lt;malloc.h&gt;
#include &lt;stdio.h&gt;

#define MY_VAL (sizeof(a) / sizeof(a[0]))
#define MY_NEW_VAL 5

int a[] = {1, 2, 3, 4, 5, 6, 7};

int main() {
  int i;
  for (i = -1; i &lt;= (MY_VAL - 2); i++) {
    printf(&quot;In loop 1\n&quot;);
  }
  for (i = -1; i &lt;= MY_NEW_VAL; i++) {
    printf(&quot;In loop 2\n&quot;);
  }
}

output -->

In loop 2
In loop 2
In loop 2
In loop 2
In loop 2
In loop 2
In loop 2

My compiler is clang version 15.0.7, running linux as my os. Just in case this is a compiler specific behaviour.

I am aware this is not something to be used in a real world use case, just found this behaviour to be odd. Please explain.

答案1

得分: 7

sizeof 的类型是 size_t,它是无符号的,而你的 i 是有符号的。C 会将 i 转换为 size_t,这会使 -1 变成一个很大的正数,大于 MY_VAL - 2。所以循环永远不会运行。如果你启用了足够的警告,编译器会告诉你这个可能的问题。

另一方面,MY_NEW_VAL 的类型是从常量值派生的。对于这个小值,它是一个 int。所以那个可以工作。

如果你想从 -1 开始,你需要将限制变成有符号的:for (i = -1; i <= (int)MY_VAL - 2; i++)。然后它就可以工作了。

英文:

sizeof is of type size_t, which is unsigned, whereas your i is signed. C is converting i to a size_t, which makes the -1 a large positive number — greater than MY_VAL - 2. So the loop never runs. If you had had sufficient warnings enabled, the compiler would have told you about this possible problem.

MY_NEW_VAL on the other hand is of a type derived from the constant value. For this particular small value, it is an int. So that one works.

Since you want to start at -1, you need to make the limit signed: for (i = -1; i &lt;= (int)MY_VAL - 2; i++). Then it works.

huangapple
  • 本文由 发表于 2023年5月30日 00:26:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/76358910.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定