Sizeof (int) doğru iken sizeof int neden yanlış?


97

sizeofHerhangi bir veri türü ve ifadenin boyutunu hesaplamak için kullanılan bir operatör olduğunu biliyoruz ve işlenen bir ifade olduğunda parantezler ihmal edilebilir.

int main()
{
        int a;

        sizeof int;
        sizeof( int );
        sizeof a;
        sizeof( a );

        return 0;
}

ilk kullanım sizeofyanlış, diğerleri haklı.

Gcc kullanılarak derlendiğinde, aşağıdaki hata mesajı verilecektir:

main.c:5:9: error: expected expression beforeint

Sorum şu ki, C standardı bu tür bir işleme neden izin vermiyor. Will sizeof intbelirsizliği neden?


5
Komik olan, tüm ifadelerin parantez olmadan kabul edilmemesidir: deneyin sizeof (int)a.
Fred Foo

2
@MikkelK .: OP, işaretli cevapta belirtilen alıntıları zaten bildiği standart alıntıların arkasında akıl yürütme istiyor.
Alok Save

2
@Lundin: aslında derleme sizeof +(int)aavantajına sahip *&;-)
Steve Jessop

2
@SteveJessop Ah doğru, bu bir değer değil. Embarcadero C ++ ile derlenmiş olsa da, garip bir şekilde yeterince. Her neyse, şimdi unary + operatörü için bir kullanım bulduğumuza inanıyorum! Bu, C programlama tarihinde ilk defa olmalı :)
Lundin

2
@Lundin: Unary konusunda hala dikkatli olmalısın +. Örneğin, sizeof +(char)a == sizeof(int)tamsayı ilerletme nedeniyle, boyutunu almaya çalıştığınız ifadeyle ilgili herhangi bir endişe varsa, parantez içine koymak muhtemelen daha az hataya meyillidir. Bu yüzden "kullanım" diyecek kadar ileri gideceğimden emin değilim, ancak onu kullandığımı kabul
etsem

Yanıtlar:


101

Aşağıdakiler belirsiz olabilir:

sizeof int * + 1

Bu mu (sizeof (int*)) + 1yoksa (sizeof(int)) * (+1)?

Açıkçası, C dili belirsizliği çözmek için bir kural getirebilirdi, ancak neden rahatsız etmediğini tahmin edebiliyorum. Dil olduğu haliyle, bir tür belirticisi bir ifadede hiçbir zaman "çıplak" görünmez ve bu nedenle, ikincisinin *türün bir parçası mı yoksa bir aritmetik işleci mi olduğunu çözmek için kurallara gerek yoktur .

Mevcut dilbilgisi, şimdiden olası belirsizliğini çözüyor sizeof (int *) + 1. Öyle (sizeof(int*))+1, değil sizeof((int*)(+1)) .

C ++, işlev tarzı çevrim sözdizimi ile çözülmesi gereken benzer bir soruna sahiptir. Sen yazabilir int(0)ve yazabilir typedef int *intptr; intptr(0);ama yazamıyorum int*(0). Bu durumda, çözüm, "açık" türün basit bir tür adı olması gerektiğidir, yalnızca içinde boşluklar veya noktalama işaretleri bulunan herhangi bir eski tür kimliği olamaz. Belki sizeofaynı kısıtlamayla tanımlanabilirdi, emin değilim.


1
C ++, new int*(X)yeni operatörün muhtemelen bir tür olabilecek en uzun dizeyi aldığını belirtmediyse, bu belirsiz olacaktır. Yani C ++ 'da sizeof ile aynı şeyi yapabilirlerdi, sanırım. Ancak C ++ 'da sizeof int()hangisinin belirsiz olacağını söyleyebilirsiniz (tür veya değer başlatılmış int?).
Johannes Schaub -

@ JohannesSchaub-litb: Mmm, bu yüzden belki o zaman C ++, eğer birini ayrıştırmak mümkünse, türün tercih edildiğini söyleyebilir, aksi takdirde bir ifadedir. Belirsizlik çözüleceğini ancak sizeof int()( "hayır kötü kurulacağını operator()için size_tben istenmeyen olacağını bekliyoruz, hangi")!
Steve Jessop

32

Gönderen C99 Standardı

6.5.3.4.2 operatör bir ekspresyon ya da bir tür parantez içinde adı olabilir onun işlenen (bayt) boyutu, elde edilir.
sizeof

Sizin durumunuzda intne ifade ne de parantezli isim.


10
Bunun neden 7 olumlu oy aldığını anlamıyorum. Silinen üç cevap gibi, kuralın neden var olduğunu açıklamak yerine sadece kuralı tekrarlar.
Fred Foo

8
@larsmans, evet, sana katılıyorum. Kuralı tekrarlamaya devam etse de, en azından, okumaya yetki veren bir parça verir.
Yishu Fang

3
@larsmans C99'da alınan her kararı haklı çıkarmaya başlarsak, tüm yıl burada olacağız. Standarttan alıntı yapmak, bu tartışmayı tamamlamanın herhangi bir yolu kadar iyidir.
Perry

1
@Perry: Bu türden bir soruyu beğenmediyseniz, soruyu tartışmalı olarak kapatmak için oy verebilirsiniz.
Fred Foo

4
C ++ 'ın uygulayıcısı olmayan biri olarak, ben bile bu cevabı anlıyorum, İngilizceyi okuyup anlayabiliyorsanız sorunun ne olduğundan emin değilim.
Kev

6

C'de sizeof operatörünü kullanmanın iki yolu vardır. Sözdizimi şudur:

C11 6.5.3 Unary operators
...
sizeof unary-expression
sizeof ( type-name )

Bir türü işlenen olarak kullandığınızda, dilin sözdizimi tanımına göre paranteze sahip olmalısınız. Bir ifadede sizeof kullanırsanız, paranteze ihtiyacınız yoktur.

C standardı, onu bir ifadede nerede kullanmak isteyebileceğinize dair böyle bir örnek verir:

sizeof array / sizeof array[0]

Bununla birlikte, tutarlılık adına ve operatör önceliğiyle ilgili hatalardan kaçınmak için, kişisel olarak durum ne olursa olsun her zaman () kullanmanızı tavsiye ederim.


@ JohannesSchaub-litb C standart komitesinin C90 standardını belirlerken nasıl gerekçelendirdiğine dair herhangi bir gerekçe sağlamadığını kabul ediyorum. Onlara sormanız gerekir ... Herhangi bir gerekçe olmaksızın cevap verir, ancak sözdizimi 6.5.3'te belirtildiği gibi olduğundan C buna izin vermez. OP ayrıca bu cevapta açıklanan sizeof expressionve arasındaki farkın farkında değilmiş gibi görünüyordu sizeof(type).
Lundin

(Kayıt için, hem C90 hem de C11 gerekçelerini okudum ve hiçbiri herhangi bir açıklama
sunmuyor

Bunun için gerekli bir gerekçe olmadığından şüpheleniyorum, sadece orijinal C tasarımcılarının yapmaya karar verme şekli. Belki de erken ayrıştırıcı için işleri kolaylaştırdı. Yazı tiplerinin ve değişkenlerin aynı isim alanını paylaştığı gerçeği hakkında bir cevap gönderecektim, ancak bu ilk sözdizimine izin vermeyi engellemez; sadece ayrıştırma kurallarına ihtiyaç duyduğu zaman değişkeni parantez olmadığında tercih ettiğini, varsa türü tercih ettiğini ve isim net olduğunda her iki form da kullanılabilir. Değiştirmeye gerek olmadığı için, standartlar komiteleri onu yalnız bıraktı.
Barmar
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.