Soru Gcc standart başlıklarında çok sayıda parantez


GCC başlık dosyalarındaki sabit ifadeler neden parantezlerle çevrelenir?

#define INTMAX_MIN (-9223372036854775807LL)
#define INTMAX_MAX (9223372036854775807LL)

Bu şekilde parantezleri çıkarsam fark ne olurdu?

#define INTMAX_MIN -9223372036854775807LL
#define INTMAX_MAX 9223372036854775807LL

Ve neden 'L' soneki var? Aşağıdakileri yazarsam aynı olur mu?

#define INTMAX_MIN -9223372036854775807
#define INTMAX_MAX 9223372036854775807

Gerçek bir yararlılık var mı yoksa her zaman aynı şey mi?

'L' nin uzun sürdüğü ve C makrolarındaki parantezlerin öneminin de farkında olduğumun farkındayım. Bunu merak uğruna soruyorum.


44
2017-12-27 02:19


Menşei




Cevaplar:


Yazdın

a = 7 INTMAX_MIN;

Bir sözdizimi hatası almayı beklersiniz, çünkü bunun karşısında yasadışı bir ifade olacaktır. Ve olacak, çünkü

a = 7 (-9223372036854775807LL);

gerçekten size bir sözdizimi hatası veriyor. Ancak parantezler olmadan aşağıdakilere genişlerdi:

a = 7 -9223372036854775807LL;

Bu, size niyet ettiğin gibi olmamasına rağmen, size bir hata vermez.

Daha genel olarak, bu tanımların tümü tanımlayıcılara benzeyen şeyler için genişlemeler sağlar. Bir aritmetik ifadede, bir tanımlayıcı "birincil ifade" dir, ancak -9223372036854775807LL değildir. Bununla birlikte, parantezli bir ifade "birincil ifade" dir.

Ve bu gerçek sebep. Böylece makro ne genişliyor gibi görünüyor bir şeye birincil bir ifade olduğu Bir birincil ifade. Olanlardan asla şaşıracaksın. Programlamada sürpriz genellikle kötüdür.

Genellikle fark etmez, ancak tanımları yazan insanlar genellikle çalışmalarını istemezler. Her zaman çalışmasını istiyorlar.

İzleyen LL, bu tamsayı yazım türüne göre işaretler. long longBu tipik olarak (ve bu durumda) 64 bittir. LL son eki olmadan, gerçek, int, long int veya long long int olarak yorumlanabilir (hangisi 64 bitlik değerleri destekleyen ilk hangisiyse). Türü aşmak, değeri bozmak kadar önemli olabilir.


84
2017-12-27 02:39



Ayrıca tartışabilirsiniz a = 7-INT_MAX; parantez içeren ve içermeyen INT_MAXsonucun farklı olacağını belirterek a = 7 - INT_MAX;. - Jonathan Leffler
@JonathanLeffler Sonuç nasıl farklı olurdu? İçin parantez gerekmez INT_MAX bir tamsayı değişmezi birincil ifadedir. - Eric M Schmidt
@EricMSchmidt: … Blah, falan…  ... Tabii ... Oh drat! Özgün ön işlem süreci bir cevap vermişti, ancak modern (1989 ya da daha sonraki sürümlerde olduğu gibi) girdiyi belirliyor ve girdi belirsiz kalıyor. #define X -7 ve int main(void) { int x = 7-X; return x; } Durum 14 ile çıkacak bir program verir. Hatırlamam gerekirdi. - Jonathan Leffler
"literal, sıradan bir tamsayı olarak yorumlanacaktır", @mafso yorumları olarak yanlıştır. Deneyin printf("%zu\n", sizeof (9223372036854775807)); - chux
@mafso: Bu, dilin bakış açısından tamamen doğru değil. Kullanarak izin verilen C dilinin tek standart sürümü imzasız soneksiz sabitler için tipler C89 / 90'dı. Bu işlev C99'da yasa dışıydı. Eklenti sabitleri sadece sahip olabilir imzalı türleri. Sabit, en büyük imzalı türe sığmazsa davranış tanımsızdır. Yani dili kullanarak desteklemiyor unsigned long long soneksiz bir sabit için. - AnT


