0
  OS: Linux
  CC: GCC 4.8.2

Targer: Change size of char* -> to smaller

PROBLEM: Size after change is same...

line is string with data...

Code fragment:

 char * tmp = NULL;

[...]

 tmp = malloc(sizeof(char) * 8);

 strncpy(tmp, line, sizeof(char) * 8);

[...]

Now smaller tmp:

 printfTest(tmp); //Content dump

 nevAddr = realloc(tmp, sizeof(char) * 3);

 if(newAddr != NULL)
 {
    tmp = newAddr;
 }
 else
 {
     free(tmp);
     puts("Realloc - FAIL");
     exit(VALID);
 }

 printfTest(tmp); //Content dump

printfTest function:

  void printfTest(char * data)
  {
      printf("Test: '%s'", tmp);
  }

Result:

 Test: 'BLABLABL' //8chars
 Test: 'BLABLABL' //8chars (!? Why)

Where is my fail?

Jan Czarny
  • 916
  • 1
  • 11
  • 29
  • 2
    `sizeof(char)` is `1`. And why do you expect `realloc` to modify your buffer? – Carl Norum Feb 03 '15 at 19:46
  • 1. I need cut string lenght to 3 chars and pass ref. to function. 2. Release unused memory – Jan Czarny Feb 03 '15 at 19:53
  • What do you expect to happen to the string? It just happens that `realloc` is _not required_ to move the memory block during the reallocation. Anyway, you're responsible for handling the data - null-terminate the string again. – jweyrich Feb 03 '15 at 19:53
  • 3
    your second printf invokes undefined behaviour, so everything is possible. – mch Feb 03 '15 at 19:55
  • So better idea is add '\n' at the 3 pos [0, 3]? It's only solution? But.. '\n' - waste of memory... – Jan Czarny Feb 03 '15 at 19:57
  • 1
    Not `\n`. You need `\0`. And if you have only 3 bytes, you can't access any index greater than 2 (remember indices start at 0). – jweyrich Feb 03 '15 at 20:02
  • [`strncpy()` is not a "safer" `strcpy()`](http://the-flat-trantor-society.blogspot.com/2012/03/no-strncpy-is-not-safer-strcpy.html). – Keith Thompson Feb 03 '15 at 20:14

1 Answers1

4

You are confusing two different concepts of "size". Here's a character array with 100 chars:

char x[100]; // sizeof(x) / sizeof(x[0]) == 100
strcpy(x, "short string");

The size of the x array is still 100, even though the length of the string, strlen(x) is just 12.

(Actually, maybe you could benefit from a basic introduction to strings in C, like this tutorial instead of reading this answer. )

When you print a string in C, the software keeps printing characters until it finds a \0 (the null character), even if this involves reading pass the end of the array. In fact, the compiler cannot know if it has gone past the array. It just blindly continues until the finds the null character.

The strcpy above actually writes 13 bytes, not 12. It prints the 12 characters and the null character on the end.

This means that an array in C that is intended to hold a string must actually have one extra space to hold the null character. If you want to store "world", you must have at least six characters

char y[5];
strcpy(y,"hello"); // undefined behaviour, as y is too small
char z[6];
strcpy(z,"hello"); // OK

(And no, strncpy does not fix this problem. "No null-character is implicitly appended at the end of destination if source is longer than num. ")

Anyway, to return to your question. One way to shorten the string would be to write a null character in the appropriate place:

char x[100];
strcpy(x, "hello");
printf("%s\n", x); // prints "hello"
x[3] = '\0'; // replace the second 'l' with the null
printf("%s\n", x); // prints "hel"

To change the string, you need to change the bytes, perhaps with code like mine, or perhaps with another strcpy.

Simply calling realloc does not actually change any of the bytes in the string, it merely frees some of the memory nearby.

Aaron McDaid
  • 26,501
  • 9
  • 66
  • 88