[英]How can I find the length of a character pointer using strlen() in C?
I am making it clear that my question is exact duplicate of this question. 我明确表示我的问题与这个问题完全相同。
But unfortunately I have one question which any of the answers didn't addressed. 但不幸的是,我有一个问题,任何答案都没有解决。 So the code was:-
所以代码是: -
#include <string.h>
int foo(void) {
char bar[128];
char *baz = &bar[0];
baz[127] = 0;
return strlen(baz);
}
Question was: What are the possible outputs of this function? 问题是:这个功能的可能输出是什么?
When I run this code, this gives 0 everytime and the correct answers are 0 and 127(I still didn't get why?). 当我运行这段代码时,每次都给出0,正确的答案是0和127(我仍然没有得到原因?)。
My question is how this statement is even valid I mean we are calculating the length of baz
which contains a memory address say 0xb96eb740
which is a hex number, so what we are doing is strlen()
on this address to find it's length? 我的问题是这个语句是如何有效的我的意思是我们正在计算包含内存地址的
baz
的长度,例如0xb96eb740
这是一个十六进制数,所以我们在这个地址上做strlen()
来查找它的长度? I mean how can we find length of an address , which is just a number? 我的意思是我们怎样才能找到一个地址的长度,这只是一个数字?
I am really confused and trying to understand it for hours but still not getting it. 我真的很困惑,并试图理解它几个小时但仍然没有得到它。
Don't get stuck on the fact that it's being passed an address. 不要因为它被传递一个地址而被困住。
strlen()
always takes an address. strlen()
总是占用一个地址。 It's argument is a const char *
, the address of a string. 它的参数是一个
const char *
,一个字符串的地址。 All of these calls pass the exact same address: 所有这些调用都传递完全相同的地址:
strlen(baz);
strlen(&bar[0]);
strlen(bar);
baz
is assigned &bar[0]
, so the first and second are equivalent. baz
被赋值为&bar[0]
,所以第一个和第二个是等价的。 An array decays to a pointer to its first element ( array == &array[0]
), so the second and third are equivalent. 数组衰减到指向其第一个元素的指针 (
array == &array[0]
),因此第二个和第三个元素是等价的。
I mean how can we find length of an address , which is just a number?
我的意思是我们怎样才能找到一个地址的长度,这只是一个数字?
Let's say that bar == &bar[0] == baz == (char *) 0xb96eb740
as per your example. 假设根据你的例子,
bar == &bar[0] == baz == (char *) 0xb96eb740
。 strlen()
will first check if memory location 0xb96eb740 contains \\0
. strlen()
将首先检查内存位置0xb96eb740是否包含\\0
。 If not, it will then check 0xb96eb741. 如果没有,它将检查0xb96eb741。 Then 0xb96eb742.
然后是0xb96eb742。 Then 0xb96eb743.
然后是0xb96eb743。 It will continue checking each location sequentially until it finds
\\0
. 它将继续按顺序检查每个位置,直到找到
\\0
。
I know that's true.
我知道那是真的。 But why does
strlen(baz)
return 0?但是为什么
strlen(baz)
返回0?
As the linked Q&A explains, the behavior is indeterminate because the contents of the bar[128]
array are uninitialized. 正如链接的问答所解释的那样,行为是不确定的,因为
bar[128]
数组的内容是未初始化的。 There could be anything in that array. 该阵列中可能有任何内容。 The only cell we know the value of is
bar[127]
, which is set to \\0
. 我们知道值的唯一单元格是
bar[127]
,它被设置为\\0
。 All the others are uninitialized. 所有其他人都没有初始化。
That means that any one of them, or all of them, or none of them, could contain a \\0
character. 这意味着它们中的任何一个或全部,或者都不包含
\\0
字符。 It could change from run to run, from call to call even. 它可以从一次运行变为另一次运行,甚至从呼叫到呼叫。 Every time you call
foo()
you could get a different result. 每次调用
foo()
都可以得到不同的结果。 That's entirely possible. 这完全有可能。 The result will vary based on what data happens to be on the stack before
foo()
is called. 结果将根据调用
foo()
之前堆栈上的数据而变化。
When I run this code, this gives
0
every time and the correct answers are0
and127
(I still don't get why?).当我运行这段代码时,每次都给出
0
,正确的答案是0
和127
(我仍然不明白为什么?)。
It could return any value between 0 and 127. Due to the indeterminate behavior you mustn't read too much into what the program happens to return when you run it. 它可以在0和127之间的任意值返回由于你一定不要过分解读该程序会发生什么,当你运行它返回不确定的行为。 The output could be different if you run the program again, if you cal a different set of functions before
foo()
, if you run a different program beforehand, if you change compilers, if you run it a different day of the week, if you use a different operating system, etc., etc., etc. 如果你再次运行程序,如果你在
foo()
之前调用一组不同的函数,如果你事先运行一个不同的程序,如果你改变编译器,如果你在一周的另一天运行它,如果你运行它,则输出可能会有所不同您使用不同的操作系统等,等等。
My question is how this statement is even valid I mean we are calculating the length of baz which contains a memory address say 0xb96eb740 which is a hex number, so what we are doing is strlen() on this address to find it's length?
我的问题是这个语句是如何有效的我的意思是我们正在计算包含内存地址的baz的长度,例如0xb96eb740这是一个十六进制数,所以我们在这个地址上做strlen()来查找它的长度?
The strlen
function accepts an address as argument, and its behaviour is to read the character stored at that address. strlen
函数接受一个地址作为参数,其行为是读取存储在该地址的字符。 (It does not try to read the characters of the address as you seem to be suggesting). (它不尝试读取地址的字符作为你似乎在暗示)。 If that character is not
'\\0'
then it will read the character at the next address and see if that is '\\0'
etc. 如果该字符不是
'\\0'
那么它将读取下一个地址的字符并查看是否为'\\0'
等。
The answer to your question is anything can happen . 你的问题的答案是任何事情都可能发生 。
The array bar
is uninitialized. 阵列
bar
未初始化。 Only bar[127]
is explicitly set to '\\0'
. 只有
bar[127]
显式设置为'\\0'
。 Passing an uninitialized array to strlen()
, which you do indirectly by passing baz
, which points to bar[0]
, has undefined behavior. 将未初始化的数组传递给
strlen()
,通过传递指向bar[0]
baz
间接执行该操作,具有未定义的行为。
In practice, on modern architectures without trap values, function foo()
has unspecified behavior and can return any value between 0
and 127
depending on whatever the stack contains when you call it. 实际上,在没有陷阱值的现代体系结构中,函数
foo()
具有未指定的行为,并且可以返回0
到127
之间的任何值,具体取决于调用时堆栈包含的内容。
In your case it returns 0
because there happens to be a null byte at the beginning of bar
, but you cannot rely on that and successive calls to foo()
could return different values. 在你的情况下,它返回
0
因为在bar
的开头恰好有一个空字节,但你不能依赖它,并且对foo()
连续调用可能返回不同的值。
If you run a program that calls foo()
under valgrind or some other memory sanitizing tool, it might complain that strlen()
accesses uninitialized memory. 如果你运行一个在valgrind或其他内存清理工具下调用
foo()
的程序,它可能会抱怨strlen()
访问未初始化的内存。
Others have covered that the value is indeterminate , so I go directly to this: 其他人已经说过价值是不确定的 ,所以我直接谈到这个:
I mean how can we find length of an address, which is just a number?
我的意思是我们怎样才能找到一个地址的长度,这只是一个数字?
You don't. 你没有。 The length of a string is calculated by reading the memory sequentially from the address you want to start with and see how far you need to go before you hit the first
'\\0'
character. 字符串的长度是通过从您想要开始的地址开始按顺序读取内存来计算的,并在您点击第一个
'\\0'
字符之前查看您需要走多远。 Here is an example of how you can implement a function that returns the length of a string: 下面是一个如何实现返回字符串长度的函数的示例:
int strlen(char * str) {
int length=0;
while(str[length] != '\0')
length++;
return length;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.