strlen sometimes equal to sizeof for null-terminated strings

我们两清 提交于 2019-12-25 14:01:07

问题


I know that strlen counts the number of characters up until (and excluding) the null character '\0' (or 0) and that sizeof gives the amount of space needed to store the string including the null character, but am confused with the output of my code.

Question:

I expect the result of strlen to be consistently 1 less than the result of sizeof because my strings are null-terminated, but it only seems to be the case for the string of length 4 and 8, excluding '\0' (i.e. the 3rd and 5th results below). I suspect it is the same reason that rubbish is being printed at the end of the string for 1st, 2nd, and 3rd results. Could someone explain this behavior?

I read this related question, but I don't think that's what's happening here: strlen - the length of the string is sometimes increased by 1.

What the code does:

In main, it creates an array of integers 0, 2, 4, 6, and 8. And then for each of those lengths, it calls on the function make_and_print_msgs to:

  • create a string of that length + 1 (for the null character), e.g. for a length of 4, the string "aaaa\0" is created
  • print the message letter-by-letter using %c in printf
  • print it as a string using %s in printf
  • finds the strlen of the string
  • finds the sizeof the string

Output:

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

Code:

(Sorry code is a bit long, that's why I explained it above. Some comments in the code are references to Python NumPy functions.)

#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]);
    }
}

回答1:


Change this : msg[i+1] = '\0'; to msg[i] = '\0';

You do not need to increment i as it is already incremented by the previous for loop.

Working ideone link: http://ideone.com/GJO1q1




回答2:


In your code, sizeof(msg) always equals to msglength+1 because you declared as char msg[msglength+1];.

strlen(msg) always counts till the first '\0' encountered. Thus in your code it is sometimes msglength+1 and sometimes msglength depending on the initial content of uninitialized msg.



来源:https://stackoverflow.com/questions/29872687/strlen-sometimes-equal-to-sizeof-for-null-terminated-strings

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!