(Ezt még korábban írtam:)
Nagyjából a következő történhet:
Az egyik file-odban allokálsz 256 byte-ot (statikus tárolási osztállyal). Ez deklaráció (mert bevezeti a nevet) és definíció is (mert tárhelyet allokál).
A másik file-odban csak deklaráció van (bevezeti a nevet az adott forrásfile számára, de tárhelyet nem allokál).
A kettő összepászítását a linker oldja meg. Amikor a második (a hivatkozó) file-odban az szerepel, hogy "na olvassuk ki a word2-t", akkor a linker ennek az első file-ban allokált 256 byte címét tolja alá. A kérdés az, hogy mennyit olvasol ki, és hogyan használod a tömbből kiolvasott byte-okat.
Ha a hivatkozó file-ban
extern char word2[256]
szerepel, akkor a tárgykód a kiolvasott byte-okat közvetlenül fogja használni. Másként érzékeltetve, a
sizeof word2
konstans kifejezés értéke 256.
Ha a hivatkozó file-ban
extern char *word2
szerepel, akkor a "word2" a fordító számára a második file-ban egy 4-byte-os területet takar, amelyet pointer-ként kell használni, vagyis oda köll menni, ahova mutat. (Más szóval, a
sizeof word2
konstans kifejezés értéke 4.)
Érted a különbséget? Az első esetben a
word2[3]
annyit tesz, hogy a linker betolja a tárterületet, azon belül megkeressük a 4. byte-ot, aztán kalap. A második esetben ugyanez a kifejezés azt jelenti, hogy linker betolja a tárterületet, beolvasunk onnan 4 byte-ot, a beolvasott értékhez (a mutatott címhez) hozzáadunk 3-at, és ami ott van, az a kifejezés értéke.
Az
a[b]
kifejezés mindig annyit tesz, hogy
*(a + b)
. (A kommutativitást most hagyva,) az "a" egy pointer, a "b" a (típushelyes) eltolás a mutatott címhez képest, a "*" pedig a dereferencia. Az egyetlen trükk, hogy amennyiben "a" nem pointer, hanem tömb, akkor automatikusan a legelső elem címe (pointer, &a[0]) kerül be a kifejezésbe. De ettől még a "sizeof a" tök mást fog visszaadni akkor, ha "a" tömb, és akkor, ha "a" mutató.