我正在努力尝试理解一些字符串函数,以便我可以在以后的编码项目中更有效地使用它们,所以我在下面设置了简单的程序:
#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.任何人都可以解释这个吗?谢谢!
答案 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'
。