SORU
6 Mayıs 2012, Pazar


" (s1) - strlen(s2)" hiçbir zaman sıfırdan küçük strlen

Şu anda aşağıdaki yardımcı fonksiyon yazdım dize uzunlukları sık karşılaştırmalar gerektiren bir C programı yazıyorum:

int strlonger(char *s1, char *s2) {
    return strlen(s1) - strlen(s2) > 0;
}

Fonksiyonu s1 s2 daha kısa uzunlukta olmasına true değerini fark ettim. Biri bu tuhaf davranışlarını açıklayabilecek olan var mı?

CEVAP
6 Mayıs 2012, Pazar


Rastlamak ne imzalı ve imzasız miktarlarda içeren ifadeleri kullanırken C içinde ortaya çıkan bazı garip davranış.

Bir işlem bir işlenen imzalanan nerede yapılır ve diğer imzasız, C örtük olarak imzasız imzalı değişken dönüştürme işlemleri ve sayılar negatif olmayan varsayarak bir konser verecek. Bu Sözleşme genellikle < > ilişkisel operatörler için nonintuitive davranışlara yol açar.

Yardımcı işlevi ile ilgili olarak, strlen tipi size_t (imzasız bir miktar) verir, çünkü farkı ve karşılaştırma hem bilgisayarlı işaretsiz aritmetik kullanmayı unutmayın. s1 s2, strlen(s1) - strlen(s2) negatif farkı daha kısa, ama bunun yerine 0 daha büyük olan büyük, işaretsiz bir sayı olur. Böylece

return strlen(s1) - strlen(s2) > 0;

dönerse s1 s2 daha kısa olması durumunda bile 18**. Fonksiyonunu düzeltmek için, bu kodu kullanın:

return strlen(s1) > strlen(s2);

C dünyasına hoş geldiniz! :)


Diğer Örnekler

Bu soru son zamanlarda ilgi çok aldı bu yana, (basit) bir kaç örnek sunmak için, sadece karşısındaki fikir alıyorum emin olmak istiyorum. 32-bit bir makine iki kullanarak ile çalışıyoruz varsayalım tamamlayıcı gösterimi olacak.

İmzasız çalışma/C değişkenleri arasında imzalanan anlamak için önemli bir kavrameğer tek bir ifadede imzasız ve imzalı miktarda bir karışımı varsa, imzalı imzasız değerleri dolaylı olarak, atama.

Örnek 1:

Düşünün şu ifade:

-1 < 0U

İkinci ifadenin imzasız olduğu için ilk biridirörtülü olarak dökmeimzasız ve dolayısıyla ifade karşılaştırma eşdeğerdir

4294967295U < 0U

elbette yanlış olan. Bu muhtemelen beklediğin davranış değildir.

Örnek 2:

Bir dizinin eleman sayısını parametre tarafından verildiği a, sum girişiminde aşağıdaki kodu length düşünün:

int sum_array_elements(int a[], unsigned length) {
    int i;
    int result = 0;

    for (i = 0; i <= length-1; i  ) 
        result  = a[i];

    return result;
}

Bu işlev hataları örtülü çevrim nedeniyle imzalı imzasız ortaya çıkabilir nasıl göstermek için tasarlanmıştır. Şimdiye kadar olumsuz bir uzunluk kullanmak isteyen imzasız olarak parametre length geçmek oldukça doğal; sonuçta görünüyor? i <= length-1 kriter durdurma da çok kolay görünüyor. Ancak, zaman değişkeni ile çalışma length 0 Bu iki verim kombinasyonu beklenmedik bir sonuç eşit.

Parametre length imzasız olduğu, 32* *hesaplama modüler ayrıca eşdeğerdir işaretsiz aritmetik kullanılarak yapılır. SonuçUMax. <= karşılaştırma da imzasız bir karşılaştırma kullanılarak yapılır, ve o zamandan beri herhangi bir sayı daha az veya eşittirUMaxkarşılaştırma her zaman tutar. Böylece kod dizisi a geçersiz öğeleri erişmek için çalışacaktır.

Kodu ya length for i < length döngü int veya testi değiştirerek bir ilan etmesi ile çözülür.

Ne Zaman İmzasız Kullanmalıyım? Sonuç:

Her şey çok tartışmalı burada belirtmek istemiyorum, ama ben sık sık C'de program yazarken uygun burada

  • YOKbir sayı sıfırdan büyük olduğu için sadece kullanın.Kolay hata yapar ve bu hatalar bazen inanılmaz derecede ince (Örnek #2 gösterildiği gibi).

  • YAPINmodüler aritmetik yaparken kullanın.

  • YAPINbitini temsil etmek için kullanırken kullanın.Bu işaret uzantısı olmadan mantıklı değil mi vardiya gerçekleştirmek için izin verir, çünkü genellikle uygundur.

Tabii ki, bu karşı gitmeye karar durumlar olabilir"". kuralları Fakat çoğu zaman daha, bu öneriler aşağıdaki kod ile ve daha az çalışmak için daha kolay hale getirecek hata eğilimli değil.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Damien Hayes

    Damien Hayes

    11 Mart 2008
  • Facebook Developers

    Facebook Dev

    24 ŞUBAT 2009
  • Incredible Tutorials

    Incredible T

    27 EKİM 2006