error: invalid type argument of '->' の原因と直し方
構造体そのものの変数に対して->を使おうとしたときに出るエラーです。->は構造体へのポインタ専用の演算子です。
エラーメッセージの読み方
main.c:7:21: error: invalid type argument of '->' (have 'struct Point')
main.c- ファイル名
7- 行番号
21- 列番号 — この位置でgccが構文解析に失敗しました
invalid type argument of '->' (have 'struct Point')- 内容 — 期待していたもの、または受け付けられなかったもの
このエラーが出る典型パターン
パターン1
1 #include <stdio.h> 2 3 struct Point { int x; }; 4 5 int main(void) { 6 struct Point a = {5}; 7 printf("%d\n", a->x); ^ 8 return 0; 9 }
aは構造体そのもの(ポインタではない)なので、メンバアクセスには.を使います。->は構造体へのポインタ専用です。
直し方: a->x を a.x にします。
パターン2
1 #include <stdio.h> 2 3 struct Item { int price; }; 4 5 int main(void) { 6 struct Item i = {100}; 7 printf("%d\n", i->price); ^ 8 return 0; 9 }
変数iは構造体の実体です。ポインタを経由していないので.でアクセスします。
直し方: i->price を i.price にします。
パターン3
1 #include <stdio.h> 2 3 struct Node { int value; }; 4 5 int main(void) { 6 struct Node n = {7}; 7 printf("%d\n", n->value); ^ 8 return 0; 9 }
構造体を指すポインタが登場する連結リストなどのコードに慣れてくると、実体に対しても->を使ってしまう混同が起こりやすくなります。
直し方: n->value を n.value にします。
パターン4
1 #include <stdio.h> 2 3 struct Box { int width; }; 4 5 int main(void) { 6 struct Box b = {12}; 7 printf("%d\n", b->width); ^ 8 return 0; 9 }
bは構造体の実体なので、メンバアクセスには.を使います。
直し方: b->width を b.width にします。
パターン5
1 #include <stdio.h> 2 3 struct Car { int speed; }; 4 5 int main(void) { 6 struct Car c = {60}; 7 printf("%d\n", c->speed); ^ 8 return 0; 9 }
ポインタを経由していない構造体変数には.でアクセスします。
直し方: c->speed を c.speed にします。
よくある誤解
構造体変数とその構造体へのポインタは似た場面で使われますが、メンバへのアクセス方法は別です。変数そのものなら.、ポインタ経由ならアロー->を使います。ポインタをデリファレンスしてから.でアクセスする(*p).xという書き方はp->xと完全に同じ意味です。
実務での勘所
->は本質的には(*p).xの糖衣構文で、意味は完全に同じです。この省略記法が用意された理由は、Cでは連結リストや木構造のようにポインタ経由で構造体をたどるコードが非常に多く、p->next->valueのように複数回チェーンして書く場面で、(*(*p).next).valueのような書き方では読みにくくなりすぎるためです。ポインタを介したメンバアクセスが頻出するCの実務コードでは、->は単なる省略以上に可読性を大きく左右する記法です。