C言語 プログラミング

C言語で注意すべき点【C言語プログラミング基礎編(8)】

C言語講座8回目、初心者がやりがちな間違いをまとめてみました。

 

C言語でやりがちなミス

C言語

よく見かけるC言語の勘違い、ミスを幾つか整理しています。

アロケーションしないでポインタを使う


【間違い】
char* p;
strcpy(p, "Hello");
printf("%s\n", p);

通常は、2行目でドカン!
運がわるいと動いてしまって、ある時突然エラーになるので厄介です。
ポインタは、単に領域を指し示すだけなので、キチンと領域を確保して使う必要があります。


【修正後】
char* p;
p = malloc(6); /* Hello 5文字+ヌル文字1バイト分 */
strcpy(p, "Hello");
printf("%s\n", p);
free(p);

ヌル文字分の領域が不足


【間違い】
#define NAME_LEN 6
char name[NAME_LEN];
strcpy(name, "yamada");

これも、アプリケーションが落ちる要因です。


【修正後】
#define NAME_LEN 6
char name[NAME_LEN+1];
strcpy(name, "yamada");

文字列の最後には、ヌル文字'\0'が入るので、実際の文字を確保する領域の長さ+1分の配列確保が必要になります。

ローカル変数のリターン


【間違い】
char* func(const char* s)
{
char buf[128];
strcpy(buf, "hello");
strcat(buf, s);
return buf;
}

関数を抜けたときに、buf の領域は存在しなくなるため、その後、
関数の戻り値を使用すると動作が保証されなくなります。

いくつかの修正方法があります。

【修正方法】

A)静的領域を利用
容易ですが、マルチスレッド等の同時アクセスがある場合には使えません。
また、呼出先で2度呼び出されると、内容が変化することも注意が必要です。

char* func(const char* s)
{
static char buf[128]; /* static とつける */
strcpy(buf, "hello");
strcat(buf, s);
return buf;
}

B)領域をアロケーション
確実であるが、領域のフリー手段の提供など、領域開放についての考慮は必須

char* func(const char* s)
{
char* p;
char buf[128];
strcpy(buf, "hello");
strcat(buf, s);
p = malloc(strlen(buf) + 1); /* +1を忘れずに */
strcpy(p, buf);
return p;
}

C)出力先も引数で受け取る
引数が増えるが、C言語の場合は、これが通常の対応であり、障害も起き難い。
ライブラリ関数もこの形式が多い。
もっとも、出力先には、十分な領域があることが前提であり、汎用ライブラリ化する
場合には、出力先のサイズも渡してサイズチェックをする等考慮が必要である。


char* func(const char* s, char* buf)
{
strcpy(buf, "hello");
strcat(buf, s);
return buf;
}

今回はここまでにします。

C言語の話は、この後も何回かに分けて投稿しますので、興味のある方は引き続きよろしくお願いします。

-C言語, プログラミング

Copyright© SIMPLEONESOFT (BLOG) , 2022 All Rights Reserved.