当我偶然发现不了解的东西时,我正在学习循环。
在这段代码中,如果我输入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);
}
答案 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 = 3
和unsigned 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