2

I'm trying to mimic the way strcpy works, by writing my own function. My question is more specific to the size of an array.

I'm trying to copy contents of stringA into stringB, which I have declared as size of 1.

  1. Shouldn't I get an error saying stringB is too small to hold stringA? The reason, I suspect I don't get an error is because an array name StringB is converted to a pointer?

  2. Why is char str[1] = "abcd" illegal then ?

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void strCopy(char *source,char *destination) {
        printf("%p,%p\n",source,destination);
        while (*source != '\0') {
            *destination = *source;
            printf("> %c,%p,%p\n",*source,source,destination);
            source++;
            destination++;
        }
    
        *destination = '\0';
    }
    
    int main(int argc,char *argv[]) {
       char stringA[] = "To be or not to be.";
       char stringB[1];
       strCopy(stringA,stringB);
       printf("StringB: %s\n",stringB);
    
       return (0);
    }
    
fuz
  • 88,405
  • 25
  • 200
  • 352
hmmm
  • 93
  • 2
  • 9
  • That isn't how the language works. You can (and have) freely shot yourself in the foot, and with it produced an *ill-formed* program. It executes *undefined behavior*, and with that, **no** expectations of anything defined (the loose "definition" of *chaos* not withstanding) is sound. – WhozCraig Oct 04 '14 at 12:37
  • Use `valgrind`. Then you'll see you are doing something bad. – skywall Oct 04 '14 at 12:49
  • Thanks,do i need to use the memcheck feature of valgrind to be precise ? – hmmm Oct 05 '14 at 18:03

2 Answers2

2

1) Shouldn't i get an error saying stringB is too small to hold stringA ?

you didn't get any error because of compilers memory allocation scheme. there is a good chance that compiler would have allocated memory to stringB first and stringA later. so consider if stringB is having memory location 1000 (only one byte), then stringA will be having memory locations from 1001 to 1020(including space for NULL). so when ever you try to copy contents from stringA to stringB into your function, it actually copies from location 1001 to 1000, then 1002 to 1001 and so on, so according to your program you must be having output as shown if this is the case. it seems that you are printing addresses of strings. see addresses of strings and check if this is the case. again this is merely consequence that string2 is allocated memory first than stringA. it is not neccesary that on all the variations of compilers, this will be the answer everytime.

stringB : To be or not to bee

stringA : o be or not to bee

now you are not getting error because both arrays are present in stack frame and both are accessed by pointers, so compiler doesn't care about sizes of array when data copy is done using pointers. it just copies till you are in allowed memory space. if this is not the case and stringA would have been present first in memory, then you would get segmentation fault.

2) Why is char str[1] = "abcd" illegal then ?

not this is very different case than your case, you are allocating only one byte to string, and initializing it with more characters than its size. note that your data copy is being done at run time, but this initialization is at compile time, so compiler knows size of array and will show you a warning, it is not illegal but compiler only assigns first character to string and you may get unpredictable result as there no space left for NULL character at last.

Chintan Patel
  • 310
  • 1
  • 2
  • 11
  • The output i get is: StringB: To be or not to be StringA: o be or not to be .I looked at the addresses and 'T' from stringA gets overwritten by 'O' from StringB. Why would the compiler allocate memory for stringB first,why not stringA ? Thanks a lot. – hmmm Oct 04 '14 at 22:44
  • It can be more clear after knowing locations of both strings. Post locations and output in comment. – Chintan Patel Oct 04 '14 at 22:46
  • > t,0x7fff6f334d70,0x7fff6f334d6f > o,0x7fff6f334d71,0x7fff6f334d70 > ,0x7fff6f334d72,0x7fff6f334d71 > b,0x7fff6f334d73,0x7fff6f334d72 > e,0x7fff6f334d74,0x7fff6f334d73 > ,0x7fff6f334d75,0x7fff6f334d74 > o,0x7fff6f334d76,0x7fff6f334d75 > r,0x7fff6f334d77,0x7fff6f334d76 > ,0x7fff6f334d78,0x7fff6f334d77 # Output Truncated ## Address of A: 0x7fff6f334d70 Address of B: 0x7fff6f334d6f I see that B is allocated memory ahead of A,just wondering whats the reason for the compiler to do this. – hmmm Oct 04 '14 at 22:54
  • Pattern of allocating memory cant be predicted neither should be tried to. If you want to learn new things in c then fine otherwise avoid such programming – Chintan Patel Oct 04 '14 at 23:07
  • Thanks man.I'm actually new to C and i'm glad that i came across this pitfall.If i were to do the above operation correctly,doest it make sense to define StringA and StringB as 'static' inside the main scope ? or should i use malloc()? or declare stringA and B with some size ? Whats the right approach ? – hmmm Oct 05 '14 at 18:01
1

1) Shouldn't i get an error saying stringB is too small to hold stringA ?

You may not get an error depending on where in the memory space stringB was placed. If the stringB pointer was placed in the middle of the application's memory then you can certainly write values past its declared bounds. You'll just be overwriting memory that was used to store some other value or function. C/C++ never checks if you went past the array length like some other languages do, e.g. Java.

2) Why is char str1 = "abcd" illegal then ?

Since the behavior of your program is completely undefined based on your implementation it is difficult to describe exactly what is going on.

Also see the following post: why doesn't my program crash when I write past the end of an array?

Community
  • 1
  • 1
Ramón J Romero y Vigil
  • 17,373
  • 7
  • 77
  • 125