0

This must be a very simple question, but I'm finding it weirdly hard to search for the answer.

In C, I've written the following strncpy-like function:

int mystrncpy(char* s, char* t, int n) {
    // copies at most n characters of t into s, assuming s is long enough

    while (n > 0 && (*t != 0)) {
        *(s++) = *(t++);
        n--;
    }

    // at this point, either n=0 (in which case we ran out of string to copy)
    // or *t = 0 (in which case we now need to null-terminate the string)
    *s = 0;

    return 0;
}

(It differs from strncpy in that it always ensures s is null-terminated at the end, and its arguments have been swapped around relative to strncpy.)

Now, if I call it as follows:

int main() {
    char s[5] = "hello";
    char* t = "oppagangnamstyle";

    mystrncpy(s, t, 10);

    printf("%s\n", s);
    return 0;
}

I expected to get some kind of "attempted to access element 5 of s" error, because s is allocated to be only five characters long.

What actually happens is that "oppagangna" is printed, and the program returns with exit code 0.

When I step through with the debugger, in mystrncpy, the character s points to is successively 'h', 'e', 'l', 'l', 'o', '\0', '\0', …

Is it just fluke (or, which comes to the same thing, the compiler/operating system being unexpectedly nice to me) that s happens to have zeros after it in memory, which are happy to be filled with more elements during the execution of mystrncpy? Or have I misunderstood something else?

Patrick Stevens
  • 569
  • 3
  • 17
  • Also look at all the "linked" and "related" questions there. This is asked extremely frequently. The short version is: undefined behavior. (Read about it if you're not familiar with the term.) – Mat Aug 02 '16 at 11:54
  • Thank you; I was sure it must be asked all the time, and I failed to check the updated "linked questions" after I'd finished composing the question. Sorry. – Patrick Stevens Aug 02 '16 at 11:57
  • It also differs from `strncpy` in that is is not `const`-safe. It is fine to define your own version of a standard function, but 1) don't change the established interface 2) Qualify paramters `const` where possible. 3) If you want a padded armchair with soft cushions, don't use C! 4) Why do you think a **pointer** to a single element of an array has any knowledge about the length of the whole **array**? – too honest for this site Aug 02 '16 at 12:44
  • @Olaf This is an exercise from K+R, in which I am following their conventions; that is why the interface differs, and also why it is not `const`-safe. Sadly I must use C for certain embedded systems :( I wasn't expecting the pointer to have knowledge about the length, but I was expecting an error to be thrown by the operating system or at least to be warned by the compiler, rather than just the apparently-undetectable undefined behaviour that actually happened. – Patrick Stevens Aug 02 '16 at 12:48
  • Rev1, I suppose? Anyway, even K&R rev 2 is far outdated. It does not even cover C99, less the current version of the C standard. It also includes bad practice in some places. Get a more recent book! Not sure what sad about using C in general, less for embedded systems, but there are very well recent C compilers, or at least some which support C99. One of the best included: gcc. And on embedded systems, there typically is no OS or just some library-like minimal OS functionality. You should know that. And how should the compiler warn about run-time issues? – too honest for this site Aug 02 '16 at 12:50
  • @Olaf It's edition 2. Noted; thanks. – Patrick Stevens Aug 02 '16 at 12:50
  • Tell me if you find a compiler which does, because it solved the halting problem! And yes, that's exactly what **undefined** like in "undefined behaviour" means! Not sure if it is there, but any programming book should start with "It is the responsibility of the programmer to write correct code. If you expect the compiler (or any other tool) to guarantee this, you might want to learn gardening or collect stamps instead". – too honest for this site Aug 02 '16 at 12:53

0 Answers0