英文:
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 <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");
}
}
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 <= (int)MY_VAL - 2; i++)
. Then it works.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论