Search code examples
carraysmacosvectorcc

Array in C and null character


I'm doing an exercise proposed by the book "The C Programming Language" by Brian W. Kernighan and Dennis M. Ritchie concerning the array. The exercise wants a program that is able to receive lines of text as input and display those that exceed 80 characters. For convenience here I have defined a maximum of 3 input lines, 20 as the maximum length and 5 as the border beyond which to display.

The program works well, the "printValues" function allows me to see which inserted lines exceed 5 characters, but my curiosity led me to see if indeed the null character (/ 0) is put in the unused spaces of the vectors. With my surprise the output is varied; if I use an input like this:

one
two
helloworld

the output for the first line will be:

nomi[0][0]=o
nomi[0][1]=n
nomi[0][2]=e
nomi[0][3]=\0
nomi[0][4]=?
nomi[0][5]=
nomi[0][6]=\0
nomi[0][7]=\0
nomi[0][8]=\0
nomi[0][9]=?
nomi[0][10]=c
nomi[0][11]=
nomi[0][12]=
nomi[0][13]=\0
nomi[0][14]=\0
nomi[0][15]=\0
nomi[0][16]=
nomi[0][17]=\0
nomi[0][18]=\0
nomi[0][19]=\0

nomi[1][0]=t
nomi[1][1]=w
nomi[1][2]=o
nomi[1][3]=\0
nomi[1][4]=\0
nomi[1][5]=\0
nomi[1][6]=\0
nomi[1][7]=\0
nomi[1][8]=\0
nomi[1][9]=\0
nomi[1][10]=\0
nomi[1][11]=\0
nomi[1][12]=\0
nomi[1][13]=\0
nomi[1][14]=\0
nomi[1][15]=\0
nomi[1][16]=\0
nomi[1][17]=\0
nomi[1][18]=\0
nomi[1][19]=\0

nomi[2][0]=h
nomi[2][1]=e
nomi[2][2]=l
nomi[2][3]=l
nomi[2][4]=o
nomi[2][5]=w
nomi[2][6]=o
nomi[2][7]=r
nomi[2][8]=d
nomi[2][9]=\0
nomi[2][10]=\0
nomi[2][11]=\0
nomi[2][12]=\0
nomi[2][13]=\0
nomi[2][14]=\0
nomi[2][15]=\0
nomi[2][16]=\0
nomi[2][17]=\0
nomi[2][18]=\0
nomi[2][19]=\0

making some tests I realized that only in the first line I have some strange characters in the empty cells of the vector. Can someone explain it to me?

sorry for my English.

#include <stdio.h>
#define MAXNAMES 3
#define MAXNAMESLENGHT 20
#define HIGHERTHAN 5

void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]);
void printIndexs(char names[][MAXNAMESLENGHT]);

int main() {
    char names[MAXNAMES][MAXNAMESLENGHT];   
    char provisionalName[MAXNAMESLENGHT];
    int i, e, c;

    for(i = 0; i <= MAXNAMES - 1; i++) {
        for(e = 0; e <= (MAXNAMESLENGHT - 2) && (c = getchar()) != EOF && c != '\n'; ++e) {
            names[i][e] = c;    
        }
        names[i][e] = '\0';
    }

    printValues(names, provisionalName);
    printIndexs(names);

    return 0;
}

void printValues(char names[][MAXNAMESLENGHT], char provisionalName[]) {
    printf("________________________________________");
    printf("\nI nomi che superano i %d caratteri sono:\n", HIGHERTHAN);

    int i, e;
    char flag = 'F';

    for(i = 0; i <= MAXNAMES - 1; ++i) {
        for(e = 0; e <= MAXNAMESLENGHT - 1 && names[i][e] != '\0'; ++e)
            provisionalName[e] = names[i][e];

        provisionalName[e] = '\0';
        if(e > HIGHERTHAN) {
            flag = 'T';
            printf("%s\n", provisionalName);
        }       
    }
    if(flag == 'F') printf("nessuno\n");
}

void printIndexs(char names[][MAXNAMESLENGHT]) {
    printf("________________________________________");
    printf("\nIndici:\n");

    for(int i = 0; i <= MAXNAMES - 1; ++i) {
        for(int e = 0; e <= MAXNAMESLENGHT - 1; ++e) {
            if(names[i][e] == '\n')                                 // return (\n)
                printf("names[%d][%d]=\\n\n", i, e);
            else if(names[i][e] == '\0')                            // null character (\0)
                printf("names[%d][%d]=\\0\n", i, e);
            else
                printf("names[%d][%d]=%c\n", i, e, names[i][e]);    // carattere
        }
        printf("\n");
    }       
    printf("\n");
}

Solution

  • Objects defined inside functions without qualifiers like static are not automatically initialized. (Your arrays are objects.) Commonly, compilers use the stack for such objects (but they may use processor registers and do various optimizations besides using the stack simply). The data you are seeing in the area is merely leftover data from previous use of the stack. (Although main is the first routine executed in your C program, there is startup code that is actually executed before main, to set up the C environment for your program. It leaves some data on the stack.)

    The elements of your array are never “empty.” C has no value that means “empty” for char objects.1 C does not automatically initialize your array to be “empty” or to have zero values in its elements. When you defined the array, all you got was the guarantee there was storage you could access—you did not get any guarantee about what was in that storage.

    Footnote

    1 The semantics of C are complicated, and there are situations in which the value of an object is unspecified, which means not only that its value is not determined by the rules of C but that the program might act as if the object did not have a fixed value (it could appear different each time you used it).