Return Pointer from function with pointer as param
Nothing is wrong with your thinking - you're absolutely correct. Good work, you're now more qualified in the C programming language than the author of the book.
The book is worthless - 3rd revised edition, and it teaches the antiquated version of C from 3 decades ago with horribly broken examples. You just happened to be lucky with that test4
. Putting the address of the first element of array just suppresses the warning in some compilers, and the array happened to be in the correct position on the stack and not being overwritten. But GCC 8.3 isn't fooled by using an intermediate variable.
In the function
char *test4(char *ptr){
char buffer[10];
ptr = buffer;
strcpy(buffer, "testwert");
return ptr;
}
using the ptr
within the function does in no way affect the pointer outside the function. It worked in the original example because the ptr
was still pointing to the value returned from test3
, which was allocated from heap. When you replace it with ptr = test4(ptr);
you'll get wholly undefined behaviour, as ptr
now points to a variable past its lifetime. And when undefined behaviour happens, then the program might do anything, including (C11 3.4.3p1):
[...] ignoring the situation completely with unpredictable results [...]
with "unpredictable results" including the possibility of it working "as intended".
The previous bulletin point lists one of the options as
- [Sie verwenden] einen beim Aufruf der Funktion als Argument übergebenen Puffer [...]
i.e. [You'll use] a buffer passed as an argument into the function. For this option, test4
should read
// use the **array** starting from *ptr
char *test4(char *ptr){
// use a **different** string here so that you can verify
// that it actually *works* (max 9 characters!)
strcpy(ptr, "testval 4");
return ptr;
}
or even perhaps
void test4(char *ptr){
strcpy(ptr, "testval 4");
}
with documentation telling that prior to calling this function ptr
should point to an array of at least 10 char
s.
char *test4(char *ptr) {
char buffer[10];
ptr = buffer;
strcpy(buffer, "teswert");
return ptr;
}
This code doesn't do anything else than returning an invalid pointer. Your understanding is correct, the stack pointer returned is invalid and shouldn't be read.
The reason why this "works" is because that pointer isn't actually used.
test4(ptr);
A copy of the pointer is passed and the return value is discarded, so it does nothing. The printed text is from test3
. Case in point, you can change that one "testwert"
and the print you get is the exact same, and if you change the one in test3
it changes both prints. So in other words, the book makes a mistake and hides it with another mistake, and then it doesn't notice all the mistakes because of how poorly it tests the code (if it wouldn't be "testwert"
four times, the errors would be apparent, and of course any compiler worth its salt will issue a warning).
I recommend trashing that book.
With the edited version of ptr = test4(ptr)
it's undefined behavior, so anything might happen. This includes printing the expected output, printing rubbish, crashing the program or worse.