2012-04-07 2 views
7

Przeglądam mój podręcznik i jestem nieco zdezorientowany, jeśli chodzi o kod, który tam jest. W jednej części, są one wykonywaniu arytmetyki wskaźników w następujący sposób:void * vs. char * wskaźnik arytmetyczny

void* bp; 
... 
bp = (void*)((char*)(bp)+16); 
... 

ale później, to należy wykonać następujące czynności:

void* bp; 
... 
bp = bp+16; 
... 

czuję się jak powinny one być dwie różne rzeczy, ale oni traktują to tak samo. czuję się w ten sposób, ponieważ, na przykład, jeśli było zrobić dostępu do tablicy (na tablicy liczb całkowitych na przykład), to zrobi następujące

int* a = malloc(n*sizeof(int)); 
... 
q = *(a+1); 
... 

w tym przypadku, nie mam dostępu do następnego 4 bajty w tablicy całkowitej, a nie kolejny bajt? Podobnie czuję, że jeśli mam pustkę * a, to * (a + 1) powinno być następnymi 4 bajtami ... A może tak nie jest? Dziękuję.

+0

Ten drugi przykład nie powinien się kompilować. –

+1

@OliCharlesworth: Nie skompiluje (lub przynajmniej wyśle ​​ostrzeżenie), jeśli kompilujesz w trybie zgodności. gcc nie jest domyślnie zgodny i implementuje 'void *' arytmetyczną jako rozszerzenie. –

Odpowiedz

11

To wpadka. Arytmetyka na void * nie jest zdefiniowana przez standard, ale niektóre kompilatory oferują ją jako rozszerzenie, zachowując się tak samo jak char * dla arytmetyki. Drugi jest formalnie nieważny C, ale wymknął się prawdopodobnie z (złego) nawyku.

+0

Tak więc właściwym sposobem uzyskania dostępu do następnych 16-bajtów byłby pierwszy rzut na char *, a następnie dodanie 16? Lol, musisz teraz zmienić dobrą ilość kodu. Aha, skopiowałem pierwszy mały błąd, dokonałem niewielkiej zmiany, ale nie sądzę, żeby to zmieniło moje pytanie. – de1337ed

+0

Możesz też rzutować na 'uint64_t *' i dodać 2;) Tak, przenośną metodą jest rzutowanie na wskaźnik do typu o znanym rozmiarze i robienie arytmetyki. Jeśli nie potrzebujesz przenośności, a twoje dokumenty kompilujące, że arytmetyczna "void *" działa w określony sposób, możesz z tego skorzystać. Ale oczywiście, w pewnym momencie będziesz musiał przesłać do innego kompilatora ... –