2014-10-20 491 views
5
benim derleyici aşağıdaki durumda bir hata atıyor neden karıştı

:C - ifadesi değiştirilebilir bir lvalue olmalıdır

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 

    for (i = 0; i < len; i++) { 
     otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 
    } 
} 

ama otherFunc geçmek öncesinde döküm halinde hiçbir sorun artırılmıyor çünkü, sorun değil boşluk olmayan işaretçi:

void funcExample (void * p_Buf, uint16_t len) 
{ 
    uint16_t i; 
    uint8_t * p_Buf_8bit; 

    p_Buf_8bit = (uint8_t *) p_Buf; 

    for (i = 0; i < len; i++) { 
     otherFunc (p_Buf_8bit++); 
    } 
} 

Bir kez gösterici boş gösterici artırılamıyor mu? Burada temel bir şey eksik miyim?

+0

özdeş değil, ama * çok * [burada ** benzer soru **] (http://stackoverflow.com/questions/24002044/neden-can-ı-not-do-aritmetik-on-a-döküm-of-a-boşluk-pointer). – WhozCraig

cevap

5

Cast operatörleri c:

6.5.4. p5 Parçalı bir tip adıyla bir ifadenin öncesinde ifadesinin değeri adlandırılan türe dönüştürür. Bu konstrüksiyon bir döküm olarak adlandırılır. 104) değerini belirten bir dökümün, ifadenin türü veya değeri üzerinde etkisi yoktur.

104) bir lvalue verim olmayan bir dökme. Böylece, uzman bir türü için bir dökme tipi

Ancak tekli operatör ++ arasında vasıfsız sürümü için bir döküm ile aynı etkiye sahiptir belirtildiği gibi bir lvalue gerektirir:

6.5.3.1 . p1 ön ek artış veya azalış operatörünün işlenen, atom nitelikli, veya vasıfsız gerçek veya işaretçi türü sahip olacaktır ve değiştirilebilir bir lvalue olacaktır.

Dolayısıyla yapabileceğiniz:

p_Buf = (uint8_t*)p_Buf + 1 ; 
p_Buf lvalue olduğunu

ve (uint8_t*)p_Buf rvalue olduğunu.


bana sadece (dediğin gibi) ikinci örnekte sen döküm olmadığını unutmayın edelim, ancak bir uint8_t işaretçi beyan ederim. Ardından, üzerinde ++ kullandığınızda, herhangi bir yayınlama gerçekleştirmezsiniz (çünkü doğru türde olduğundan) ve işlem geçerli olur.

+0

"void" işaretçinizi işaretçi yerine "uint8_t" olarak dönüştürüyorsunuz. – Seprum

+0

@Seprum Hayır Ben değilim. Eski bir düzenleme görmüş olabilirsiniz. sayfayı yenile. – 2501

+0

zaten düzenlenmiş. – Seprum

0

bir döküm işlemi sonucu bir rvalue değil, bir lvalue olup. ((uint8_t *)p_Buf)++ sadece yasal C kodu değildir. C bir void işaretçi artırma

1

kötü bir fikirdir. Derleyicilerin çoğu derlenmesine bile izin vermiyor. Bunu kullan:

p_Buf = (uint8_t*)p_Buf + 1; 
1

Gönderilen @ 2501 yanıtı kesinlikle doğrudur, ancak standardın neden artış için standardın neden lvalue gerektirdiğini açıklamıyor. Temel nedeni, artışını gerçekleştirmek için arttırma sonrası artış için lvalue (değişken veya bellek konumu) gerekir.

p_Buf ürününü uint8_t* türüne yazdığınızda, C dilinde bir rvalue oluşturdunuz.Basit bir ifadeyle, rvalues ​​, işlevlere geçirilebilen, değişkenlere atanabilecek geçici değerleri temsil eder. Artış artırım, orijinal değeri döndürür ve sonra değerin kaydedildiği değişken veya bellek konumunu günceller, artırır. Yalnızca ifade süresi boyunca var olduklarından, rıhtımları güncelleştirilemez ve bunlar sonradan artış işlemez. Böylece

otherFunc (((uint8_t *)p_Buf)++); //error = expression must be a modifiable lvalue 

sorun ((uint8_t *)pBuf) hiçbir gerçek depolama konumu ile sadece bir rvalue ifadesi olmasıdır. Aslında, cast, yalnızca p_Buf değerini kullandığınız ve artık p_Buf değişkenini doğrudan kullanmadığınız anlamına gelir. Eğer bir değişkene döküm atamak Öte yandan

:

p_Buf_8bit = (uint8_t *) p_Buf; 

sonra değişken p_Buf_8bit değişken veya bellek konumunu temsil bir lvalue vardır. Bu post-artırılır olmak C bu mükemmel iyi biçimli beyanda edebilirsiniz:

otherFunc (p_Buf_8bit++); 
+0

ek açıklama için teşekkür ederiz -> bu gerçekten yardımcı olur. Sorun, dökümün geçici/geçici doğasıdır (rvalue vs lvalue). teşekkür ederim. – jaypee

İlgili konular