2

Below is the program to copy the one string to another. I would expect the following program to give me a warnig or an error but it works just.

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void strcp(const char *source,char *dest)
{
    while(*source!='\0')
    {
        *dest++=*source++;
    }
//  *dest='\0';
}
int main(void)
{
    char source[]="This is a test string";
    int len=strlen(source);
    char *dest = (char *)calloc(len,sizeof(char));
    strcp(source,dest);
    printf("\n The destination now contains ");
    printf("%s",dest);
    return 0;
}

Here I ve commented out *dest='\0' So *dest doesnot contain any null character at the end of the string But how is then the printf statement in the main function working fine cause I guess all function which involves string rely on the '\0' character to mark the end of string ?

P.S. I got the answer of my first question but none of the answer talked about this question below And also I found it strange that i could use pointer dest directly with %s specifier in the printf I just wrote the last printf in the main to check will it work or not cause earlier i was using

char *temp=dest
while(*temp!='\0')
{
   printf("%c",*test++);
}

In place of printf("%s",dest)

13
  • DO not use calloc() for this situation, you don't need to initialize all items to 0 because you are going to overwrite them immediately, and using calloc() may hide bugs from memory debuggers, also Do not cast it's return value Commented Jun 8, 2015 at 12:52
  • 1
    Your code invokes Undefined Behavior. It means that anything can happen. It need not necessarily be a crash or a segfault or anything else. And In C, don't cast the result of malloc(and family) Commented Jun 8, 2015 at 12:54
  • @CoolGuy Is undefined behaviour cause of commenting out *dest='\0' ? Commented Jun 8, 2015 at 12:55
  • 1
    @DavidHaim but the effect of ++ is sequenced after the evaluation of the expression, isn't it? Commented Jun 8, 2015 at 13:02
  • 3
    @DavidHaim Although ugly and bad practice, copy lines such as *dest++=*source++; are common in C, and also well-defined. It is completely equivalent to *dest = *source; dest++; source++;. And because the latter form is completely 100% equivalent, one should use the latter so one doesn't confuse the reader. It is good programming practice never to mix the ++ operators together with other operators, because in many other cases, doing so leads to bugs and undefined behavior. Commented Jun 8, 2015 at 13:06

2 Answers 2

4

Because undefined behavior is undefined?

By omitting the terminating '\0' and then passing the "string" to printf() with an "%s" specifier, your program invokes undefined behavior.

I write "string" above, because without the terminating '\0' it's not a string, it's just a sequence of bytes, when you terminate a sequence of bytes with a '\0' then, it becomes a string.

Since you can't predict what is going to happen, one of the things that could happen is that it works.

Although your program has more issues

  1. You are allocating less space than required. You need strlen() + 1, because of the '\0' terminator, this is the real cause of undefined behavior in your program.

  2. You are calling calloc() wrong, it should be

    dest = calloc(1, 1 + len);
    

    note that I don't write sizeof(char) because it's superflous, it's always 1, it has to be as it's mandated by the c standard.

    In your version, you are allocating one item of size len, when you really want len items of size 1.


Notes and Recommendations:

  1. DO not use calloc() for this situation, you don't need to initialize all items to 0 because you are going to overwrite them immediately, and using calloc() may hide bugs from memory debuggers.

  2. Do not cast void * in c.

Sign up to request clarification or add additional context in comments.

10 Comments

Just asking, as the memory is "zeroed" by calloc(), is not null-terminating an issue here?
It's still undefined behavior because there is no space for the '\0', and anyway I think it's good to explain why no one can expect anything from undefined behavior to be defined.
I agree with you in case of less memory allocation, but if used calloc() with enough memory to hold the string and the null-terminator properly. I don't see the reason why an explicit null-terminator is required. Can you reply please?
@NatashaDutta If the calloc() ed memory was large enough to hold the string (A valid string in c which is null terminated ) then there was no UB. Since that is no the case we see UB here
While using calloc() is needless here, how does it "hide" bugs from memory debuggers?
|
2

All strings in C have a special terminating character '\0', that is not counted when using strlen. However, all strings must still have this special termination character, or all string functions will go past the end of the string.

When allocating memory for a string, you need to add space for this terminating character, as well as adding it last.

So instead of allocating only len characters, you need to allocate len + 1 characters. And remove the comment in your strcp function, it's needed to add the terminator.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.