6

我来用另一个可能非常简单的 C 问题来打扰大家。

使用以下代码:

int get_len(char *string){

    printf("len: %lu\n", strlen(string));

    return 0;
}

int main(){

    char *x = "test";
    char y[4] = {'t','e','s','t'};

    get_len(x); // len: 4
    get_len(y); // len: 6

    return 0;
}

2个问题。为什么它们不同,为什么 y 是 6?多谢你们。

编辑:对不起,我知道什么会解决它,我只是想了解发生了什么。那么 strlen 是否只是继续转发该点,直到它碰巧找到 \0?另外,当我在 main 函数中而不是在 get_len 函数中执行 strlen 时,两者都是 4。这只是巧合吗?

4

9 回答 9

15

y不是空终止的。 strlen()计数字符,直到遇到空字符。你碰巧在 6 之后找到了一个,但它可以是任何数字。尝试这个:

char y[] = {'t','e','s','t', '\0'};

下面是一个实现的strlen()样子(在我的脑海中——手边没有我的 K&R 书,但我相信那里有一个实现):

size_t strlen(const char* s)
{
    size_t result = 0;
    while (*s++) ++result;
    return result;
}
于 2010-04-23T20:47:35.187 回答
4

这个

char y[4] = {'t','e','s','t'};

不是一个正确的以零结尾的字符串。它是一个由四个字符组成的数组,没有终止符'\0'. strlen()简单地计算字符,直到它达到零。它y只是简单地计算数组的末尾,直到它意外地找到一个零字节。
这样做是在调用未定义的行为。该代码也可以格式化您的硬盘驱动器。

您可以通过使用字符数组初始化的特殊语法来避免这种情况:

char y[] = "test";

y这使用五个字符进行初始化,因为它会自动附加一个'\0'.
请注意,我还没有指定数组的大小。编译器自己计算出来,如果我改变字符串的长度,它会自动重新计算。

顺便说一句,这是一个简单的strlen()实现:

size_t strlen(const char* p)
{
    size_t result = 0;
    while(*p++) ++result;
    return result;
}

现代实现可能不会获取单个字节,甚至不会使用 CPU 内在函数,但这是基本算法。

于 2010-04-23T20:48:02.660 回答
3

以下不是以空字符结尾的字符数组:

 char y[4] = {'t','e','s','t'};

合同的一部分strlen()是它被提供了一个指向空终止字符串的指针。由于不会发生这种情况strlen(y),因此您会得到未定义的行为。在您的特定情况下,您会被6退回,但任何事情都可能发生,包括程序崩溃。

来自 C99 的 7.1.1“术语定义”:

字符串是由第一个空字符终止并包括第一个空字符的连续字符序列。

于 2010-04-23T20:49:39.153 回答
3

strlen字符串一起使用。字符串被定义为以字符结尾的\0字符序列(数组)。

x指向一个字符串。所以,作为论据strlen可以很好地工作。x

y的不是一个字符串。因此,传递ystrlen会导致未定义的行为。结果是毫无意义的和不可预测的。

于 2010-04-23T20:50:13.053 回答
2

您需要以空值终止 y。

int get_len(char *string){

    printf("len: %lu\n", strlen(string));

    return 0;
}

int main(){

    char *x = "test";
    char y[5] = {'t','e','s','t','\0'};

    get_len(x); // len: 4
    get_len(y); // len: 4

    return 0;
}

strlen() 基本上获取您给它的指针并计算字节数,直到内存中的下一个 NULL。碰巧在你的记忆中后面有一个 NULL 两个字节。

于 2010-04-23T20:47:24.143 回答
1

实际的 C 类型字符串比其字符数大一,因为它需要一个终止空字符。

因此,char y[4] = {'t','e','s','t'};不会形成字符串,因为它是四个字符。 char y[] = "test";或者char y[5] = "test";会形成一个字符串,因为它们有一个由五个字符组成的字符数组,以空字节终止符结尾。

于 2010-04-23T20:50:50.683 回答
0
char y[5] = {'t','e','s','t','\0'};

将与

char *x = "test"; 
于 2010-04-23T20:49:49.763 回答
0

正如其他人所说,您只需要确保以 0 或 '\0' 字符结尾的字符串。作为旁注,您可以查看:http ://bstring.sourceforge.net/ 。它具有 O(1) 字符串长度函数,不像 C/C++ strlen 容易出错并且在 O(N) 时很慢,其中 N 是非空字符的数量。我不记得上次使用 strlen 和它的朋友是什么时候。寻求安全快速的功能/课程!

于 2010-04-24T01:09:51.973 回答
0

当您使用单引号时,请始终使用 '/0' 但在双引号中避免在 strlen() 中使用 '/0'

请注意,strlen() 函数在计算长度时不计算空字符 \0

于 2021-01-04T09:59:15.180 回答