char* str1="string";
これはstr1
ポインタになります。文字列リテラルの最初の文字を指します。const
文字列リテラルを変更することは許可されていないため、次のように定義する必要があります。
const char *str1 = "string";
..。
char str2[7]="string";
これにより、(ポインタstr2
ではなく)の配列がchar
作成され、文字列リテラルの内容がその配列にコピーされます。const
;として定義する必要はありません。配列自体は書き込み可能です。サイズを省略して、初期化子によって決定されるようにすることもできます。
char str2[] = "string";
次に(終了の場合はプラス1の場合はsizeof str2 == 7
6バイト)。"string"
'\0'
これ:
char* str3=(char)malloc(sizeof(char)*7);
正しく書かれておらず、コンパイルすらすべきではありません。少なくとも、コンパイラから警告を受け取る必要があります。malloc()
の結果をタイプにキャストしていますchar
。あなたはそれをに変換する必要がありますchar*
:
char *str3 = (char*)malloc(sizeof(char) * 7);
ただし、キャストは不要であり、場合によってはエラーをマスクできます。comp.lang.c FAQの質問7.7以降を参照してください:
char *str3 = malloc(sizeof(char) * 7);
しかしsizeof(char)
、定義上は1なので、次のように書くことができます。
char *str3 = malloc(7);
malloc()
メモリを割り当てますが、初期化されないため、をstr3
指す文字列を出力しようとすると、ガベージが発生します。割り当てられたスペースに終了ヌルが含まれていない場合は、実行時のクラッシュが発生します。文字'\0'
。strcpy()
たとえば、次のように初期化できます。
char *str3 = malloc(7);
if (str3 == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
strcpy(str3, "string");
コピーするデータが割り当てられたスペースより大きくならないように十分に注意する必要があります。(いいえ、`strncpy()はこの問題の答えではありません。)
void main()
間違っている; する必要がありますint main(void)
。教科書で使用するように指示された場合void main()
は、より良い教科書を見つけてください。その作者はCをよく知りません。
また、使用しているライブラリ関数に適切な#include
ディレクティブが必要です:<stdio.h>
for printf()
、<stdlib.h>
for exit()
、malloc()
および<string.h>
for strcpy()
。各関数のドキュメントには、含めるヘッダーが記載されているはずです。
私はこれが吸収することがたくさんあることを知っています。すぐにそれをすべて理解することを期待しないでください。
comp.lang.cのFAQについて触れました; これは優れたリソースであり、特にセクション6では、配列とポインター、およびそれらの間のしばしば混乱する関係について説明しています。
質問3については、C関数から文字列を返す方法は、Cがメモリ割り当てを行う方法(基本的には自分で管理する必要があります)のため、驚くほど複雑であることがわかります。ローカル変数へのポインターを安全に返すことはできません。関数が戻ると変数が存在しなくなり、呼び出し元にダングリングポインターが残るため、を返すのstr2
は危険です。文字列リテラルを返すことは問題ありません。これは、プログラムの実行全体に存在する匿名配列に対応しているためです。で配列を宣言し、その配列static
へのポインタを返すことができます。または、を使用することもできますmalloc()
(これは最も柔軟なアプローチですが、呼び出し元は次のことを行う必要があります。free()
メモリ)、または関数が結果をコピーするバッファへのポインタを呼び出すように呼び出し元に要求することができます。
一部の言語では、文字列値を作成して、関数から返すだけです。あなたが今発見しているように、Cはそれらの言語の1つではありません。