【问题标题】:For Loop conditionFor 循环条件
【发布时间】:2016-04-10 02:13:12
【问题描述】:
#include <stdio.h>
#define all_mem (sizeof(x) /sizeof(x[0]))
int x[] ={1,2,3,4,5,6,7,8,9,10};

     int main(void) {
            //  printf("The condition is %d",(all_mem-2));
            int i;
                for(i=-1;i<=(all_mem-2);i++)
            {
                printf("The number is %d",i);
            }
            return 0;
        }

在上面的代码中 for 循环甚至没有执行一次,我尝试了打印条件并且它满足循环条件。任何见解如何将 for 循环条件中的宏表达式评估为小于 -1 的值?

【问题讨论】:

  • 在有符号/无符号比较中,i 被转换为0xffffffff,比all_mem - 2 大得多。至少我认为这就是正在发生的事情。你为什么从-1开始i?我认为我从未见过这样做的代码。
  • 屏幕上什么都没有?
  • @ShahrozShaikh:由于循环条件立即失败,您不会期待任何事情。该程序可以简化为int main(void) { return 0; },这将产生任何输出。

标签: c for-loop


【解决方案1】:

在对代码进行一些更正后,例如 sizeof() 返回 size_t,而不是 int,代码运行良好。

这里是修改后的代码:

#include <stdio.h>

#define all_mem (sizeof(x) /sizeof(x[0]))

int x[] ={1,2,3,4,5,6,7,8,9,10};

int main(void)
{
    printf( "all_mem = %ld\n", all_mem ); // << added for debugging

    //  printf("The condition is %d",(all_mem-2));
    int i;
        for(i=-1;i<=(int)(all_mem-2);i++) // << 
        // << properly cast to int
        // otherwise compiler raises warning and unsigned comparison made
    {
        printf("The number is %d\n",i);
    }
    return 0;
}

这是上面代码的输出:

all_mem = 10
The number is -1
The number is 0
The number is 1
The number is 2
The number is 3
The number is 4
The number is 5
The number is 6
The number is 7
The number is 8

编译时,始终启用所有警告,然后修复这些警告。

如果遵循上述声明,那么如果没有我们的帮助,您就会发现问题。

(对于 gcc,至少使用:-Wall -Wextra -pedantic,我还添加:-Wconversion -std=c99

【讨论】:

    【解决方案2】:

    all_mem 宏正在返回一个size_t 值;整数提升规则意味着i &lt;= (all_mem - 2)的比较是将i提升为size_t,这意味着价值很大,而不是-1。尝试强制转换以确保签名比较:

    for(i = -1; i <=(ssize_t)(all_mem- 2); ++i)
    

    【讨论】:

    • 不应该是(int)演员吗?
    • @TomKarzes:点。在实践中,我通常使用size_tssize_t 类型作为我的索引变量以避免该问题,因此for 循环将保留为我的答案指定,i 的声明将更改为ssize_t i;。当然,ssize_t可能有问题,但实际上,用户虚拟内存通常是总内存空间的一半,因此可以假设数组长度适合带符号的size_t .当然,我们知道数组很小,所以 int 不会发生溢出(很确定没有 C 版本的 int 小于 5 位 :-))。
    • 但这并不能解决问题。由于i-1 开始,循环将立即退出,正如OP 报告的那样。它不起作用。事实上,演员表没有任何效果,因为它已经size_t
    • @TomKarzes:你误读了。我建议对ssize_t 进行演员表(注意额外的前导s,表示签名size_t),而不是size_t(已经是)。
    • 哦,是的,你完全正确,我误读了它。我的错!
    猜你喜欢
    • 2012-09-21
    • 2012-08-18
    • 2018-01-24
    • 2017-07-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多