私はこのシンプルでわかりやすい (そうであってほしい) コード例を思いつきました。
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/* function header definitions */
char* getString(); //<- with malloc (good practice)
char * getStringNoMalloc(); //<- without malloc (fails! don't do this!)
void getStringCallByRef(char* reference); //<- callbyref (good practice)
/* the main */
int main(int argc, char*argv[]) {
//######### calling with malloc
char * a = getString();
printf("MALLOC ### a = %s \n", a);
free(a);
//######### calling without malloc
char * b = getStringNoMalloc();
printf("NO MALLOC ### b = %s \n", b); //this doesnt work, question to yourself: WHY?
//HINT: the warning says that a local reference is returned. ??!
//NO free here!
//######### call-by-reference
char c[100];
getStringCallByRef(c);
printf("CALLBYREF ### c = %s \n", c);
return 0;
}
//WITH malloc
char* getString() {
char * string;
string = malloc(sizeof(char)*100);
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
printf("string : '%s'\n", string);
return string;
}
//WITHOUT malloc (watch how it does not work this time)
char* getStringNoMalloc() {
char string[100] = {};
strcat(string, "bla");
strcat(string, "/");
strcat(string, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", string);
return string; //but after returning.. it is NULL? :)
}
// ..and the call-by-reference way to do it (prefered)
void getStringCallByRef(char* reference) {
strcat(reference, "bla");
strcat(reference, "/");
strcat(reference, "blub");
//INSIDE this function "string" is OK
printf("string : '%s'\n", reference);
//OUTSIDE it is also OK because we hand over a reference defined in MAIN
// and not defined in this scope (local), which is destroyed after the function finished
}
コンパイルすると、[意図した] 警告が表示されます。
me@box:~$ gcc -o example.o example.c
example.c: In function ‘getStringNoMalloc’:
example.c:58:16: warning: function returns address of local variable [-Wreturn-local-addr]
return string; //but after returning.. it is NULL? :)
^~~~~~
...基本的に、ここで話し合っていることです!
私の例を実行すると、次の出力が得られます。
me@box:~$ ./example.o
string : 'bla/blub'
MALLOC ### a = bla/blub
string : 'bla/blub'
NO MALLOC ### b = (null)
string : 'bla/blub'
CALLBYREF ### c = bla/blub
仮説:
これは、ユーザー @phoxis によって非常にうまく回答されています。基本的に次のように考えてください: {と}の間のすべてがローカルスコープであるため、C 標準では外部は「未定義」です。malloc を使用すると、スタック (関数スコープ) からではなく、ヒープ (プログラム スコープ) からメモリを取得するため、外部から「可視」になります。それを行う 2 番目の正しい方法はcall-by-referenceです。ここでは、親スコープ内で var を定義しているため、STACK を使用しています (親スコープがmain()であるため)。
概要:
それを行う3つの方法、そのうちの1つは偽です。C は、関数が動的にサイズ変更された文字列を返すようにするのはちょっと不器用です。malloc してから解放するか、参照渡しにする必要があります。またはC++を使用してください;)