C'deki bir fonksiyonun boyutu neden her zaman 1 bayttır?


87

Bir fonksiyonun boyutunu kullanarak kontrol sizeof()ettiğimizde, her zaman 1 bayt elde ederiz . Bu 1 bayt ne anlama geliyor?

Yanıtlar:


80

Bu bir kısıtlama ihlalidir ve derleyiciniz bunu teşhis etmelidir . Buna rağmen derlerse, programınız tanımsız davranışa sahiptir [hata kipinin açıklığa kavuşturulması için @Steve Jessop'a teşekkürler ve bazı derleyicilerin buna neden izin verdiğine dair @ Michael Burr'un cevabına bakın]: C11'den , 6.5.3.4./ 1:

sizeofOperatör fonksiyon türüne sahip bir ifadesine uygulanabilir değildir


11
Bu bir kısıt, yani uyumlu bir derleyicide teşhis edildiği anlamına gelir. Derleyici onu yine de derlerse (tanı koymuşsa), davranış tanımsızdır. Derleyici bunu teşhis etmezse (örneğin gcc onsuz yapmazsa -pedantic), uyumsuz bir derleyiciniz vardır ve her programın tanımsız davranışı vardır.
Steve Jessop

1
Davranış onu bir GNU C uzantısı ile aynı kategoriye koyar, ancak neden birinin bu davranışı istediği hakkında hiçbir fikrim yok , bu yüzden GNU yazarlarının onu eklemek için neden kendi yollarından çıktıklarını bilmiyorum.
Steve Jessop

1
@SteveJessop: Bunun eşit olduğuna dikkat edin -std=c11, değil gnu11 . Bu gerçekten tuhaf bir derleyici uzantısı.
Kerrek SB

6
Ooh! Bahse girerim fonksiyon işaretçilerinde aritmetiği etkinleştirmek için sizeof(void), GNU C'de 1 olanla aynı şekilde
Steve Jessop 4'12

3
İlgili olarak -std=c11: birisi -std=c*seçeneklere Reklam Standartları'na başvurmalıdır . Uyumluluk modunu etkinleştirmezler, yalnızca iyi biçimlendirilmiş bir programın derlenmesini engelleyen uzantıları devre dışı bırakırlar (örneğin typeof, iyi biçimlendirilmiş bir C programı onu bir değişken adı olarak kullanabilir, ancak gccvarsayılan olarak bunu reddeder) ). Ek olarak, kötü biçimlendirilmiş programların teşhis edilmeden geçmesine izin veren uzantıları devre dışı bırakmak için, -pedanticveya -pedantic-errors.
Steve Jessop

56

Bu tanımsız bir davranış değildir - C dili standardı, sizeofoperatör için bir kısıtlama ihlali olduğundan, operatör bir işlev belirleyiciyle (bir işlev adı) kullanıldığında bir tanı gerektirir sizeof.

Bununla birlikte, C dilinin bir uzantısı olarak, GCC void, a voidveya bir işlevin boyutuna göre yapılan, işaretçiler ve işlev işaretçileri üzerinde aritmetiğe izin verir 1. Sonuç olarak, sizeofoperatör için değerlendirecek 1için voidveya GCC ile bir işlev. Bkz. Http://gcc.gnu.org/onlinedocs/gcc/Pointer-Arith.html#Pointer-Arith

GCC'nin veya seçeneklerini kullanarak GCC'nin sizeofbu işlenenlerle kullanırken bir uyarı vermesini sağlayabilirsiniz . Veya ile bir hata yapın .-pedantic-Wpointer-arith-Werror=pointer-arith


Mantığınız kusurlu. C bazıları için tanı mesajları gerektirir, ancak tümü UB için değil. Sırf bir teşhis olduğu için bir şeyin tanımlanmış davranışı olduğunu söyleyemezsiniz.
MSalters

4
C, tüm kısıtlama ihlalleri için bir teşhis gerektirir (5.1.1.3 C99 veya C11'de Teşhis). Bir kısıtlama (C99 / C11'de 3.8), "dil öğelerinin açıklamasının yorumlanacağı sözdizimsel veya anlamsal bir kısıtlamadır" ve bu, kısıtlamaları takip etmeyen bir şeyin yorumlanamayacağını söylüyor gibi görünüyor .
Michael Burr

3
Ve açık olmak gerekirse - bir kısıtlama ihlali, tanımsız davranışla sonuçlanmaz. Sözdizimi hatası gibi bir hatadır. Örneğin, standart , bir kısıtlamanın dışında görünen "bir" yapılacak "veya" olmayacak "şartı ihlal edilirse , davranış tanımsızdır" der . Bir kısıtlama ihlali UB ile sonuçlanacaksa, standart neden burada kısıtlamalarda bulunmayan sadece "yapılacaklar" ve "olmayacaklar" dan bahsediyor?
Michael Burr 04

