2012-11-06 6 views
7
static char buf[8]; 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = (char*)ptr; 
} 

Powyższy fragment kodu będzie generować "warning: cast discards ‘__attribute__((const))’ qualifier from pointer target type [-Wcast-qual]". Lubię -Wcast-qual, ponieważ może mi pomóc od przypadkowego zapisu w pamięci, do której nie powinienem pisać.Explicit Zignoruj ​​ostrzeżenia od -Wcast-qual: „__attribute __ ((const))” CAST odrzutów kwalifikator od rodzaju docelowej wskaźnik

Ale teraz chcę odrzucić const tylko dla jednego wystąpienia (nie dla całego pliku lub projektu). Pamięć, na którą wskazuje, jest zapisywalna (tak jak powyżej: buf). Wolałbym nie upuszczać const z ptr, ponieważ jest on używany gdzie indziej, a trzymanie się wskaźników (jednej stałej i jednej stałej) wydaje się gorszym pomysłem.

+1

Dlaczego nie tylko "char * q = buf;'? –

+0

Sądzę, że to niejasne z urywków, wykonuję arytmetykę na ptr przed obsadą. – ext

+1

Lepiej byłoby użyć indeksu do buffa niż do manipulowania wskaźnikami i przekazać np. 'i buff [i]' zamiast wskaźnika? –

Odpowiedz

4

W GCC 4.2 i nowszych, można wyłączyć ostrzeżenie dla funkcji, używająC#pragma. Wadą jest powstrzymanie ostrzeżenia w całej funkcji; nie można go używać tylko dla niektórych linii kodu.

#pragma GCC diagnostic push // require GCC 4.6 
#pragma GCC diagnostic ignored "-Wcast-qual" 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = (char*)ptr; 
} 
#pragma GCC diagnostic pop // require GCC 4.6 

Zaletą jest to, że cały projekt może korzystać z tych samych opcji sprawdzania ostrzeżenia/błędów. I wiesz dokładnie, co robi kod, i po prostu spraw, aby GCC zignorował pewne wyraźne sprawdzenie kodu.
Ponieważ ograniczenie tej pragmy, musisz wyodrębnić niezbędny kod z bieżącej funkcji do nowej i uczynić nową funkcję samodzielnie z tą #pragma.

+3

** Włączone domyślnie ostrzeżenia: Kolekcja kompilatora GNU (GCC) 4.6.3 może generować włączone domyślne ostrzeżenia, których nie można wyłączyć. ** '-Wcast-qual' jest jedną z nich:' warning: initialization discards 'const' kwalifikator z typu docelowego wskaźnika ** [domyślnie włączony] ** ' –

+0

@AlterMann: To zupełnie inne ostrzeżenie, które pojawia się, gdy dokonujesz ** niejawnej ** konwersji, która odrzuca" const "kwalifikator (który jest nieprawidłowy C; C nie ma takiej niejawnej konwersji). To nie ostrzeżenie PO widzi. –

-1

trochę późno, ale można też zrobić to bez mucking z ostrzeżeniami w ogóle:

static char buf[8]; 
void foo(){ 
    const char* ptr = buf; 
    /* ... */ 
    char* q = buf + (ptr-buf); 
} 

skończyć z q = buf + ptr - buf = ptr + buf - buf = ptr, ale z buf „s constness.

(Tak, to pozwala na usunięcie const z dowolnego wskaźnika w ogóle; const ma charakter doradczy, a nie mechanizm bezpieczeństwa.)

+0

Ostrzeżenie nadal istnieje, używając gcc 4.7.2 – malat

7
#include <stdint.h> 

const char * ptr = buf; 
.... 
char * p = (char *)(uintptr_t)ptr; 

Albo bez stdint.h:

char * p = (char *)(unsigned long)ptr; 
+0

Zniechęciłbym to podejście. Nie obchodź ostrzeżeń. Jeśli ich nie chcesz, użyj supresji, do czego są przeznaczone. Będzie to wyraźne o twoich intencjach i sprawi, że twój kod stanie się bardziej czytelny. –

+0

Ograniczenia nie są na ogół przenośne. A jeśli udostępnisz swój kod, ktoś skompiluje się z czymś, co nienawidzi twojej metody tłumienia. Jeśli chcesz jawnie: #define UN_CONSTIFY (_t, _v) ((_t) (uintptr_t) (_ v)) –