2015-11-03 49 views
5

Bir dizideki üçüncü öğeye bir uint8_t işaretçi nokta koyduğumu varsayalım, {1, 2, 4, 5} yani *p 4'tür. Bunu nasıl gösterebilirim? Böylece 4 ve 5'e kadar *p 45'dir. Bu mümkün mü? Şu anda yazım yapıyorum. İşte yaptığım şey, ör. verilerim dizi ise {1, 2, 4, 5} ve ben 4 ve 5.İki veya daha fazla arka arkaya hücrelere işaretçi noktası oluşturma

uint8_t dummyAddress = data[2]; 
dummyAddress = *((uint16_t*) dummyAddress); 
*p = *dummyAddress; 

Benim anlayış p şimdi 4. ve 5. işaret gerektiğidir almak istiyorum ama değilim. Bunun yerine, ikinci satırı çalıştırdığımda bir seg hatası alıyorum. p, bir uint64_t * const. Bir bayt elde etmek için çalışır, ancak aynı mantığı iki bayta uygularken doğru anlayamıyorum.

+0

Lütfen eksiksiz bir kod verin (Dizi bildirimi, kullanılan değişkenlerin türleri ...). –

+0

Daha yüksek bir uyarı Düzeyi ile derlemeniz ve Derleyici uyarılarını dinlemeniz gerekir. –

+1

Kodunuzda 'dummyAddress' bir işaretçi değil –

cevap

4

Bunu yapabilirsin:

uint8_t data[] = { 1, 2, 4, 5 }; 
uint8_t *p8 = &data[2]; 
uint16_t u16 = *(uint16_t*)p8; 

Sonra (uint16_t*)p8 data[2] ve data[3] işaret eder. Ancak *(uint16_t*)p8'a kolayca erişemezsiniz. Bunun nedeni, p8'un uint16_t sınırında hizalanamamasıdır. Bazı işlemci bu durumda bir istisna neden olur. İkincisi, *(uint16_t*)p8'a erişseniz bile, işlemcinin bayt sırasına bağlı olarak farklı sonuçlar elde edebilirsiniz (büyük endian/küçük endian). 0x0405 alabilirsiniz veya 0x0504 alabilirsiniz.

da hat

dummyAddress = *((uint16_t*) dummyAddress); 

yılında ilk uint16_t bir işaretçi olarak dummyAddress yeniden yorumlanmasına ve sonra çözümleyecek, bu yüzden bir uint16_t dönen ve dummyAddress bu depolamak lütfen unutmayın. Bu açıkça yapmak istediğin şey değil. Bu gerçekten derlerse, lütfen daha yüksek bir uyarı düzeyi ile derlemeyi ve her derleyici uyarısına göz atmayı düşünün (ve sadece anladığınız takdirde göz ardı ederek bir programlama hatası olmadığından emin olun).

BTW, p işaretçisini bulamazsanız, sorularınız için *p==45 numaralı telefonu kullanabilirsiniz. MCH söylediği gibi

Ayrıca: What is the strict aliasing rule?

+0

küçük baytlarda byte kapmak gibi görünüyor, yani * p 0x0504. şimdi bunu tersine çevirmek istersem * p okur 0x405 Bunun hakkında nasıl gideceğime dair kafam karıştı. İnsanların << operatörünü kullandıklarını ve bitleri 8 kez değiştirdiklerini ya da * p'yi 8 katını belli sayıda kez değiştirdiklerini gördüm. Herhangi bir açıklama lütfen – ponderingdev

+1

Evet, bunu 'uint16_t a = ... gibi kaydırma ile yapabilirsiniz; uint16_t b = (a >> 8) | (bir << 8). Hatta daha iyi doğrudan veri dizisi üzerinde çalışmak uint16_t b = ((uint16_t) veri [2] << 8) | veri [3] '(veya veri [2] ve veri [3]). –

0

Sen yazmalısınız:

uint_8_t *dummyAddress= &data[2]; 
uint_16_t *dummyAddress2= (uint16_t *) dummyAddress; 

uint_16_t p= *dummyAddress2; 

fakat "endian" ile dikkat Eğer {data[3], data[2} olarak yani yanlış sırada iki uint_8 's alabilirsiniz .

+2

ve tanımlanmamış bir davranıştır çünkü katı takma kuralını ihlal eder. – mch

1

Ne yaptığınızı anlayabiliyorsam, evet, her iki bayta da uint16_t'a erişerek erişebilirsiniz, ancak baytların siparişinin bellekte nasıl saklandığının yanı sıra sorunlara (veya endianess sorunlarına) girersiniz sıkı-aliasing. Bu muhtemelen şüphelenmediğiniz bir cevap verecektir. Örneğin:

#include <stdio.h> 
#include <stdint.h> 

int main (void) { 

    uint8_t array[] = {1,2,3,4}; 
    uint8_t *p = array + 2; 

    printf ("\n the uint8_t answer : %hhd\n", *p); 
    printf (" the uint16_t answer : %hd\n\n", *(uint16_t *)p); 

    printf ("**note: the will cast result in bytes 4, 3" 
      " (or (4 << 8 | 3) = 1027)\n\n"); 

    return 0; 
} 

Çıktı

$ ./bin/cast_array 

the uint8_t answer : 3 
the uint16_t answer : 1027 

**note: the cast will result in bytes 4, 3 (or (4 << 8 | 3) = 1027) 

bayt little endian sırayla sistemimde hafızada saklanır. Yani uint16_t'a attığınızda, least significant, most significant baytları bulmayı bekler.Yukarıdaki örnekte, 34 numaralı bellekte, bu döküm, asıl siparişi 43 olarak yorumlayacak ve değerini (3 << 8) | 4 = 772 yerine alacaktır.

olarak, tanımsız davranış char sonuçları dışında başka bir şey için döküm tarafından sıkı aliasing tip budama ile ilgili kuralları ihlal edilecektir kaydetti. Tüm bu eylemlerin sonuçları, donanım ve derleyiciye bağımlıdır ve bir öğrenme alıştırmasından başka hiçbir şey için kullanılmamalıdır.

+0

'* (uint16_t *) p', tanımlanmamış davranışı çağırır, çünkü bu, katı takma kuralını ihlal eder. – mch

+0

Evet, budama ile ilgili bir not düşeceğim. –

İlgili konular