2014-06-13 15 views
5

mam wiersza kodu, gdzie jest to całkiem przydatne:Czy jest to zły styl lub nieprawidłowy dostęp do makra va_arg przez odniesienie?

void *test; 
/*...*/ 
test = &va_arg(arg_list, int); 

Chciałam tylko to, co myślałem, że jest to makro, a nie funkcja, więc to może działać. Naprawdę nie spodziewałem się, że zadziała, ale robi dokładnie to, co chcę.

Ale teraz nie jestem pewien co do życia adresu i innych zagrożeń, które mogą wystąpić w tym stylu.

Czy ktoś może mi powiedzieć, dlaczego przy użyciu odniesienie wartości, va_arg jest w ten sposób jest bezpieczny/niebezpieczny?

średnia
+1

nie widzę nic w opisie, który wymaga 'va_arg (ap, type)' być lwartością. –

+0

@JamesMcNellis Może to być nieprawidłowe w niektórych środowiskach? – dhein

+0

@ meaning-matters Myślę, że mówi coś przeciwnego. Ponieważ standard mówi, że 'va_arg' zwraca tylko wartość, to nie składa obietnicy, że mógłbyś wziąć jej adres. Więc nie byłoby to bezpieczne. – user694733

Odpowiedz

3

C99 sekcja 7.15.1.1 (kopalnia nacisk)

va_arg makro rozwija się do ekspresji, który ma określony typu oraz wartość następnego argumentu w połączeniu.

Oznacza to, że va_arg niekoniecznie oznacza l-wartość; wzięcie adresu tego, co się rozszerza, jest niebezpieczne: wartość l może być użyta jako wyrażenie, ale nie każde wyrażenie jest lwartością. Rozważ wyrażenie: 3+4. Nie ma sensu przyjmowanie adresu tego.

Więc nie, nie należy to zrobić.

AKTUALIZACJA: Jak wskazano w komentarzach, podanie adresu wyrażenia, które nie jest lwartością, spowoduje błąd kompilacji. Tak więc, jeśli kod się kompiluje, powinien być bezpieczny. Kwestie unportability wynikają z faktu, że nie można skompilować na innych platformach gdzie va_arg() rozszerza się do czegoś, co nie jest lwartością.

+0

Jeśli to nie jest l-value, to czy nie byłby to błąd kompilacji? Nie wiem, dlaczego byłoby to niebezpieczne, albo kompiluje, albo nie ... – Mehrdad

+0

@Mehrdad Rozszerzenie do wyrażenia nie oznacza, że ​​wyrażenie, w tym konkretnym przypadku, nie jest lwartością. Możliwe, że tak właśnie jest, więc kompilowanie się z powodzeniem. Ale nic w standardzie nie gwarantuje tego zachowania, więc nie jest przenośne. –

+1

Więc tylko dla mnie, aby zrobić to dobrze: sposób używam kodu może spowodować błędy w czasie kompilacji, ale nie spowoduje błędów runtime? dobrze? Pozostawienie opcji szukania rozwiązań alternatywnych w systemach, w których nie będzie działać w ten sposób, może spowodować dodatkowe zakłócenia, ale nie może być szkodliwe? Czy to rozumiem? – dhein