すいません。たくさんのご指摘ありがとうございます。
ご指摘と反省点、また基本となる知識も踏まえたうえで最後に疑問を書かせていただきます。最初の方は自分の反省なので基本無視して大丈夫です。疑問の場所はコードの下です。もし間違いがありましたらご指摘をお願いします。
ポインタで関数の値を返すはずがvoid型となっているため、値が返されない。
つまり、参照返しができていないということが問題
string_duplicate関数でポインタ型変数char *aのメモリ内にあるデータが、
引数として関数に渡されているにも関わらず、関数内の文字列cがそのままアドレスaに代入されてしまって、10バイトの文字列データが使われない状態となっている。
その理由がwhile ( a!= '\0') 内にあるc = a;がアドレスを代入していることが原因。値を代入するにはc=*aをする必要がある。
ここで混同してしまったのが配列において、aが配列のポインタ変数となっている。
そのため*を付けるつけないの意味合いが全く異なってしまうことになる。*有りは配列のデータにある値を代入する。
またchar型の領域を確保したがfree関数を使わずに値を解放せずにしている。つまりいらなくなったaの配列のデータを消去せずにいる。
自分で気づかなかったことが、メイン関数に確保されているchara[10]のメモリと
string_duplicateのchar aのメモリの場所が全く異なった場所にある。
細かく書くと、
このプログラムだとメイン関数内にあるchar a[10]="ss"は
a[0]='s'
a[1]='s'
とメイン関数内に1バイト(8ビッド)ずつ格納されている。ここでchar型のバイト数が1バイトのため、例えばa[0]のアドレスが0019FF53とするとき、
a[1]のアドレスが0019FF54である。一バイトの差のため+1されている。また、逆のパターンのー1になることもある。
そこで、char c =a;文字列データ "ss"はメモリに格納される。そのときに文字列データ "ss"が格納されているメモリの先頭のアドレスがポインタ変数cに格納されるようになる。つまり、char *cは初期化されるようになる
string_duplicate(c)を用いて、変数aが変数cに代入されるときに、変数aのメモリのデータが変数cの文字列データに格納されるということ。
当然のことながら、変数aのメモリと変数cのメモリが独立した場所にあるということが分かる。
このことに気づかずになんとなくで書いてしまったこともミスの一つである。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> void string_duplicate(char *a) { int i = 0; char* c; c = (char*)malloc(sizeof(char)*10 ); while ( *a!= '\0') { c = a; c++; a++; } } void main() { char a[10] = "ss"; char* c=a; printf("%s\n", c); string_duplicate(c); printf("%s", c); }
そこで、今までの反省を含めた結果のコードです
#include <stdio.h> #include <stdlib.h> char* string_duplicate( char* a) { char* c; c = (char*)malloc(sizeof(char) * 10); while (*a != '\0') { *c = *a; c++; a++; } *c = '\0'; return c; } int main() { char a[10] = "ss"; char* c = string_duplicate(a); printf("%s\n", c); free(c); return 0; }
ここでepistemeさんとほぼ同じでchar *result =cとreturn resultを除いたこと以外はすべて同じです。関数もポインタの値を返すためにchar *型の関数にしました。
なぜ、関数内に新たなポインタ変数が必要なのでしょうか。ここではresultの事を指しています。コンパイルは通りますが例外が起こり実行できない状態となっております。新たに生成されたchar型の領域を
仮引数の値aをそのまま代入しましたが、returnでポインタ変数cの値をそのまま返すことができないのでしょうか?新たなポインタ変数が必要な理由を教えてください。





回答3件
あなたの回答
tips
プレビュー