2015-12-15 17 views
9

Można wyróżnić dwa standardowe zasady C:przekształcenie nie `void` wskaźnik `uintptr_t` i vice versa

średnia C99 6.3.2.3:

Wskaźnik do anulowania może być przekształcony lub od wskaźnika do dowolnego niekompletnego lub typu obiektu . Wskaźnik do dowolnego niekompletnego lub typu obiektu może zostać przekonwertowany do wskaźnika, aby unieważnić i przywrócić ponownie; wynik powinien być równy oryginalnemu wskaźnikowi.

I 7.20.1.4:

Poniższy typ wyznacza unsigned całkowitą z właściwością że każda ważna wskazówka, aby unieważnić mogą być konwertowane do tego typu następnie przekształcany z powrotem do wskaźnika do nieważna i wynik będzie porównać równe oryginalnej palików: uintptr_t

oznacza to, że followin kod g jest zgodny:

int *p = NULL; 
void *q = (void*)p; 
uintptr_t s = (uintptr_t)q; 

Ale czy naprawdę potrzebuje dwuetapowej obsady? Kompilator będzie wykonywać niejawny pośredni obsady jeśli robi coś takiego:

int *p = NULL; 
uintptr_t s = (uintptr_t)p; 

(dobrze, to prawdopodobnie będzie w większości kompilatorów, ale moje pytanie jest o standardowej zgodności)

+0

Należy zauważyć, że 'p' jest niezainicjalizowane w obu. Prawdopodobnie coś takiego: 'int i = 42; int * p = i i; ... 'naprawi to. –

+0

@ l3x cóż, tak, dziękuję. Ze względu na kompletność to naprawi. –

Odpowiedz

7

nie będę ryzykować. Standard sprawia, że ​​jest jasne, co jest dozwolone, a co niedozwolone.

Zapisywanie uintptr_t s = (uintptr_t)(void*)p; sygnałów do czytnika Twojego kodu, o którym wiesz, co robisz.

+3

Szczerze mówiąc, gdybym zobaczył ten kod, zastanawiałbym się, czy autor wiedział, co robią. Częściowo dlatego, że nie miałbym pełnego przypomnienia odpowiednich fragmentów z dostępnego standardu. Nie mówię, że źle jest napisać to w ten sposób, ale też nie byłoby to dla mnie oczywiste. –

+2

W takim przypadku nie zaszkodzi pisanie komentarza. Zależy od zasad twojego domu. – Bathsheba

Powiązane problemy