Thread: Demostrating that an array of characters is not terminated by zero.

  1. #1
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103

    Demostrating that an array of characters is not terminated by '\0'.

    Note: I'm getting back into C after a 10 year hiatus.

    I'm trying to demonstrate that an array of characters is not terminated by a '\0'. To accomplish this I'm using a gcc C extension packed to make sure that the following bytes after my array is known. I use a unsigned value of UINT_MAX to make sure the following bytes are not zero and 0 to back sure the the values are zero.

    Here's the what I'm trying to demonstrate. I know that an array of characters does not append a '\0' to the end but I'd like to show that.

    To demonstrate that array is not terminated by '\0' I follow the array by UINT_MAX in this code and get a strlen greater than the array.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    
    #define ARR_SIZE 5
    
    struct mys
    {
        char name[ARR_SIZE];
        unsigned n;
    } __attribute__((__packed__));
    
    int main(int argc, char **argv)
    {
        struct mys s = {{'G', '4', '1', '4', '3'}, UINT_MAX};
        fprintf(stdout, "Length: %ld\n", strlen(s.name));
        fprintf(stdout, "%s\n", s.name);
        return 0;
    }
    The output from the above code is:
    Length: 9
    G4143����
    Now if I change the value UINT_MAX to 0
    Code:
    include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
    
    #define ARR_SIZE 5
    
    struct mys
    {
        char name[ARR_SIZE];
        unsigned n;
    } __attribute__((__packed__));
    
    int main(int argc, char **argv)
    {
        struct mys s = {{'G', '4', '1', '4', '3'}, 0};
        fprintf(stdout, "Length: %ld\n", strlen(s.name));
        fprintf(stdout, "%s\n", s.name);
        return 0;
    }
    I get an output:
    Length: 5
    G4143
    Now what I'd like to know is... Does this actually demonstrate, since I'm using a C extension, that an array of characters doesn't append a '\0' to the end?
    Last edited by G4143; 02-20-2022 at 11:05 PM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Well this is \0 terminated, without you having to do anything with the .n member.
    Code:
        struct mys s = {{'G', '4', '1', '4'}, UINT_MAX};
    C doesn't care whether your char arrays are \0 terminated or not, that's just a convention of most of the standard library string handling functions.
    If you supply 5 initialisers to a 5 char array, C just does it and assumes you know what you're doing.

    > To demonstrate that array is not terminated by '\0' I follow the array by UINT_MAX in this code and get a strlen greater than the array.
    Only because strlen happened to stumble into a \0 which you know nothing about that just happened to be immediately after the struct.
    It could just as easily printed a much larger number or bombed out with a segmentation fault.

    > Does this actually demonstrate, since I'm using a C extension, that an array of characters doesn't append a '\0' to the end?
    Since the program has undefined behaviour from the moment you call strlen and a \0 is not found within the bounds of the array, it doesn't demonstrate anything.

    This might be a better demonstration.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <limits.h>
     
    #define ARR_SIZE 5
     
    struct mys
    {
        char name[ARR_SIZE];
        char pretend_nul;
        char actual_nul;
    };
     
    int main(int argc, char **argv)
    {
        struct mys s = {{'G', '4', '1', '4', '3'}, '?', '\0'};
        fprintf(stdout, "Size=%zd\n", sizeof(s));
        fprintf(stdout, "Length: %ld\n", strlen(s.name));
        fprintf(stdout, "%s\n", s.name);
        s.pretend_nul = '\0';
        fprintf(stdout, "Length: %ld\n", strlen(s.name));
        fprintf(stdout, "%s\n", s.name);
        return 0;
    }
    
    
    $ gcc foo.c
    $ ./a.out 
    Size=7
    Length: 6
    G4143?
    Length: 5
    G4143
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103
    @Salem Aren't you making assumptions about the padding in the structure?

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Quote Originally Posted by c99
    Each non-bit-field member of a structure or union object is aligned in an implementation defined manner appropriate to its type.
    It would be a weird machine that introduced padding between an array of T followed by a T.

    But if you're that uncomfortable, throw in the __attribute__((__packed__));

    Does '__attribute__((__packed__));' guarantee that there are 0 bytes of padding, or just a "best effort" according to the implementation rules?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Feb 2022
    Location
    Canada, PEI
    Posts
    103
    Thanks for help and pointers Salem. You really know your C.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 6
    Last Post: 05-17-2013, 10:52 PM
  2. Replies: 2
    Last Post: 03-20-2012, 08:41 AM
  3. Replies: 2
    Last Post: 10-30-2009, 08:55 AM
  4. Replies: 7
    Last Post: 05-11-2008, 10:57 AM
  5. zero terminated array
    By Laserve in forum C Programming
    Replies: 12
    Last Post: 06-27-2005, 12:20 AM

Tags for this Thread