C'de Struct Uzantısı

Aug 21 2020

Reklam tanımlı 2 yapı olduğunu varsayalım:

typedef struct {
   T x;
   T y;
} A;

typedef struct {
   A a;
   T z;
} B;

B yapısına bir göstericiyi A yapısına işaretçi olarak kabul edebilir miyim?

Pratikte bu güvenilir / standart / taşınabilir / derleyici değişmezdir:

B b = {{1,2},3};
A * a = &b;

print(a->x);
print(a->y);

Yanıtlar

3 Lundin Aug 21 2020 at 08:19

C17 6.7.2.1 şunu belirtir (vurgu benim):

Bir yapı nesnesi içinde, bit alanı olmayan üyeler ve bit alanlarının bulunduğu birimler, bildirildikleri sırada artan adreslere sahiptir. Uygun şekilde dönüştürülmüş bir yapı nesnesine bir işaretçi, başlangıç ​​üyesine (veya bu üye bir bit alanı ise, o zaman içinde bulunduğu birime) işaret eder ve bunun tersi de geçerlidir .

Bu, B bnesnenin işaretçisini ilk üyesinin türüne "uygun şekilde dönüştürmeniz" gerektiği anlamına gelir . Bu dönüşüm örtük olarak gerçekleşmez, bunu açık bir atama yoluyla yapmalısınız:

A * a = (A*)&b;

Bunu yapmak, yukarıda alıntılanan bölüme göre iyi tanımlanmış ve güvenlidir.

Benzer şekilde, derleyicinin bir gösterici Ave Btakma ad vermeyecek bir gösterici olduğunu varsaymasına izin verilmez . Etkili 6.5.7 türü kuralı ("kesin örtüşme") bu durum için bir istisna verir:

Bir nesnenin depolanan değerine yalnızca aşağıdaki türlerden birine sahip olan bir lvalue ifadesi tarafından erişilmesi gerekir:
...

  • üyeleri arasında yukarıda belirtilen türlerden birini içeren bir toplu veya birleşim türü

Örneğin, optimizasyon sırasında, işlevi çağıran bir derleyicinin void func (B* b), extern A a;başka bir çeviri biriminde tanımlanan bir dış hat değişkeninin işlev tarafından değiştirilmediğini varsaymasına izin verilmez .