Parantezleri bir tamsayı sabiti ve bunun gibi tek bir operatör ile makroya koymak iyi bir uygulamadır:

#define BLA (-1)

tekli operatörler olarak (- Burada) C.'de en yüksek önceliğe sahip değildir. Postfix operatörleri, tekli operatörlerden daha yüksek önceliğe sahiptir. Örneğin C'nin negatif sabitleri olmadığını unutmayın. -1 Öncelikle sabit bir ifadedir - tek operatör.

PC-Lint bir kenara bu gibi makrolarda parantez içinde öneriyoruz:

(kural 973): parentheser #define N (-1)   Parantez içinde değil, 'Sembol' makroda tek operatör   İfade benzeri bir makroda görünen operatörün parantez içinde olmadığı bulundu. İçin   örnek:

#define N -1

Kullanıcı aşağıdaki gibi parantez yapmayı tercih edebilir:

#define N (-1)

19
2017-12-27 02:33





Bu cevap neden olduğunu göstermeye çalışıyor LL gereklidir. (Bu kolay değil.)
Diğer cevaplar parantezlerin neden gerekli olduğunu göstermiştir.

Üç makroyu kodlayalım, hepsi ondalık sabitler.

#define MAXILL (9223372036854775807LL)
#define MAXIL  (9223372036854775807L)
#define MAXI   (9223372036854775807)

Buna rağmen MAXI son eki yok, bu tür yazmaz int. MAXI ilk tipine sığacak int, long, long longveya genişletilmiş bir tamsayı türü.

Buna rağmen MAXIL var L soneki, içine sığdığı ilk türe sahip olacak long, long longveya genişletilmiş bir tamsayı türü.

Buna rağmen MAXILL var LL soneki, içine sığdığı ilk türe sahip olacak long longveya genişletilmiş bir tamsayı türü.

Her durumda, makrolar aynı değere sahiptir, ancak potansiyel farklı şekiller.

Tip tayini için C11dr §6.4.4.1 5'e bakınız.


Onları basmayı deneyelim ve int ve long 32 bit ve long long ve intmax_t 64.

printf("I   %d %d %d",       MAXI, MAXIL, MAXILL);    //Error: type mismatch
printf("LI  %ld %ld %ld",    MAXI, MAXIL, MAXILL);    //Error: type mismatch
printf("LLI %lld %lld %lld", MAXI, MAXIL, MAXILL);    //Ok

Son üç çizgideki üçü de, her üç makro da doğru long longÖncelikle, biçim belirteci ve sayı arasındaki tür yanlış eşleşmeleri vardır.

Eğer sahipsek int 32-bit ve long, long long ve intmax_t 64, sonra aşağıdakiler doğrudur.

printf("LI  %ld %ld",    MAXI, MAXIL);
printf("LLI %lld", MAXILL);

Maksimum genişlik tamsayı türünde bir biçim belirteci var "%" PRIdMAX. Bu makroya genişletilemiyor "%ld"  ve  "%lld" karşılamak için MAXI, MAXIL, MAXILL. Bu ayarlanır "%lld" ve sayılar ile ilgili intmax_t aynı tür olması gerekir. Bu durumda, long long ve sadece formu MAXILL kullanılmalıdır.


Diğer uygulamalar, genişletilmiş bir tamsayı türüne sahip olabilir ( int128_t), bu durumda uygulamaya özel bir sonek veya bazı mekanizmalar kullanılabilir.


13
2017-12-27 07:23



Bir not olarak, C11 ile _Generic (ve daha önce popüler olanla typeof uzatma) türleri daha kolay gözlemlenebilir hale gelmiştir. (Eklentisiz C99'da, aradaki farkın nasıl olduğunu bilmiyorum long ve long long aynı büyüklük ve temsiliyetleri varsa gözlemlenebilir; Eğer uygulama, çağrı düzenleri hakkında varsayımlar yaparsa ve bu oldukça muhtemel değildir. long ve long long farklı geçilir, son C99 için gerçekten gerekli olup olmadığı sorusu kalır.) - mafso