2013-01-24 11 views
5

Podczas próby debugowania problem mam z wykorzystaniem Speex, zauważyłem, że to (no, nie tylko speex, ale niektóre przykładowy kod jak również) wykonuje następujące czynności:Rzuca struct T * na niezdefiniowane zachowanie struct C *, jeśli pierwszym polem T jest C?

  • zwracają wskaźnik do EncState ze związku funkcja inicjalizacji
  • Obsada że wskaźnik do wskaźnika void
  • przechowywać nieważne wskaźnik
  • (gdzie indziej)
  • Obsada wskaźnik void do wskaźnika do wskaźnika do SpeexMode
  • nieprawidłowego wskaźnika

Zdarza się, że definicja EncState zaczyna z polem typu SpeexMode *, a więc wartości całkowitą od wskaźnika do pierwszego pola i wskaźnik do struktury stało się to samo . Dereferencja działa w czasie wykonywania.

Ale ... czy język rzeczywiście pozwala na to? Czy kompilator może robić to, co chce, jeśli to kompiluje? Rzuca struct T * na niezdefiniowane zachowanie struct C *, jeśli pierwszym polem T jest C?

+0

Również duplikat [zgodności wskaźnika strukturalnego] (http://stackoverflow.com/questions/8702713/struct-pointer-compatibility) – netcoder

+0

Jest technicznie UB, tak, ze względu na surową regułę aliasingu. Preferowanym sposobem jest zwykle używanie związku z członkami obu typów. – netcoder

Odpowiedz

7

od standardu C11:

(C11 §6.7.2.1.15 „a wskaźnik do obiektu struktury, korzystnie przekształca wskazuje początkowej członka ... i vice versa Może. być bezimienny wyściółka wewnątrz jako struktury obiektu, ale nie na jego początku. ")

co oznacza, że ​​zachowanie widać jest dozwolone i gwarantowana.

+1

Jednak łamie zasadę ścisłego aliasingu. – netcoder

+0

@netcoder Prawda, jeśli prowadzi to do problemów w tym przypadku, jest niejasna. – pmr

+0

+1 Zwięzła i jasna odpowiedź ... Mogę dodać jako komentarz, że można znaleźć wiele przykładów tego rodzaju typowania w strukturze GObject – Rerito