Memcpy () ve memmove () "bayt sayısı" sıfır olarak ayarlıyken çağırabilir miyim?


104

Ben actully hareket şey yok olduğunda / tedavi durumlarda gerek ile kopya mı memmove()/ ' memcpy()uç örnekleri olarak

int numberOfBytes = ...
if( numberOfBytes != 0 ) {
    memmove( dest, source, numberOfBytes );
}

yoksa işlevi kontrol etmeden çağırmalı mıyım

int numberOfBytes = ...
memmove( dest, source, numberOfBytes );

Eski kod parçacığındaki kontrol gerekli mi?


6
soru bana free gibi işlevler üzerinde boş işaretçileri kontrol etmeyi hatırlatıyor. Gerekli değil, ama bunun hakkında düşündüğünüzü göstermek için oraya bir yorum koyardım.
Toad

12
@Toad: Bu, kodu karıştırmaktan başka hangi amaca hizmet ediyor? Birinin kodunu okurken, orijinal programcının "aslında gerekli olmayan bu işlemi yapmayı düşündüğünü, ama gereksiz olduğu için ben yapmadım" bilmeme gerek yok. Bir işaretçinin serbest bırakıldığını görürsem, boş olmasına izin verildiğini biliyorum , bu yüzden orijinal programcının "boş olup olmadığını kontrol etmeliyim" konusundaki düşüncelerini bilmeme gerek yok. Aynı şey 0 bayt ilememcpy
jalf

9
@jalf: Stackoverflow ile ilgili bir soru olması, bunu insanların şüphe duyduğu bir şey haline getiriyor. Yani bir yorum eklemek size yardımcı olmayabilir, ancak daha az bilgiye sahip birine yardımcı olabilir
Toad

2
@Toad Evet, gerekli görünen bir kontrolün neden gerçekten değerli olmadığını açıkça belirten yorumlar prensipte değerli olabilir. Diğer madalyonun yan bu özel örnekte, her programcı sadece bir kez cevabını öğrenmek için ihtiyaç duyduğu standart bir kütüphane işlevi içeren ortak bir durumda olmasıdır; daha sonra okudukları herhangi bir programda bu kontrollerin gerekli olmadığını anlayabilirler. İçin bu nedenle, ben bir yorum ihmal ediyorum. Bunun gibi birden çok çağrıya sahip bir kod tabanının yorumları kopyalayıp her birine yapıştırması veya her ikisi de çirkin olan yalnızca bazı çağrılarda keyfi olarak kullanması gerekir.
Mark Amery

Yanıtlar:


146

C99 standardından (7.21.1 / 2):

Bir bağımsız değişkenin size_t nbir işlev için dizinin uzunluğunu belirttiği durumlarda, no işleve yapılan bir çağrıda sıfır değeri olabilir. Bu alt maddede belirli bir işlevin açıklamasında açıkça aksi belirtilmediği sürece, böyle bir çağrıya ilişkin işaretçi argümanları, 7.1.4'te açıklandığı gibi yine de geçerli değerlere sahip olacaktır. Böyle bir çağrıda, bir karakteri bulan bir işlev hiçbir oluşum bulmaz, iki karakter dizisini karşılaştıran bir işlev sıfır döndürür ve karakterleri kopyalayan bir işlev sıfır karakterleri kopyalar.

Dolayısıyla yanıt hayır; kontrol gerekli değildir (veya evet; sıfırı geçebilirsiniz).


1
Bir gösterici, bir dizinin son elemanını takip eden konuma işaret etse, böyle bir işlevin amaçları açısından "geçerli" kabul edilir mi? Böyle bir işaretçi meşru olarak ertelenemezdi, ancak bir kişi ondan çıkarmak gibi diğer işaretçi benzeri şeyleri güvenle yapabilir.
supercat

1
@supercat: evet, bir dizinin sonunu bir ötesine işaret eden bir işaretçi, o dizinin içindeki (veya sonunu geçen) diğer işaretçilerle işaretçi aritmetiği için geçerlidir, ancak ayrıştırılamaz.
Mike Seymour

@MikeSeymour: Alıntı zıt bir cevap anlamına gelmemeli: kontrol gerekli ve sıfır işaretçilerle sıfırı geçemez misiniz?
neverhoodboy

7
@neverhoodboy: Hayır, alıntı açıkça " nsıfır değerine sahip olabilir " diyor . Boş işaretçileri geçemeyeceğiniz konusunda haklısınız, ancak sorunun sorduğu bu değil.
Mike Seymour

1
@MikeSeymour: Benim hatam. Gerçekten özür dilerim. Soru, işaretçi değil boyutla ilgili.
neverhoodboy

5

@You'nun söylediği gibi, standart memcpy ve memmove'un bu vakayı sorunsuz bir şekilde ele alması gerektiğini belirtir; genellikle bir şekilde uygulandıkları için

void *memcpy(void *_dst, const void *_src, size_t len)
{
    unsigned char *dst = _dst;
    const unsigned char *src = _src;
    while(len-- > 0)
        *dst++ = *src++;
    return _dst;
}

işlev çağrısı dışında herhangi bir performans cezasına bile maruz kalmamalısınız; derleyici bu tür işlevler için içsel / satır içi desteği destekliyorsa, ek denetim kodu mikro-biraz daha yavaş hale getirebilir, çünkü denetim zaten bu sırada yapılır.


1
Bu işlevin muhtemelen bellek aktarımlarını c
Toad

"bir şekilde" :) Aslında gördüğüm neredeyse tüm uygulamalar derlemede ve bitlerin çoğunu yerel kelime boyutunu kullanarak kopyalamaya çalışıyor (örn. x86'da uint32_t), ancak bu, cevabın özünü değiştirmiyor : başlamadan önce harika hesaplamalar gerektirmeyen bir süre döngüsüdür, bu nedenle kontrol zaten yapılmıştır.
Matteo Italia

9
-1, tipik uygulama C'nin bu işlevleri (C işlevleri olarak uygulanmayabilir) sıfır bağımsız değişkenle çağırmanın geçerli olup olmadığı ile ilgisizdir.
R .. GitHub BUZA YARDIM ETMEYİ DURDUR

4
C'nin geçerli olduğu gerçeği, cevabımın en başında söylediğim gibi, diğer cevaplar tarafından zaten kapsanmıştır: "@You'nun söylediği gibi , standart memcpy ve memmove'un bu vakayı sorunsuz bir şekilde ele alması gerektiğini belirtir". Performans nedenlerinden ötürü memcpy'i len = 0 ile aramaktan korkmamanız gerektiği konusunda fikrimi ekledim, çünkü bu durumda bu neredeyse sıfır maliyetli bir arama.
Matteo Italia
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.