【问题标题】:strlen sometimes equal to sizeof for null-terminated strings对于以空字符结尾的字符串,strlen 有时等于 sizeof
【发布时间】:2015-04-26 01:30:51
【问题描述】:

我知道strlen 计算直到(并且不包括)空字符'\0'(或0)的字符数,并且sizeof 给出了存储字符串所需的空间量,包括空字符字符,但我对我的代码的输出感到困惑。

问题:

我希望 strlen 的结果始终比 sizeof 的结果小 1,因为我的字符串以空值结尾,但似乎只有长度为 4 和 8 的字符串是这种情况,不包括 ' \0'(即下面的第 3 和第 5 个结果)。我怀疑这与在第一个、第二个和第三个结果的字符串末尾打印垃圾的原因相同。有人可以解释这种行为吗?

我阅读了这个相关问题,但我不认为这就是这里发生的事情:strlen - the length of the string is sometimes increased by 1

代码的作用:

main 中,它创建一个整数数组 0、2、4、6 和 8。然后对于每个长度,它调用函数 make_and_print_msgs 来:

  • 创建一个长度为 + 1 的字符串(用于空字符),例如如果长度为 4,则创建字符串“aaaa\0”
  • printf 中使用%c 逐字母打印消息
  • printf 中使用%s 将其打印为字符串
  • 找到字符串的strlen
  • 找到sizeof字符串

输出:

i    data_length[i]
--------------------
0       0
msg intended to be:    
msg printed as string: �
strlen(msg): 1
sizeof(msg): 1

1       2
msg intended to be:    aa
msg printed as string: aaS
strlen(msg): 3
sizeof(msg): 3

2       4
msg intended to be:    aaaa
msg printed as string: aaaa
strlen(msg): 4
sizeof(msg): 5

3       6
msg intended to be:    aaaaaa
msg printed as string: aaaaaai
strlen(msg): 7
sizeof(msg): 7

4       8
msg intended to be:    aaaaaaaa
msg printed as string: aaaaaaaa
strlen(msg): 8
sizeof(msg): 9

代码:

(抱歉代码有点长,所以我在上面解释了。代码中的一些 cmets 是对 Python NumPy 函数的引用。)

#include <stdio.h>
#include <math.h>   /* needed for ceil */
#include <string.h> /* needed for strlen */

void make_linspace(int a[], double start, double stop, int num) {
    /* Fills array a[] (in place) with linearly spaced values just like np.linspace in NumPy (Python) */
    double spacing = (stop-start)/(num-1);
    int i;
    for (i=0; i<num; i++){
        a[i] = start + i*spacing;
    }
}

void make_and_print_msgs(int n_proc, int msglength)
{
    /* Create a string called msg of length msglength + 1 (for the null character '\0') */
    char msg[msglength+1];
    int i;
    printf("msg intended to be:    ");
    for (i=0; i<msglength; i++) {
        msg[i] = 'a';
        printf("%c", msg[i]);
    }
    msg[i+1] = '\0';

    /* Print message to screen as a string and fine strlen(msg) and sizeof(msg) */
    printf("\n");
    printf("msg printed as string: %s\n", msg);
    printf("strlen(msg): %d\n", strlen(msg));
    printf("sizeof(msg): %d\n\n", sizeof(msg));

}

void main(int argc, char *argv[])
{
    int n_proc = 2;

    /* Create an array containing the lengths of strings to be printed (In this case, data_length should be {0, 2, 4, 6, 8} */
    int start = 0;
    int stop_range = 10;    /* the stop value if we are using range() */
    int step = 2;             /* spacing between the integers in the output of range() */
    int stop = stop_range - step;    /* the stop value if we are using linspace() */
    int npoints = (int) ceil( ((double)stop_range - (double)start) / (double)step );  /*  number of elements in the list produced by range(start, stop_range, step)  */

    int data_length[npoints];   /* 1D array of string lengths (# of non-null chars in each str) */
    make_linspace(data_length, start, stop, npoints);
    int i;


    /* For each length, call on make_and_print_msgs to make a string of that length (plus '\0') and then print to stdout */
    printf("   i    data_length[i]\n--------------------\n");
    for (i=0; i<npoints; i++) {
        printf("%4d %7d\n", i, data_length[i]);
        make_and_print_msgs(n_proc, data_length[i]);
    }
}

【问题讨论】:

  • msg[i+1] = '\0'; 应该是msg[i] = '\0';,因为msglengthmsg 的最后一个有效索引,i 在循环后等于它。
  • 天哪!那真是个愚蠢的错误。非常感谢。
  • 不要使用%d 打印size_t 类型的值。使用%zu

标签: c string null sizeof strlen


【解决方案1】:

改变这个:msg[i+1] = '\0';msg[i] = '\0';

您不需要增加i,因为它已经增加了之前的for loop

工作理念链接:http://ideone.com/GJO1q1

【讨论】:

  • 啊,是的!我才意识到我犯了一个多么愚蠢的错误。谢谢!
【解决方案2】:

在您的代码中,sizeof(msg) 始终等于 msglength+1,因为您声明为 char msg[msglength+1];

strlen(msg) 始终计数,直到遇到第一个 '\0'。因此,在您的代码中,有时是 msglength+1,有时是 msglength,具体取决于未初始化的 msg 的初始内容。

【讨论】:

  • sizeof(msg) 是 msglength+1,而不是 msglength。
  • @user3125367 哎呀,错字了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-06-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多