2010-09-21 9 views
6

Mam funkcję, która przyjmuje niepodpisane długie * i musi przekazać ją do zewnętrznej biblioteki, która przyjmuje niepodpisane int * i na tej platformie bez znaku int/long mają ten sam rozmiar.Odlewanie, które łamie zasady ścisłego wygładzania

void UpdateVar(unsigned long* var) { 
    // this function will change the value at the address of var 
    ExternalLibAtomicUpdateVar((unsigned int*)var); // lib atomically updates variable 
} 

Generuje to ostrzeżenie, że łamie zasady ścisłego wygładzania. Czy są jakieś prace dookoła?

Dziękuję

Edycja: I przeprosić za nie jest jasne. Kod jest aktualizacją atomową, więc chodzenie po bibliotece w celu jej przechowywania nie jest opcją. Mogę upuścić do montażu, ale chciałbym to zrobić w C++.

+0

tylko dla pojedynczego obiektu lub tablicy longs/ints? – sellibitze

+0

To magazyn atomowy dla pojedynczego 32-bitowego fragmentu pamięci. – coderdave

Odpowiedz

8
void UpdateVar(unsigned long* var) { 
    unsigned int x = static_cast<unsigned int>(*var); 
    ExternalLibUpdateVar(&x); 
    *var = static_cast<unsigned long>(x); 
} 
+0

Dokonaj tego 'static_cast's, a ja będę głosował w górę. – sbi

+0

Przepraszam; nie zauważyłem znacznika C++ – dave

+0

Jaka jest prawdziwa różnica między 'static_cast' i' reinterpret_cast' w tym przypadku? – identity

2

To powinno działać:

void UpdateVar(unsigned long* var) { 
    // this function will change the value at the address of var 
    ExternalLibUpdateVar(reinterpret_cast<unsigned int*>(var)); 
} 
+0

Niebezpieczne, jeśli sizeof (long)! = Sizeof (int) – nos

+0

Powiedział w oryginalnym poście, że gwarantują, że będą miały ten sam rozmiar na swojej platformie. Ale tak, masz rację. – identity

+1

+1. Pod pewnymi warunkami jest to w mojej opinii właściwe. Ale to naprawdę zależy od przypadku i czułbym się bardziej komfortowo z jakimś 'sizeof (int) == sizeof (long)' sprawdź w programie, który sprawia, że ​​kompilacja kończy się niepowodzeniem, jeśli warunek nie jest spełniony - C++ 0x '' static_cast' ktoś? :-) – sellibitze

0

Nic w mandatach C standard, który int i long muszą mieć ten sam rozmiar; co więcej, nawet jeśli mają one tę samą wielkość, nic w standardowym mandacie, że mają tę samą reprezentację (między innymi, mogą mieć niekompatybilne kombinacje bitów dopełnienia i odwzorowań pułapek, tak że aliasing między tymi dwoma typami nie może służyć żadnym przydatny cel).

Autorzy Standardu nie chcieli wymuszać implementatorów na platformach, na których aliasing między int i long nie miałby żadnego znaczenia dla rozpoznania takiego aliasingu. Nie chcieli też pisać reguł, które miałyby zastosowanie do niektórych platform (tych, w których aliasing służyłby celowi), ale nie do innych (tych, w których nie byłoby to możliwe). Zamiast tego doszli do wniosku, że ludzie piszący kompilatory jakości próbowaliby rozpoznawać aliasing w przypadkach, w których byłby użyteczny.

Możliwość używania wskaźników do jednego 32-bitowego typu do odczytu i zapisu wartości innego 32-bitowego typu, który ma taką samą reprezentację, jest wyraźnie przydatna, szczególnie jeśli interfejsy API są podzielone na typy, których oczekują. Jeśli niektóre popularne interfejsy API na platformie używają wartości int* dla wartości 32-bitowych, a inne używają wartości long*, implementacja ogólnego przeznaczenia dla tej platformy o wartości musi umożliwiać dostęp do danych obu typów za pomocą wskaźników innych.

Niestety, autorzy niektórych kompilatorów są bardziej zainteresowani procesem przetwarzania określonego podzbioru programów, niż wydajnym przetwarzaniem większego podzbioru programów i nie można polegać na generowaniu przydatnego kodu, jeśli konieczna jest wymiana danych. między interfejsami API, które używają tej samej reprezentacji danych, ale różnymi nazwanymi typami, chyba że całkowicie wyłączono analizę aliasingu. Oczywiście, jeśli celujesz w dialekty C, które są odpowiednie do ogólnego zastosowania na mikrokontrolerach, takie problemy nie mają znaczenia.