C言語のchar配列とポインタの違いとは?初心者が混乱しやすいポイントを徹底解説

目次

はじめに

C言語を学んでいると、次の2つのコードが出てきます。

C
char str1[] = "hello";
char *str2 = "hello";

どちらも文字列を扱っているように見えます。

しかし実際には、

  • メモリの使い方
  • 書き換え可否
  • sizeofの結果
  • 関数引数での挙動

などが大きく異なります。

この違いは、C言語初心者が最も混乱しやすいポイントの1つです。

実際、組み込み開発でも、

  • 文字列を書き換えてクラッシュ
  • ROM領域を書き換えようとして異常動作
  • 配列だと思ってsizeofを使ったらバグ

といった原因になることがあります。

この記事では、

  • char配列とは何か
  • charポインタとは何か
  • メモリ上で何が違うのか
  • なぜ文字列リテラルを書き換えてはいけないのか
  • 実務ではどう使い分けるのか

を図付きで分かりやすく解説します。


C言語文法解説シリーズ

本記事は「C言語文法解説シリーズ」の1つです。
C言語の文法を、組み込み開発の視点も交えて解説しています。

C言語文法解説シリーズ一覧はこちら

C言語の文法を基礎から体系的に解説するシリーズです。

先に以下の記事を読むと理解しやすくなります。

👉 「配列とは?」
👉 「ポインタとは?」
👉 「文字列とは?」


まず結論

C
char str1[] = "hello";
char *str2 = "hello";

この2つは、

書き方意味
char str1[] = "hello";配列の中に文字列をコピーする
char *str2 = "hello";文字列リテラルを指す

という違いがあります。

ここを理解することが最重要です。

配列とポインタについてはこちらの記事で解説しています。


char配列とは?

まずはこちら。

C
char str1[] = "hello";

これは、

👉 「文字列を格納するchar配列」

です。

内部的には、

{'h','e','l','l','o','\0'}

という配列になります。

文字列についてはこちらの記事で解説しています。


メモリ上のイメージ

文字が連続したメモリ領域に保存されています。

文字列のメモリ上のイメージ

配列なので書き換え可能

str1 は自分専用の配列領域を持っています。

そのため、

C
str1[0] = 'H';

のように書き換えできます。


実際の例

C
#include <stdio.h>

int main(void) {
    char str1[] = "hello";

    str1[0] = 'H';

    printf("%s\n", str1);

    return 0;
}

実行結果:

Hello

charポインタとは?

次はcharポインタについて。

C
char *str2 = "hello";

これは配列ではありません。

👉 「文字列リテラルを指すポインタ」

です。


文字列リテラルとは?

文字列リテラルとは、

"hello"

のように直接書いた文字列のことです。

これはプログラム中の特別な領域に配置されます。


メモリ上のイメージ

文字列リテラルを指すポインタのメモリ上のイメージ

str2 は、

👉 文字列の先頭アドレスを持っているだけ

です。


初心者さん

見た目はほとんど同じなのに、中身は全然違うんですね

エンジニアくん

そう。配列は“データそのもの”、ポインタは“場所を指しているだけ”なんだ


文字列リテラルを書き換えてはいけない

ここが超重要です。

例えば:

C
char *str2 = "hello";

str2[0] = 'H';

これは危険です。


なぜ危険なのか

文字列リテラルは、

👉 読み取り専用領域(rodata領域など)

に配置されることが多いためです。

そのため、

C
str2[0] = 'H';

を実行すると、

  • クラッシュ
  • 異常動作
  • 未定義動作

になる可能性があります。

.rodata領域についてはこちらの記事で解説しています。


実務では const を付ける

実際のコードでは、

C
const char *str = "hello";

と書くことが多いです。

constの使い方についてはこちらの記事で解説しています。


const を付ける理由

これは、「この文字列は書き換えません」という意味です。


書き換えようとすると警告

C
const char *str = "hello";

str[0] = 'H';

これはコンパイルエラーや警告になります。

