1

I have this simple program which works correctly.

#include<stdio.h>

int main(int argc, char *argv[]) {
    int mystrlen(char *s);
    char s[6] = "ABCDEF";
    printf("%d", mystrlen(s)); // print 6
}

int mystrlen(char *s) {
    char *p=s; /*Assigning the starting value to p */
    while(*s != '\0') {
        s = s + 1;
    }
    return s-p;
}

The only change which I will make is instead of int main(int argc, char *argv[]), I will use int main(void), which I am not sending any command line arguments.

Now, the same program completely misbehaves for me!

#include<stdio.h>

int main(void)
{
    int mystrlen(char *s);
    char s[6]="ABCDEF";
    printf("%d",mystrlen(s)); // prints 8 !!

}

int mystrlen(char *s) {
    char *p=s; /*Assigning the starting value to p */
    while(*s != '\0') {
        s = s + 1;
    }
    return s-p;
} 

Can anyone explain why this is the case? It was the last thing I expected to be wrong in the program. Is this compiler dependent behavior? FWIW, I am using gcc

Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
  • 6
    Your source array does not allocate enough space for the terminating null. Make your `s` array `s[7]` – Joe Apr 15 '14 at 14:17
  • 5
    Better yet, make it `s[] = "..."` and let the compiler make it the correct size. – William Pursell Apr 15 '14 at 14:18
  • 2
    You have not provided enough room for the null terminating char, [the standard says for sized arrays it will only append a null terminating char it if there is room](http://stackoverflow.com/questions/20694796/no-compiler-error-when-fixed-size-char-array-is-initialized-without-enough-room/20694830#20694830). So basically undefined behavior. If you had left the array unsized you would have been ok. – Shafik Yaghmour Apr 15 '14 at 14:18
  • Your first piece of code works by mistake. – Sergey Kalinichenko Apr 15 '14 at 14:19
  • Your first program works by chance, not by design. – Jens Apr 15 '14 at 14:24

3 Answers3

6

Undefined behavior: you do not allocate space for the null terminator. You should enable warnings in your compiler, which should catch this.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
3

Your problem lies with the statement char s[6]="ABCDEF";. There's no space for a null terminator which is what all the standard library string functions (and your function mystrlen) require.

Use char s[]="ABCDEF"; instead. In doing this, the null terminator is added for you automatically - that's how quoted literals work: think of the closing quotation as including an implicit \0. Also, C will calculate the size of the array for you so there's no need to specify that.

Formally the behaviour of your program is currently undefined. It's not just compiler-dependent but anything dependent.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • 1
    I don't believe explicitly putting null in the string literal is necessary, there just needs to be room for it. And wouldn't it be easier and safer to just not specify the array size? `char s[] = "ABCDEF";` – Fred Larson Apr 15 '14 at 14:24
  • @FredLarson: Of course you're correct. I think I'll amend a little. – Bathsheba Apr 15 '14 at 14:25
2

It would be an undefined behavior as your source array s has not enough space for terminating null ie, \0. Enable your compiler warnings.

You can change your array like

char s[7]="ABCDEF";

From the C99 standard

An array of character type may be initialized by a character string literal, optionally enclosed in braces. Successive characters of the character string literal (including the terminating null character if there is room or if the array is of unknown size) initialize the elements of the array

Rahul Tripathi
  • 168,305
  • 31
  • 280
  • 331