2015-08-13 24 views
6

Znalazłem segment kodu. Nie rozumiem tego. Wydaje się, że zmienna __rem jest w ogóle bezużyteczna. Linia poniżej nie robi żadnej użytecznej pracy jeszcze:Co ten kod oznacza

(void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ 

Segment kodu całość jest jak poniżej:

#define do_div(n,base) do{    \ 
    uint32_t __base = (base);   \ 
    uint32_t __rem;     \ 
    (void)(((typeof((n)) *)0) == ((uint64_t *)0)); \ 
    if (((n) >> 32) == 0) {   \ 
     __rem = (uint32_t)(n) % __base;  \ 
     (n) = (uint32_t)(n)/__base;  \ 
    } else      \ 
     __rem = __div64_32(&(n), __base); \ 
    __rem;      \ 
}while(0) 
/* Wrapper for do_div(). Doesn't modify dividend and returns 
* the result, not reminder. 
*/ 
static inline uint64_t lldiv(uint64_t dividend, uint32_t divisor) 
{ 
    uint64_t __res = dividend; 
    do_div(__res, divisor); 
    return(__res); 
} 

Dlaczego jest bezużyteczny kod tutaj?

+1

sprawdzanie poprawności kompilatora? – EOF

+1

Ponownie, proszę podać informacje o toolchain. Jest to oczywiście nieodłączny kompilator (podwójny undersores w identyfikatorach). – Quentin

+0

Jest to plik div64.h w systemie uboot. Kopiuję to i na początku działa dobrze. Ale kiedy skompilowałem go z RVDS 5.01. Kompilator narzekał, że "wyrażenie nie ma żadnego efektu"[email protected] – user1651758

Odpowiedz

12

1. (void)(((typeof((n)) *)0) == ((uint64_t *)0));

Zobacz Linux/include/asm-generic/div64.h:

Niepotrzebne wskaźnik porównania jest tam celu sprawdzenia bezpieczeństwa typu (n musi być 64bit)

Przykład:

n musi być int, ale jest short

void main() 
{ 
    short n; 
    (void)(((typeof((n)) *)0) == ((int *)0)); 
} 

Dostajemy ostrzeżenie: comparison of distinct pointer types lacks cast

skompilowany z: wersja gcc -o main main.c

Compiler: gcc (GCC) 4.9.2 20141101 (Red Hat 4.9.2-1)

Wniosek:

Porównanie wskaźnika nie jest bezużyteczne. Generuje ostrzeżenie, jeśli zmienna przekazana do do_div() ma niewłaściwy typ.

2. __rem

Kod otoczony szelkami jest gcc Statement wyrażenia. __rem to, że tak powiem, wartość zwracana do_div().

przykład:

#include <stdio.h> 

#define do_div(n,base) ({ \ 
    int __rem = n % base; \ 
    n /= base;    \ 
    __rem;     \ 
}) 

int main() 
{ 
    int a = 9; 
    int b = 2; 
    int c = 0; 

    printf("%i/%i = ", a, b); 
    c = do_div(a, b); 
    printf("%i, reminder = %i\n", a, c); 
    return 0; 
} 

wyjściowa: 9/2 = 4, reminder = 1

W powyższym przykładzie c = do_div(a, b) odpowiada c = ({int rem = a % b; a /= b; rem;}).

Wniosek:

__rem nie ma sensu to jest "wartość powrót" do_div().

+0

Dziwne, że powoduje to domyślnie ostrzeżenie, jest to całkowicie uzasadnione: "Projekt standardu C11: 6.3.2.3 Wskaźniki 4 [...] Wszelkie dwa wskaźniki zerowe powinny być równe. [...]". – EOF

+0

Oh, generuje również ostrzeżenie na moim gcc 4.8.4. Byłem zaskoczony, że nie wymaga '-Wall' lub' -Wextra' lub czegoś podobnego. – EOF

+0

@EOF, który mówi, że będzie porównywać takie same * po * konwersji do tego samego typu. Jednak konwersja do tego samego typu wymaga rzutowania w tym przypadku. (C11 6.5.8/2) –