Widziałem ten kod w projekcie.Odlewanie dwa razy w tej samej linii
b
„s typ jest void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Czy ta linia bezcelowe? Mam na myśli, że to samo jak a = (int) b
we wszystkich przypadkach?
Widziałem ten kod w projekcie.Odlewanie dwa razy w tej samej linii
b
„s typ jest void*
:
void *b = ...;
int a = (int) (unsigned long) b;
Czy ta linia bezcelowe? Mam na myśli, że to samo jak a = (int) b
we wszystkich przypadkach?
To prawdopodobnie unika ostrzeżenie kompilatora na 64-bitowych systemach Unix gdzie unsigned long
jest ilość 64-bitowy, a tym samym na tyle duże, aby posiadać wskaźnik, ale int
jest ilość 32-bitowy, który nie jest wystarczająco duży, aby pomieścić wskaźnik . Obsada do (unsigned long)
zachowuje wszystkie bity adresu; kolejna obsada do int
wyrzuca 32-bitowe adresy o wysokim priorytecie, ale robi to bez domyślnego ostrzeżenia.
wykazać:
int main(void)
{
void *b = (void *)0x12345678;
int a = (int)(unsigned long)b;
int c = (int)b;
return a + c;
}
$ gcc -O3 -g -std=c99 -Wall -Wextra -c ar.c
ar.c: In function ‘main’:
ar.c:5:15: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast]
$
Korzystanie GCC 4.7.1 na Mac OS X 10.8.4, zalegających do 64-bitowej kompilacji.
Interesujące jest spekulowanie, co zostanie zrobione z wartością "część adresu".
Widzę to również w moim projekcie.
Dla mojej sprawy zawartość "b" jest wypełniona przez inne źródła/oprogramowanie pośredniczące używane do komunikacji między procesami.
Po wypełnieniu "b" program wyświetli zawartość "b" z rzutem do właściwego pola "a". aplikacja następnie używa "a" do przetwarzania.
Mój projekt używa char * zamiast void *.
Bezpośrednie typowanie tekstu do wskaźnika na mniejszy typ, powiedz int, może spowodować błąd kompilacji na niektórych kompilatorach (takich jak Clang) w środowisku 64-bitowym.
Na przykład
void *p = GetSomeAddress;
int i = (int)p; //error on compilers like Clang.
Solution:
int i = (int)(unsigned long)p;
lub
int i = (int)(long)p;
to dlatego, że w Unix pod modelu LP64 długo jest 64-bitowy.
Takie przypadki, należy dokładnie sprawdzić, dlaczego potrzebujesz typecast od wskaźnika do int lub innego mniejszego typu, co może spowodować utratę danych.
To pytanie może ci również pomóc. How should I handle "cast from ‘void*’ to ‘int’ loses precision" when compiling 32-bit code on 64-bit machine?
pamiętajcie, kreatywnych ludzi ukryć numeryczną (lub logiczna) informacje w 'void *' s :) – hroptatyr
Czy to czyni mnie twórczy - z przykładowym kodzie, które pisałem w czasie, kiedy komentując? –
Hehe, w istocie, to robi, stąd +1 :) Poważnie, wiele interfejsów API używa 'void *', gdzie 'intptr_t' byłby odpowiedni – hroptatyr