2013-07-02 11 views
7

C ve C++ standartlarının tümü, bir dize işlemi geçerli bir dize değişmez jetonu üretemediğinde, davranışın tanımsız olduğu etkisine metin içerir. C++ 11'de, bu, bir ham dizgi değişmezinde bir satırsonu karakteri ekleyerek mümkündür. Ama yakalananlar her zaman standartlarda olmuştur. UB veya kötü oluşturulmuş program zaten olmadı Operatör hatası dizisi

stringize UB üretebilir başka bir yolu var mı

?

C veya C++ herhangi bir lehçesi hakkında duymak isterim. Ben bir ön işlemci olan writing.

+3

Çoğu insan, onları işe değil almak için mücadele başaramamak. –

+0

Hah… Başarısızlığın doğru olduğunu, yani bir test çantası aldığını doğrulamak istiyorum. Yeni satırlarla ilgili hile, onu tuzağa düşürdüğümden ve bir \ n \ eklediğim için yardımcı olmaz. Tamam – Potatoswatter

+0

sonra ne soran alamadım, sen önişlemci testcases gerek (Aslında bu, ters eğik çizgi sayıyorsanız eğer. Bir ' "\\\\ n"' bulunuyor). mcpp'nin bazı doğrulama paketi var. –

cevap

4

Stringify (#) operatörü, dize sabitlerinde yalnızca \'dan kaçar. Gerçekten de, bir satırın sonu hariç, \ dizgisi sabiti dışında özel bir önemi yoktur. Bu nedenle, bir ön işlem jetonudur (C bölüm 6.4, C++ bölüm 2.5).

Sonuç olarak, varsa

#define Q(X) #X 

sonra

Q(\) 

meşru çağrısıdır: \ bir göstergesi dönüştürülür asla bir ön işleme belirteci, bu nedenle geçerli bu. Ancak \ dizgesini oluşturamazsınız; Bu, geçerli bir dizgi değişmezi olmayan "\" değerini verir. Bu nedenle, yukarıdakilerin davranışı tanımlanmamıştır.

Burada daha eğlenceli test durumu var:

#define Q(A) #A 
#define ESCAPE(c) Q(\c) 
const char* new_line=ESCAPE(n); 
const char* undefined_behaviour=ESCAPE(x); 

dizgelenmiş parametre değişmez bir dize olamayacak kadar uzun nerede olacağını tanımlanmamış bir stringify bir az ilginç bir durumdur. (Standartlar, bir dizgi maksimum boyutu en az 65536 karakter ama muhtemelen daha büyük olabilecek bir makro argüman, maksimum boyutu hakkında hiçbir şey söylemek öneririz.)

+0

Teşekkürler! Shoulda bunu düşündü. Sonlandırılmamış bir dize zaten ham dize catenation'da test ettiğim bir şeydir ve bu da aynı şekilde tuzağa düşer :). Daha fazla eğlenceli durumunuz, ön işlemcideki UB gibi görünmüyor; '' \ x ''yazmakla aynı şey mi yoksa bir şey mi özlüyorum? , Bir dizgi s-karakter içeriyor ve evrensel karakterli-isimleri-dizilerini kaçış: – Potatoswatter

+0

@Potatoswatter (. Sekanslar daha sonra çevrilir Kaçış). '\ x' yukarıdakilerin hiçbiri değildir. Yani ' "\ x"' değişmez geçerli bir dize değil, ben öyle anlıyorum ve böylece (x) '(veya bu konuda,' ESCAPE (*) ') tanımsız KAÇIŞ' ile önişlemci fiyatlarını nasıl. Öyleyse, ön işlemcinin, eğer seçtiyse, ikisini de bir gülen yüzle değiştirebilirdi. – rici

+0

En azından C++, "Ters eğik çizgiyi izleyen karakterin Tablo 7'de listelenmediği çıkış sekansları, uygulama tarafından tanımlanan semantiklerle koşullu olarak desteklenir." Öyleyse, ayrık bir önişlemci için biraz kısıtlayıcı olacağını düşünüyorum. Ama haklısın, bu gramer :) Tekrar teşekkürler! – Potatoswatter