2011-06-23 11 views
24

Mam pustą wskazówkę o nazwie ptr. Chcę zwiększyć tę wartość o liczbę bajtów. Czy jest jakiś sposób na zrobienie tego?Zwiększ wskaźnik pustego o jeden bajt? przez dwa?

Należy pamiętać, że chcę to zrobić w miejscu bez tworzenia żadnych innych zmiennych.

Czy mogę zrobić coś takiego jak ptr = (void *)(++((char *) ptr));?

Odpowiedz

48

Nie można wykonywać arytmetycznych na pustym wskaźniku, ponieważ arytmetyka wskaźnikowa jest zdefiniowana pod względem wielkości wskazywanego obiektu.

Można jednak rzutować wskaźnik do char*, czy arytmetyki tego wskaźnika, a następnie przekształcić go z powrotem do void*:

void* p = /* get a pointer somehow */; 

// In C++: 
p = static_cast<char*>(p) + 1; 

// In C: 
p = (char*)p + 1; 
+1

nie powinien to być reinterpret_cast? – Balk

+4

@Balk: 'static_cast' jest wystarczające. –

15

Żadnych operacji arytmetycznych nie można wykonać na wskaźniku void.

Kompilator nie zna rozmiaru przedmiotu wskazywanego przez wskaźnik void. Możesz rzucić wskaźnik na (char *), aby to zrobić.

W gcc jest rozszerzenie, które traktuje rozmiar void jako 1. więc można użyć arithematyki na void*, aby dodać przesunięcie w bajtach, ale użycie go dałoby nieprzenośny kod.

+0

W GCC jest to możliwe, ponieważ 'sizeof (void)' '1 'plony. –

+0

@Blagovest Buyukliev: Jest to rozszerzenie w GCC, które traktuje rozmiar pustki jako 1, Użycie go dałoby nieprzenośny kod. –

+1

@Blag: Jak zawsze, proszę skompiluj z '-pedantic'. :) – Xeo

4

Wystarczy zwiększając void* zdarza się pracować w gcc:

#include <stdlib.h> 
#include <stdio.h> 

int main() { 
    int i[] = { 23, 42 }; 
    void* a = &i; 
    void* b = a + 4; 
    printf("%i\n", *((int*)b)); 
    return 0; 
} 

Jest to jednak błędne pod względem koncepcyjnym (i oficjalnym), więc należy je wyraźnie zaznaczyć: należy je odrzucić, a następnie odsyłać do char*.

void* a = get_me_a_pointer(); 
void* b = (void*)((char*)a + some_number); 

Dzięki temu staje się oczywiste, że zwiększasz liczbę bajtów.

+1

Jak zawsze, proszę skompiluj z '-pedantic'. :) To niezgodne rozszerzenie GCC. – Xeo

+0

Zgadnij, że jestem rozpieszczony :) - zredagowałem odpowiedź na poprawność – tdammers

-1

można zrobić:

++(*((char **)(&ptr))); 
+4

Tak, ale po co? To okropny niejasny kod, który sprawia, że ​​niepotrzebnie trudno jest przetworzyć to, co robi, bez powodu. Również odmiany w stylu C należy odradzać w C++, ale to najmniejszy problem. –

+2

Możesz również wbić płonącą laskę w oko. Prawdopodobnie boli mniej niż patrząc na '++ (* ((char **) (& ptr));'. –

Powiązane problemy