是否可以在 C 中使用带有 char 迭代器的 FOR 循环?
Posted
技术标签:
【中文标题】是否可以在 C 中使用带有 char 迭代器的 FOR 循环?【英文标题】:Are FOR loops with char iterators in C possible? 【发布时间】:2016-05-06 01:11:06 【问题描述】:我在使用 unsigned char 作为迭代器时遇到问题。使用以下代码会导致卡在 FOR 循环中。 The output looks like this.
unsigned char i;
char * arr;
int * freq;
arr = (char *)(malloc(256*sizeof(char)));
freq = (int *)(malloc(256*sizeof(int)));
for (i=0; i<=255;i++)
arr[i]=i;
freq[i]=0;
printf("%c",i);
我的问题是为什么会这样?是因为使用 unsigned char 作为迭代器吗?
【问题讨论】:
因为unsigned char i
不能保存大于 255 的值。i<=255
始终为真。
不要将malloc
和朋友的结果投射到 C 中!并且sizefo(char)
被定义 以产生1
。明确写出来是没有用的。
此外,使用 char 作为迭代器不太可能更“高效”,您不妨使用整数。不过我可能是错的
@aidan.plenert.macdonald:数组上的interator的正确类型是size_t
(无符号)。或者,如果保证值是 <= SIZE_MAX
,则可以使用 unsigned int
。
@chux: 255
是标准要求的最小最大值(!)值。没有任何声明 unsigned char
不能容纳更大的值。
【参考方案1】:
i <= 255
如果i
是unsigned char
类型并且该类型在您的平台上是8 位的(很可能是),那么表达式将始终是true
,并且您有一个无限循环。不过,这是定义明确的行为。 unsigned char
将简单地环绕,一旦达到 255,它的值将再次从 0 开始。
解决办法当然很简单:将i
的类型改为int
。
为避免将来出现此类意外,请务必打开编译器的警告。如果我用 GCC 编译虚假循环并将 -Wall
和 -Wextra
标志传递给它,它会告诉我这一点。
main.c: In function ‘main’:
main.c:5:17: warning: comparison is always true due to limited range of data type [-Wtype-limits]
for (i = 0; i <= 255; ++i)
^
【讨论】:
正确的类型是size_t
。
对于一般数组大小,是的。但标准保证 int
将能够保存高达 2^15 – 1 的值,因此在这种情况下会很好。
如何开启编译器的警告?
@MASh 如果您使用的是 GCC 或 Clang,请使用答案中提到的标志。对于其他编译器,请查阅他们的文档。【参考方案2】:
因为你的条件是i <= 255
,所以当i
变成255
,就会加一。 您的机器上unsigned char
的最大范围是[0,255],所以它再次回绕到零。所以循环,永远持续下去。
这个问题被称为算术或integer overflow
【讨论】:
我会写“无符号字符的最大范围是 [0,255] [在你的机器上]”。重点补充。unsigned char
是至少 8 位,最多不是。【参考方案3】:
for 循环执行以下操作:它执行初始化。然后它检查循环条件。如果循环条件为真,则执行循环,然后执行增量表达式。然后它再次检查循环条件。这字面意思就是它的作用。
当 i = 255 并执行 i++ 时,编译器尝试将 i 设置为 256,但由于它是无符号字符且可能是 8 位,因此 256 被截断为零。然后循环条件 i 完全遵循您告诉它的操作,而不是您希望它执行的操作。
【讨论】:
小修正:编译器不会对变量的内容做任何事情。它只是生成代码。【参考方案4】:主要问题:由于unsigned char i
不能保存大于UCHAR_MAX
的值。 i<=255
总是正确的。 UCHAR_MAX
通常是 255,因为它肯定在 OP 的平台上,但可能更多。
其他说明:
使用数组索引时,最好使用size_t
。
不需要投射malloc()
结果。还要通过变量的大小而不是类型的大小来考虑倍数。 - IMO:更容易维护和正确编码。
避免幻数 256、255 浮动。
#define N 256
size_t i;
char * arr;
int * freq;
arr = malloc(sizeof *arr * N);
freq = malloc(sizeof *freq * N);
for (i=0; i<N;i++)
arr[i]=i;
freq[i]=0;
printf("%c",i);
【讨论】:
@Olaf 不是那么古怪的符号? ^^我只是记得标准中是怎么表达的,所以就用了。以上是关于是否可以在 C 中使用带有 char 迭代器的 FOR 循环?的主要内容,如果未能解决你的问题,请参考以下文章