不正確ですが、オブジェクト指向でたとえるなら、型がクラスで変数がインスタンスです。分かれていなければ不便です。インスタンスが無ければインスタンス変数は設定できません。
C
1#include <stdio.h>
2#include <stdlib.h>
3
4struct Person {
5 char* name;
6 int age;
7};
8
9void print_person(struct Person* person)
10{
11 printf("%s(%d 歳)\n", person->name, person->age);
12}
13
14int main(void)
15{
16 struct Person alice;
17 alice.name = "Alice";
18 alice.age = 11;
19
20 struct Person bob;
21 bob.name = "Bob";
22 bob.age = 12;
23
24 struct Person* people[] = { &alice, &bob };
25 for (int i = 0; i < 2; i++) {
26 print_person(people[i]);
27 }
28
29 return 0;
30}
この場合、Person が構造体の定義で、alice や bob が構造体変数です。struct Person alice;
と宣言してメモリを割り当てています。メモリを割り当ててはじめて name や age を設定することができます。
なぜ定義と宣言が分かれているかという質問ですが、分かれているからこそ alice と bob を同じ手続きで作れ、同じ関数で表示できるのです。
そして構造体変数がないとメンバ変数が操作できないのは、定義だけでメモリが割り当てられていないからです。