我明确指出,我的问题与该问题完全相同。
但不幸的是,我有一个问题,任何答案都没有解决。所以代码是:
#include <string.h>
int foo(void) {
char bar[128];
char *baz = &bar[0];
baz[127] = 0;
return strlen(baz);
}
Run Code Online (Sandbox Code Playgroud)
问题是:此功能的可能输出是什么?
当我运行此代码时,每次给出0,正确的答案是0和127(我仍然不明白为什么?)。
我的问题是,该语句如何有效?我的意思是我们正在计算baz包含一个内存地址的长度,说0xb96eb740这是一个十六进制数,那么我们正在strlen()此地址上查找它的长度是什么?我的意思是我们如何才能找到一个只有数字的地址的长度?
我真的很困惑,想花几个小时来理解它,但仍然听不懂。
不要卡在地址被传递的事实上。strlen() 总是需要一个地址。它的参数是a const char *,字符串的地址。所有这些调用都传递完全相同的地址:
strlen(baz);
strlen(&bar[0]);
strlen(bar);
Run Code Online (Sandbox Code Playgroud)
baz被分配&bar[0],因此第一个和第二个是等效的。数组会衰减为其第一个元素(array == &array[0])的指针,因此第二个和第三个元素是等效的。
我的意思是我们如何才能找到一个只有数字的地址的长度?
假设bar == &bar[0] == baz == (char *) 0xb96eb740按照您的示例。strlen()首先检查内存位置0xb96eb740是否包含\0。如果不是,它将检查0xb96eb741。然后是0xb96eb742。然后是0xb96eb743。它将继续顺序检查每个位置,直到找到为止\0。
我知道是真的 但是为什么
strlen(baz)返回0?
正如链接的问答所解释的,行为是不确定的,因为bar[128]数组的内容尚未初始化。该数组中可能有任何内容。我们知道的唯一单元格的值是bar[127],设置为\0。所有其他未初始化。
这意味着它们中的任何一个或全部或不包含一个\0字符。它可能会随运行而变化,甚至因调用而异。每次致电foo()您都会得到不同的结果。那完全有可能。结果将根据调用之前堆栈中恰好有哪些数据而有所不同foo()。
当我运行此代码时,
0每次都会给出正确答案,0并且是127(我仍然不明白为什么?)。
它可以返回0到127之间的任何值。由于行为不确定,您在运行程序时不要过多地了解程序会返回什么。如果您再次运行该程序,如果您之前计算了一组不同的函数foo(),如果您事先运行了另一个程序,如果您更改了编译器,如果您在一周的另一天运行了该程序,并且使用了不同的操作系统等,等等,等等。