C编程 - strlen的功能

时间:2014-02-28 02:13:31

标签: c string strlen

我正在努力尝试理解一些字符串函数,以便我可以在以后的编码项目中更有效地使用它们,所以我在下面设置了简单的程序:

#include <stdio.h>
#include <string.h>

int main (void)
{
// Declare variables:
char test_string[5];
char test_string2[] = { 'G', 'O', '_', 'T', 'E', 'S', 'T'};
int init; 
int length = 0;
int match;

// Initialize array:
for (init = 0; init < strlen(test_string); init++)
{    test_string[init] = '\0';
}

// Fill array:
test_string[0] = 'T';
test_string[1] = 'E';
test_string[2] = 'S';
test_string[3] = 'T';

// Get Length:
length = strlen(test_string);

// Get number of characters from string 1 in string 2:
match = strspn(test_string, test_string2);

printf("\nstrlen return = %d", length);
printf("\nstrspn return = %d\n\n", match);

return 0;
}

我希望看到回归:

strlen return = 4 strspn return = 4

但是,我看到strlen return = 6和strspn return = 4.据我所知,char test_string [5]应该分配5个字节的内存并将十六进制00放入第五个字节。 for循环(甚至不应该是nessecary)然后应该将test_string的所有内存字节设置为十六进制00.然后,紧接着的行应该填充test_string字节1到4(或test_string [0]到test_string [3])用我指定的。此时调用strlen应该返回一个4,因为它应该从字符串0的地址开始并计算一个增量,直到它到达第一个空字符,即字符串[4]。然后strlen返回6.任何人都可以解释这个吗?谢谢!

3 个答案:

答案 0 :(得分:7)

char test_string[5];

test_string是一个包含5个未初始化的 char个对象的数组。

for (init = 0; init < strlen(test_string); init++)

KABOOM。 strlen会扫描第一个'\0'空字符。由于test_string的内容是垃圾,因此行为未定义。如果恰好存在空字符,则可能返回一个小值;如果test_string中没有任何零字节,则可能返回大值或程序崩溃。

即使不是这种情况,在strlen()循环的标头中评估for也是低效的。每个strlen()调用都必须重新扫描整个字符串(假设你给它一个有效的字符串),所以如果你的循环工作,它将是O(N 2 )。

如果希望test_string只包含零字节,可以这样初始化它:

char test_string[5] = "";

或者,因为您稍后初始化前4个字节:

char test_string[5] = "TEST";

或只是:

char test_string[] = "TEST";

(后者让编译器发现它需要5个字节。)

回到你的声明:

char test_string2[] = { 'G', 'O', '_', 'T', 'E', 'S', 'T'};

这会导致test_string2长度为7个字节,不带后跟'\0'个字符。这意味着将test_string2传递给任何需要指向字符串的指针的函数都会导致未定义的行为。你可能想要这样的东西:

char test_string2[] = "GO_TEST";

答案 1 :(得分:4)

strlen搜索'\ 0'字符来计算它们,在你的test_string中没有,所以它会继续,直到找到一个恰好距离数组开头6个字节的字符,因为它未初始化

编译器不会生成用于初始化数组的代码,因此如果稍后再填充该代码,则无需付费即可运行该代码。

要将其初始化为0并跳过循环,您可以使用

char test_string[5] = {0};

这样,所有字符都将被初始化为0,并且在您使用“TEST”填充数组后,您的strlen将起作用。

答案 2 :(得分:2)

这里有一些问题。首先,char test_string[5];只为该字符串留出5个字节,但不将字节设置为任何字节。特别是,当你说“char test_string [5]应该分配5个字节的内存并将十六进制00放入第五个字节”时,第二部分是错误的。

其次,您的数组初始化循环使用strlen(test_string)但由于test_string的字节未初始化,因此无法知道是什么,因此strlen(test_string)返回一些未定义的结果。清除数组的更好方法是memset( test_string, 0, sizeof(test_string) );

使用“TEST”填充数组但不在末尾设置NULL字节,因此最后一个字节仍未初始化。如果您执行上面的memset,则会修复此问题,或者您可以手动执行test_string[4] = '\0'