2014-07-03 22 views
5

'daki iki kod konumu arasındaki satırları sayın İki kod konumu arasındaki satır sayısını saymak için C önişlemcisini kullanmak istiyorum.C önişlemcisi

#define START __LINE__ 
static char* string_list[] = { 
    "some string", 
    "another string", 
    ... 
    "last string" 
}; 
#define END __LINE__ 
#if END - START > 42 
    #error Too many entries 
#endif 

Tabii bu, bu durumda START çünkü çalışmaz ve END sadece makro __LINE__ redefinitions şunlardır: Temel fikir böyle bir şeydir.
# ve ## işleçleriyle biraz etrafta oynuyordum, ancak önişlemci çalışırken START ve END değerlerini değerlendirmek için önişlemciyi alamadım.

Sorum şu: Bu mümkün mü?

Çalışma zamanı sırasında dizinin boyutunun kontrol edilmesi bir seçenek değildir.
Önceden herhangi bir ipucu veya fikir için teşekkürler!

+0

Advise 'statik const char * dize_list [] ... – Clifford

+0

“ Çalışma sırasında dizinin boyutunun kontrol edilmesi ”(C) bu imkansızdır. 'Sizeof' bir derleme zamanı sabiti verdiğinin farkında mısınız? Ve “önişlemci çalışırken” gerçekten bir gereklilik (ne 'sizeof' yerine getirmeyecek)? – mafso

cevap

8

Bu makrosunu bu amaçla kullanmamalısınız: Bir yere fazladan bir satır eklediyseniz, kod tamamen sürdürülemez duruma gelecektir. Ya çok az satır varsa? Böyle örneğin, static_assert desteği vardır C11 kullanmıyorsanız

static_assert(sizeof(string_list)/sizeof(*string_list) == SOME_CONSTANT, 
       "Wrong number of entries in string list."); 

, bu tür bilgileri bir kendini öne sürmek mümkün: Bunun yerine makro

, statik bir assert kullanmak

#define COMPILE_TIME_ASSERT(expr) {typedef uint8_t COMP_TIME_ASSERT[(expr) ? 1 : 0];} 
+0

+1. Bu COMPILE_TIME_ASSERT makrosu, son googleplex yılları için kullandığımdan daha gizli. – Bathsheba

+0

@Bathsheba Kesinlikle orada böyle çok çirkin makrolar var :) Şahsen standartlaştırılmış 'static_assert' C11'e yükseltmek için yeterli sebep olduğunu düşünüyorum. – Lundin

+0

Çok teşekkür ederim. Bu, – Chris

5

[kullanabileceğiniz işaret @Lundin onayla bir typedef]

Bu tek yönlü

olduğunu 10
typedef uint8_t START[__LINE__]; /*put this on one line*/ 

typedef uint8_t END[__LINE__]; /*put this on another line*/ 

sizeof(END) - sizeof(START) ofset hattı veren derleme ifadesidir.

Makrolara koyun ve tadı için START ve END yeniden adlandırın. Çok fazla olan başlatıcı sağlarsanız

static const char* string_list[42] = {... 

derleyici anlatacağım: böylece diziyi bildirirseniz

+0

Veya "typedef uint8_t n1 [__ LINE __];" işlevini kullanın, böylece hiçbir şey ayırmanıza gerek kalmaz. Yine de, bu, '__LINE__' makrolarının dizi boyutlarının statik olarak denetlenmesi için uygun olmayan temel sorunu çözmez. – Lundin

+0

@Lundin: Bu zarif ve benim için çalışıyor (gcc ve msvc2012). Değiştirdim. – Bathsheba

0

.

static char* string_list[43] = { ..., NULL } ; 

Ve belki bunu biliyor gerekiyorsa zamanında uzunluğunu belirlemek için bir işlev yazma: Sen eğer gerekli sonunu işaretlemek için bir gözcü girişi sağlayabilir.

+0

Sorun şu ki, bu sizi çok az başlatıcıya karşı korumaz. – Lundin

+0

Tabii ki değil, ama sorudaki kod asla çok az * için test etmiyordu. – Clifford

İlgili konular