Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how come printf is printing a non null terminated string? [closed]

Tags:

c

The c programming book says that my string must be null terminated to print it using printf but still the following program prints the string despite it being non null terminated !!

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

int main(){
    int i ;
    char str[10] ;
    for(i = 0 ; i < 10 ; i++ ) {
        str[i] = (char)(i+97) ;
    }

    printf("%s",str) ;
}

I am using codeblocks IDE .

like image 928
Nikunj Banka Avatar asked Dec 01 '12 04:12

Nikunj Banka


4 Answers

It's undefined behavior to read beyond the bounds of an array, you were actually unlucky it didn't crash, if you run it enough times or call it in a function it may (or may not) crash, you should always terminate the string, or use a width specifier:

printf("%.10s", str);
like image 136
iabdalkader Avatar answered Sep 26 '22 13:09

iabdalkader


Whatever is after the 10th element of str happens to be a null. That null is outside the defined bounds of the array, but C doesn't have array bounds checking. It's just luck in your case that that's how it worked out.

like image 33
Andy Lester Avatar answered Sep 24 '22 13:09

Andy Lester


According to C standard the printf function prints the character in the string until it finds a null character. Otherwise after the defined array index what it will do is not defined. I have tested your code. and after printing "abcdefghij it prints some garbage value.

like image 43
Debobroto Das Avatar answered Sep 24 '22 13:09

Debobroto Das


If you do other things before that call, your stack area will contain other data than an unused one. Imagine that:

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

int use_stack(void) {
   char str[500];
   memset(str, 'X', sizeof(str));
   printf("Filled memory from %p to %p.\n", &str, &str+sizeof str);
}

void print_stuff() {
    int i;
    char str[16]; // changed that so that 10..15 contain X
    for(i = 0; i < 10; i++) {
        str[i] = (char)(i+97);
    }

    printf("%s<END>",str); // have a line break before <END>? Then it comes from i.
    printf("&str: %p\n", &str);
    printf("&i: %p\n", &i);
    // Here you see that i follows str as &i is &str + 16 (0x10 in hex)
}

int main() {
    use_stack();
    print_stuff();
}

your stack area will be full of Xes and printf() will see them.

In your situation and your environment, the stack is coincidentically "clean" on program start.

EDIT: This may or may not happen. If the compiler puts the variable i immediately after the array, your data will nevertheless be NUL-terminated, because the first byte is the value of i (which you happen to print as well -it might be a libne break in your case - and the 2nd byte is a NUL byte. Even if this is the case, your code invokes UB (undefined behaviour).

Can you have a look (by piping the program output into hexdump or alike) if your output contains a 0A character? If so, my guess is correct. I just tested it, an on my compiler (gcc) it seems to be the way.

As said, nothing you should rely on.

EDIT2: If you see a line break before <END>, my guess was right. And if you have a look at the pointers now being printed, you can compare their addresses in memory.

like image 38
glglgl Avatar answered Sep 24 '22 13:09

glglgl