2012-04-07 30 views
7

Ders kitabımı inceliyorum ve içinde bulunduğumuz kodun bir kısmı hakkında biraz kafam karıştı. bir kısmında, aşağıdaki şekilde işaretçi aritmetik performans:void * vs. char * işaretçi aritmetiği

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

ama daha sonra onlar aşağıdakileri yapın:

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

iki farklı şeyler olması gerektiği gibi hissediyorum ama tedavi ettikleri Aynı şeyden hoşlanır. (örneğin bir tamsayı dizisi için) bir dizi erişimi yapmak olsaydı, örneğin, bu durumda aşağıdaki

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

yapacağını, çünkü ben önümüzdeki erişen değildir, bu şekilde hissediyorum Tamsayı dizisinde 4 bayt ve sonraki bayt değil mi? Benzer şekilde, eğer ben * a boşluğum varsa, o zaman * (a + 1) sonraki 4 bayt olmalıdır ... Ya da öyle değil mi? Teşekkür ederiz.

+0

Bu ikinci örnek, derlememelidir. –

+1

@OliCharlesworth: Uygun modda derlerseniz, derleme (veya en azından bir uyarı tetikler) olmaz. gcc varsayılan olarak uymuyor ve bir boşluk olarak "void *" aritmetiğini uygular. –

cevap

11

Bu bir kaymadır. void * üzerinde aritmetik, standart tarafından tanımlanmadı, ancak bazı derleyiciler, bir aritmetik için char * ile aynı davranan bir uzantı olarak sunar. İkincisi resmi olarak geçerli C değil, ama muhtemelen (kötü) alışkanlıktan kaymıştır.

+0

Dolayısıyla, sonraki 16 baytlara erişmenin uygun yolu ilk önce char * 'a basmak ve sonra 16 eklemek olacak? Lol, şimdi iyi bir kod miktarını değiştirmeliyim. Oh ve ben ilkini biraz yanlış kopyaladım, küçük bir değişiklik yaptım ama bu soruya bir fark yaratacağını düşünmüyorum. – de1337ed

+0

Ya da "uint64_t *' a basabilir ve 2 ekleyebilirsin;) Evet, taşınabilir yol, bir işaretçiye bilinen boyuttaki bir türe atmak ve bunun için aritmetik yapmaktır. Taşınabilirlik ve derleyici belgelerinize ihtiyaç duymazsanız, void * aritmetiği belirli bir şekilde çalışır. Ama elbette, bir noktada farklı bir derleyiciye gitmek zorunda kalacaksınız ... –