当str为空时,在'for'循环条件中strlen(str)-1的值将是多少?

5
我正在分析一个场景:
char str[] = ""; // Understand

如果我理解strlen(str)的话,它的结果是0。这是正常的。

printf(" %d,  %ul,  %u, %d,  %ul, %u", 
    strlen(str),
    strlen(str),
    strlen(str),
    strlen(str) - 1,
    strlen(str) - 1,
    strlen(str) - 1);

输出结果为:

0、0l、0、-1、4294967295l、4294967295

我也理解这些。

for (int i = 0; i < strlen(str) - 1; i++)
{
}

在我看来,for循环中的strlen(str) - 1是令人困惑的。

strlen(str) - 1在for循环中的值为4294967295。

为什么会这样?而不是-1呢?


1
害怕调试器?试试单步执行! - too honest for this site
1
您的代码包含未定义行为。strlen 的结果类型为 size_t,但您使用矛盾的格式说明符进行打印。size_t 的正确格式说明符是 %zu - fuz
1
“wraparound/underflow is one of the things considered as undefined behaviour” 这个说法在有符号整数中是正确的,但在这里不适用。由于 strlen() 的返回类型是 size_t,即无符号整数,因此 wraparound/underflow 是被明确定义的,而且不是未定义行为。 - chux - Reinstate Monica
1
四个赞,对于本质上是“0-1”的东西?? - Martin James
1
@JimBalter:呸,那算什么。她还包括了%u%ul的输出,显然没有注意到%ul只是%u后面加上l - ruakh
显示剩余6条评论
2个回答

16

strlen返回一个无符号整数size_t。所以如果strlen(str)等于0,那么strlen(str)-1会产生SIZE_MAXsize_t可以容纳的最大值)。

当打印size_t值时应该使用%zu


3
这个声明。
printf(" %d,  %ul,  %u, %d,  %ul, %u", strlen(str),strlen(str),strlen(str),strlen(str)-1,strlen(str)-1,strlen(str)-1);

这段代码表明,当使用无符号整数的格式说明符%ul输出strlen(str)-1时,其值为4294967295l

在循环条件中:

for (int i=0;i<strlen(str)-1;i++)

编译器需要确定左右操作数的公共类型来确定条件结果的类型。

i<strlen(str)-1

右操作数strlen(str)-1的类型为size_t(函数strlen的返回类型为size_t)。它通常是对应于unsigned long的无符号整数类型。它不能有负值,任何存储在此类型对象中的值都被解释为非负值。正如输出所示,strlen(str)-1的值等于4294967295l。(如果使用类型说明符%zu ,则可能无法排除size_t甚至可以对应于unsigned long long的情况,这样你将得到实际值)

右操作数的类型为int,其级别最多不大于size_type的级别。因此,两个操作数都被转换为size_t类型,并具有非负值。

确定公共类型的过程称为通常的算术转换。显然,4294967295l大于0。因此,如果没有break语句,则循环将迭代4294967295l次。

如果按照以下方式重写循环中的条件,则可以获得预期结果:

for ( int i = 0; i < ( int )strlen( str ) - 1; i++ )

4294967295 中,小写字母 l 代表什么? - M.M

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接