为什么不能使用i = -1初始化循环?

时间:2019-12-08 11:55:09

标签: c

当我偶然发现不了解的东西时,我正在学习循环。

在这段代码中,如果我输入for循环i = 0,它会按预期工作,如果我写“ dog”,我会得到3个a,但是如果我写i = -1,我就不会根本没有得到输入,不应该再给我一个额外的吗?

我不能在任何需要的地方开始i值吗?

#include <string.h>

int main (int argc, char **argv) {
        char string[10];

        scanf("%s", string);

        void changestring (char *newstring) {
                for (int i=0; i < strlen(newstring); i++) {
                        printf("a");
                }
        }
        changestring(string);
}

2 个答案:

答案 0 :(得分:3)

首先,让我们稍微重写一下代码,以消除一些混乱(由于未启动,这里发生的事情很少,可能看起来很相似,但并非如此)。

#include <string.h>

void print_as_according_to_strlen(char *n) {
    for (int i=0; i < strlen(newstring); i++) {
        printf("a");
    }
}

这是相关的部分。如果您查看strlen的定义,就会发现它返回的类型为size_t

size_t strlen(const char *s);
     

返回字符串s的长度。

size_t unsigned 类型。 C和C ++具有某些规则,通过这些规则,整数值在操作中一起使用时会隐式转换为“公共”类型。这些就是所谓的“整数提升规则” –必须知道的重要知识,您绝对必须学习它们。

其中一个规则是,如果您将一个 signed 整数与一个 unsigned 整数“交互”,则提升的类型将是 unsigned 以及。当然,如果您尝试将负值提升为无符号类型,结果将有所不同。

现在使用C语言变得棘手,因为在某些情况下(实际上是大多数情况),尝试执行未定义行为,即可能发生任何事情。但是,有一些例外,它实际上表现良好(例如,如果您有两个 unsigned 变量unsigned a = 3unsigned b = 5,则操作a-b的结果为实际上是一个定义明确的值,因为无符号溢出定义明确,结果为UINT_MAX - (b-a)

您的底线是:您必须重写代码,以便将比较升级为带符号的比较,或者代替从-1开始,转到strlen(…)+1。建议不要使用int,而建议使用ptrdiff_t,因为int的大小可能足以或可能不足以容纳strlen的结果。碰巧(不是C语言,而是现代OS如何管理内存)strlen永远不会返回可能溢出ptrdiff_t

的值
ptrdiff_t len = strlen(newstring);
for(ptrdiff_t i=-1; i < len ; i++){

答案 1 :(得分:0)

对于初学者来说,嵌套函数定义不是C标准功能。您应该在main外部定义函数。

关于您的问题,然后在此表达式中

i < strlen(newstring)

编译器使用操作数的常规算术转换来确定运算符<的常见类型。

函数strlen的返回类型为size_t,它是无符号类型,其转换等级高于或等于int类型的等级。因此,表达式i被转换为保留其位的无符号类型size_t。结果,您将获得一个非常大的无符号值,该值比函数strlen返回的值更大,并且caondition的值为false。

请考虑以下演示程序

#include <stdio.h>

int main(void) 
{
    int i = -1;

    printf( "i = %i, ( size_t )i = %zu\n", i, ( size_t  ) i );

    return 0;
}

其输出可能看起来像

i = -1, ( size_t )i = 18446744073709551615