Zcy
Zcy

Reputation: 75

Is there a terminating character (NOT EOF) at the end of the file which will be read as the last char?

I was trying to read a file into a string with the following code. I assigned 5 bytes for the char *a and actually read a file with more than 5 chars. However, the output still print the correct file contents without any garbage value or missing value.

#include <stdio.h>
#include <stdlib.h>

#define INPUT_SIZE 5

int main() {

        char *a = malloc(INPUT_SIZE);
        FILE *fp = fopen("text", "r");
        if (fp == NULL) {
                perror("Unable to open the file");
        }

        char *b = a;
        char c;
        int i = 0;
        while ((c = fgetc(fp)) != EOF) {
                *b++ = c;
        }

        printf("%s", a);
        free(a);
        fclose(fp);
        return 0;
}

The input file is

abc
def
g

And the output is exactly the same as the input file.
Since normally there should be a '\0' at the end of the char * to show where the string end. But in this occasion, there is no explicit '\0' in the char *a. So I wonder if there is an '\0' at the end of the file which was read as the last char ?

Upvotes: 1

Views: 155

Answers (1)

Brian Tracy
Brian Tracy

Reputation: 6831

This is a situation where the results may look correct, but you are simply getting "lucky" with the output of your program.

First, when you call malloc(INPUT_SIZE), your implementation of libc will generally not allocate just 5 bytes, but actually some multiple of 8 bytes (like 16 or 32, depends on the platform [see unexpected output of size allocated by malloc in C). This extra data contains possible padding bytes after your data and metadata before and after your requested block. This is done for alignment and bookkeeping purposes, but the takeaway is that you get more than you ask for when you call malloc.

You should not take advantage of this implementation detail to fit more data into a malloced region that you requested as that space is not really yours for the taking. By writing past the end of your buffer, you risk scribbling on important data that your allocator needs to ensure consistency.

Second, the null terminator behavior you are seeing is simply you getting lucky and receiving a zeroed out section of memory from malloc. This is not always guaranteed, and the next time you run the program, your buffer could come back from malloc filled with random values, instead of 0. If you want pre-zeroed memory, use calloc instead.

So to answer the question, no there is not a null terminator at the end of files, your program is just using undefined behaviors of the standard library to make it look like there is.

Upvotes: 2

Related Questions