是否可以在 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&lt;=255 始终为真。 不要将malloc 和朋友的结果投射到 C 中!并且sizefo(char)定义 以产生1。明确写出来是没有用的。 此外,使用 char 作为迭代器不太可能更“高效”,您不妨使用整数。不过我可能是错的 @aidan.plenert.macdonald:数组上的interator的正确类型是size_t(无符号)。或者,如果保证值是 &lt;= SIZE_MAX,则可以使用 unsigned int @chux: 255 是标准要求的最小最大值(!)值。没有任何声明 unsigned char 不能容纳更大的值。 【参考方案1】:
i <= 255

如果iunsigned 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 &lt;= 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&lt;=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 循环?的主要内容,如果未能解决你的问题,请参考以下文章

C ++中反向迭代器的非常奇怪的行为

For-Loop一个带有负迭代器的“空”向量?

是否可以在不创建特殊迭代器的情况下每次迭代步进不同的量?

foreach 循环是不是从字面上重写为带有迭代器的 for 循环? [复制]

使用带有 char * 的正则表达式迭代器

带有向量迭代器的程序中的分段错误