2013-06-18 19 views
14

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?

Odpowiedz

22

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".

+2

pamiętajcie, kreatywnych ludzi ukryć numeryczną (lub logiczna) informacje w 'void *' s :) – hroptatyr

+0

Czy to czyni mnie twórczy - z przykładowym kodzie, które pisałem w czasie, kiedy komentując? –

+0

Hehe, w istocie, to robi, stąd +1 :) Poważnie, wiele interfejsów API używa 'void *', gdzie 'intptr_t' byłby odpowiedni – hroptatyr

0

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 *.

1

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?

Powiązane problemy