ポインタ配列の const が理解できなかったのでメモ

検証コード

const char* const foo[] = {"foo","bar","baz"};

extern void __print(const char* buf);
void main(void) {
	char* str;
	__print(foo[0]);
}

これの foo のついている2つのconstを消したりつけたりする。__print は最適化で消されないように extern してるだけで特に意味はない。

arm-none-eabi-gcc -c c.c -o a.o && arm-none-eabi-objdump -t a.o

このようにして symbol table を見て、どのセクションに配置されるかを確認する。

char* foo[]

...
00000000 g     O .data  0000000c foo
00000000 g     F .text  0000002c main
...

当然 .data に配置される。

const char* const foo[]

...
0000000c g     O .rodata        0000000c foo
00000000 g     F .text  00000028 main
...

当然 .rodata に配置される。

const char* foo[]

...
00000000 g     O .data  0000000c foo
00000000 g     F .text  0000002c main
...

.data に配置される。

これがいまいちよくわからない。ここにconstをつけても以下はコンパイルエラーにならない。何が const になっているのだろう?「ポインタの配列 foo」そのもの?

foo[0] = "piyo";

しかし以下のように「ポインタの配列 foo」そのものを更新しようとしてもエラーになるので、そもそも「ポインタの配列 foo」そのものを更新しようがない気がする。

	char* bar[] = {"xxx"};
	foo = bar; //=>  error: assignment to expression with array type

char* const foo[]

0000000c g     O .rodata        0000000c foo
00000000 g     F .text  00000028 main

.rodata に配置される。

この場合、foo[0] への代入はコンパイルエラーになる。「ポインタの配列」の「ポインタ」が const になっている?

「ポインタ配列」の場合、上記のように「ポインタの配列 foo」そのものを更新しようがないので、.rodata で良いのだろうか?

foo[0] = "piyo"; //=> error: assignment of read-only location 'foo[0]'

char* const foo と const char* const foo は全く同じバイナリが吐かれる。ポインタ配列の最初の const は無意味なのだろうか?

  1. トップ
  2. tech
  3. C言語のポインタ配列の const の効果