3
sizeofBir işlevin UB olmaması dışında UB hakkında pek bir şey ifade etmedim (sadece diğer yanıtların UB olduğunu söylediği için hemen hemen bahsetmiştim). Ama belki de cümleyi kurgulama şeklim yüzünden bunu karıştırdım. Daha net olmak için. sizeofbir işlev UB değildir (birkaç yanıtın iddia ettiği gibi). Bu bir kısıtlama ihlalidir. Bu nedenle, bir teşhis gerektirir. GCC, bir uzantı olarak izin verir.
Michael Burr

2
@KerrekSB: OP bir teşhis almıyor çünkü muhtemelen GCC kullanıyorlar, bu da bu kullanıma bir C dili uzantısı olarak izin veriyor.
Michael Burr

13

Bu, derleyicinin yazarının, iblisleri burnunuzdan uçurmak yerine 1 değerine karar verdiğini gösterir (aslında, sizeofbize bu ifadenin tanımlanmamış başka bir kullanımıydı : "C derleyicisinin kendisi bir tanı koyması GEREKİRSE bu ilk gerekliyse programınızdan kaynaklanan teşhis ve daha sonra kendisi iblislerin burnunuzdan uçmasına neden olabilir (ki bu bu arada belgelenmiş teşhis mesajı olabilir), sözdizimi kurallarının veya kısıtlamalarının daha fazla ihlali için daha fazla teşhis sunabilir (veya bu nedenle, seçtiği herhangi bir nedenle). " https://groups.google.com/forum/?fromgroups=#!msg/comp.std.c/ycpVKxTZkgw/S2hHdTbv4d8J

Bundan, bir derleyicinin tanımlanmamış bir yapıya yanıt olarak yapmaya karar verdiği şey için kullanılan argo terim "nazal iblisler" var. 1bu durum için bu derleyicinin nazal iblisidir.


@IlmariKaronen Yine de itiraf etmeliyim ki, C (ve C ++) ile ilgili cevaplarımın çoğunun ya genel dilden bağımsız ilkeler ya da bunun gibi tarihsel külçeler üzerine olmasının bir nedeni var. C deneyimim kendi içinde tarihi sınırlıyor :)
Jon Hanna

7

Diğerlerinin de belirttiği gibi, sizeof () herhangi bir geçerli tanımlayıcı alabilir, ancak işlev adları için geçerli (dürüstçe doğru ve geçerli) bir sonuç döndürmez. Dahası, kesinlikle "burundan iblisler" sendromuna neden olabilir veya olmayabilir.

Program işlev boyutunuzun profilini çıkarmak istiyorsanız, ara sonuç dizininde (şeylerin .obj / .o olarak derlendiği veya elde edilen görüntünün / yürütülebilir dosyanın bulunduğu yer) bulunabilen bağlayıcı haritasını kontrol edin. Bazen bu harita dosyasını oluşturup oluşturmama seçeneği vardır ... derleyiciye / bağlayıcıya bağlıdır.

Bir işleve bir işaretçi boyutunu istiyorsanız, hepsi aynı boyuttadır, işlemcinizdeki adresleme kelimesinin boyutundadır.


1
Ne tür bir ifade "kesinlikle olabilir veya olmayabilir" ??? Bu kelimenin tam anlamıyla her şey için doğru değil mi?
Kerrek SB

@KerrekSB evet, ama burada bir şey yapabilir veya yapmayabilir ve yine de kurallar dahilinde olabilir. Bir derleyicinin derlemeyi reddedebileceği veya reddedemeyeceği doğrudur, int x = 1;ancak standartlara uyumlu bir derleyici için bunlardan yalnızca birine izin verilir. İle sizeof()bir işleve uygulanmakta olan, bu ya bir dizi değer döndürmek veya derlemeye reddeder veya sırasında belirli bir kayıtta ne varsa dayanan rasgele bir değer döndürmek veya olmayabilir. Basit burun iblisleri olası değildir, ancak standardın lafzı dahilindedir.
Jon Hanna

@kerrek Hiçbir şey için doğru olabilir ya da hiçbir şey için yanlış olmayabilir ... Bunu bulanık mantıksız olarak bakın.
jpinto3912

1
Bir işlevin işaretçisinin boyutunu bilmek istiyorsanız, bir işlevin sizeofişaretçisine uygulayın.
alexis
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.