C言語編 目次

 関数設計

 

・関数名の命名規則
・プログラミングに出る!英単語

 ポインタ

 

・データ型とポインタ

 データ型

 

・char *とconst char *は違う
・符号付きと符号なし

 演算子

 

・三項演算子とデータ型の問題

 制御構文

 

・条件式で代入する
・三項演算子を使ったswitch

 構造体

 

・構造体のサイズとアライメント
・構造体メンバのサイズを知る

 配列

 

・配列使用時の注意
・配列の要素数を知る

 メモリ管理

 

・メモリスタック
・動的メモリ確保とメモリリーク

 モジュール設計

 

・モジュール分割
・汎用モジュールとアプリ依存モジュール

 パフォーマンス
  徹底チューニング

 


・どんな処理に時間がかかるのか
・ファイル入出力の効率化
・アルゴリズムを考える1
・アルゴリズムを考える2

 プリプロセッサの便利機能


・2重インクルード防止

 


トップページへ戻る

char *とconst char *は違う

 char *とconst char *は違います(当然)。ではどう違うか明確にわかりますか?一言で言えば「データ型」が違いますね。これについてはC言語編「データ型とポインタ」を見てください。

 さて、「const char *」というデータ型は、書き換えできない(読み取り専用の)文字列に対して使います。簡単に使い方を見てみましょう。

#include <stdio.h>
#include <string.h>

int main(int argc, char* argv[])
{
    char         str[32] = "sample";
    const char   *pstr = str;

    pstr[5] = 'a';              // エラー 書き込みはできない
    strcat(pstr, "program");    // エラー char *とconst char *は互換性がない

    return 0;
}

 「const char *」型の変数pstrを作りました。これは文字列のポインタをあらわしていますが、文字列の内容を後から書き換えることはできません。間違えないでほしいのは、ポインタ変数の内容を書き換えられないということではありませんよ。ポインタがさす文字列が書き換えられないんです。(ポインタ変数の内容は書き換えられます。)

 また、strcat()の第一引数は「char *」型なので、互換性のない「const char *」型は渡すことはできません。

 当然、無理矢理ほかのデータ型のポインタにキャストして書き換えることはできますが、そんな暴挙をしない限り、データが書き換わらないことを保障できる安全なデータ型です。これは積極的に使っていきましょう。

 例えば、関数のプロトタイプ宣言が次のようなものだったとしたとき、これを見て、「おっ、この関数は渡した文字列の内容は書き換えないんだな。安心。安心。」と解釈できます。

int StoreStr(const char *str);

 しかし、関数のプロトタイプ宣言が次のようなものだったら、「うっ、この関数は何をするかわからないぞ。これは危険だな。」となってしまいます。

int StoreStr(char *str);

 関数を作るときに、何気なく引数に「char *」型を使っていませんか?関数の中で文字列を書き換えない場合は、それを主張するために、引数を「const char *」型にするようにしましょう。

 さて、C++では「データ型」に対しては非常に厳密さを要求します。それだけ安全性が高まっているということですね。「const char *」から「char *」へのキャストに関しては、特殊なキャスト方法をとらないとキャストできません。「const」をとってしまうというのは、非常に危険なことだというのを言語が主張しているんですね。

 それは、Cでも全く同じです。「char *」型と「const char *」型は全く違うということを理解しておきましょう。