つまり、 バグ防止につながります。


sizeof の違い

初心者がかなりハマるポイントです。


配列の場合

C
char str1[] = "hello";

printf("%zu\n", sizeof(str1));

結果:

6

になります。

理由は:

h e l l o \0

で6バイトだからです。


ポインタの場合

C
char *str2 = "hello";

printf("%zu\n", sizeof(str2));

これは、

👉 ポインタサイズ

になります。

64bit環境なら:

8

になることが多いです。


なぜ違う?

str2 は文字列そのものではなく、

👉 アドレスを保存している変数

だからです。


初心者さん

えっ、文字数じゃないんですか?

エンジニアくん

ポインタは“住所”だからね。sizeofで見ているのは住所のサイズなんだ


関数引数での違い

これも重要です。


配列を関数に渡すと?

C
void func(char str[]) {
    printf("%zu\n", sizeof(str));
}

実はこれ、

👉 配列ではなくポインタ扱い

になります。


なぜ?

C言語では、

👉 配列を関数に渡すと先頭アドレスに変換される

からです。

これを「配列のポインタ変換(配列退化)」と言います。


実際の結果

64bit環境なら:

8

になることが多いです。

つまり、

👉 関数内では配列サイズが分からない

ということです。


実務でよくあるバグ

例えば:

C
void func(char str[]) {
    size_t size = sizeof(str);

    // 配列サイズだと思ったら実は8
}

こういうバグは本当にあります。

組み込みでもよく事故ります。


配列とポインタは「似ているが別物」


なぜ混乱するのか

C言語では、

C
str[i]

がどちらでも使えるためです。


実は内部的には同じ計算

C
str[i]

は内部的に:

C
*(str + i)

です。

つまり、

👉 ポインタ演算

でアクセスしています。


だから見た目が似る

  • 配列
  • ポインタ

はかなり似た書き方ができます。

しかし、

👉 メモリ上の意味は違う

ことを忘れてはいけません。

配列とポインタの違いについてはこちらの記事で解説しています。


実務での使い分け


書き換えるなら配列

C
char str[] = "hello";

固定文字列なら const char *

C
const char *str = "hello";

ROM節約でも重要

組み込みでは、

C
const char *str = "hello";

にすると、

👉 ROM配置できる

場合があります。

RAM節約にもつながります。


まとめ

char配列charポインタ は、見た目が似ています。

しかし実際には:

項目char配列charポインタ
実体配列アドレス
文字列コピーされるされない
書き換え可能危険
sizeof配列サイズポインタサイズ
実務用途編集用文字列固定文字列

という違いがあります。

この違いを理解すると、

  • 文字列
  • ポインタ
  • 配列
  • メモリ
  • const
  • ROM/RAM

の理解が一気につながります。

C言語では非常に重要なポイントなので、しっかり押さえておきましょう。


この記事が参考になった方へ

文字列やポインタをさらに理解したい方は、こちらの記事もおすすめです。

配列とは?
ポインタとは?
文字列とは?

配列を含むC言語の基本文法をこちらの記事で整理しています。

エンジニアとして技術を学ぶことは重要ですが、
キャリアや副業についても同時に考える必要があります。

副業の現実や市場価値、今後のキャリア戦略については、
こちらの記事でまとめています。

技術に関するご相談・開発・自動化ツール作成・記事執筆などのご依頼も承っています。

小さなご相談からでもお気軽にご連絡ください。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

組み込みソフトエンジニアとして働きながら、
C言語・メモリ・ポインタなどの基礎から実務まで解説しています。

副業・キャリアについても実体験ベースで発信中です。

X・Qiita・noteでも発信しています。
X:更新情報・日常
Qiita:技術発信
note:キャリア・副業

▼まずはここから読むのがおすすめ
C言語文法シリーズ
メモリ領域解説シリーズ
割り込み処理解説シリーズ
ソフトウェア設計解説シリーズ
キャリアと副業ロードマップ

コメント

コメントする


目次