2010-10-23 39 views
12

Tôi có một số C-program (mô-đun Apache, tức là chương trình chạy thường xuyên), sẽ là write() chuỗi 0 chấm dứt trên ổ cắm, vì vậy tôi cần biết chiều dài của nó.Xác định # độ dài chuỗi được xác định tại thời gian biên dịch

Chuỗi đượC#defined như:

#define POLICY "<?xml version=\"1.0\"?>\n" \ 
    "<!DOCTYPE cross-domain-policy SYSTEM\n" \ 
    "\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \ 
    "<cross-domain-policy>\n" \ 
    "<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \ 
    "</cross-domain-policy>\0" 

Có hài lòng một cách, tốt hơn so với sử dụng strlen(POLICY)+1 tại runtime (và do đó tính độ dài một lần nữa và một lần nữa)?

Chỉ thị tiền xử lý, cho phép thiết lập POLICY_LENGTH đã có lúc biên dịch?

Trả lời

22

Sử dụng sizeof(). ví dụ. sizeof("blah") sẽ đánh giá là 5 tại thời gian biên dịch (5, không phải 4, vì chuỗi ký tự luôn bao gồm ký tự kết thúc rỗng ẩn).

+0

Bạn có thể muốn chắc chắn rằng nó rõ ràng lý do tại sao nó đánh giá đến 5 và không 4. –

+0

sizeof ("blah") là 5. Nhưng vấn đề là sizeof (blah) trong đó 'char * blah =" blah "' là 4 vì nó là một kích thước con trỏ trong hệ thống 32 bit. Đó là một vấn đề bởi vì chúng tôi không cần sizeof ("chuỗi cụ thể"). Chúng ta cần sizeof (given_pointer). Bạn sẽ phải sử dụng strlen (pointer) thay vào đó nhưng là sux và cần thêm +1 là một vấn đề nhỏ ở đây. – Val

2

sizeof công trình tại thời gian biên dịch

#define POLICY "<?xml version=\"1.0\"?>\n" \ 
    "<!DOCTYPE cross-domain-policy SYSTEM\n" \ 
    "\"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">\n" \ 
    "<cross-domain-policy>\n" \ 
    "<allow-access-from domain=\"*\" to-ports=\"8080\"/>\n" \ 
    "</cross-domain-policy>\0" 

char pol[sizeof POLICY]; 
strcpy(pol, POLICY); /* safe, with an extra char to boot */ 

Nếu bạn cần một biểu tượng tiền xử lý với kích thước, chỉ cần đếm số ký tự và viết biểu tượng cho mình :-)

#define POLICY_LENGTH 78 /* just made that number up! */ 
+7

hoặc '#define POLICY_LENGTH (sizeof (POLICY))' ... –

+3

@Oli: Tôi đoán pmg có nghĩa là một biểu thức hợp lệ để sử dụng trong điều kiện tiền xử lý, mà 'sizeof' không phải là .. –

+0

@R: Tôi không biết điều đó. Điều đó có khả năng khá khó chịu ... –

3

Sử dụng 1+strlen(POLICY) và bật tối ưu hóa trình biên dịch. GCC sẽ thay thế strlen (S) với độ dài của S tại thời gian biên dịch nếu giá trị từ S được biết tại thời gian biên dịch.

0

Tôi có vấn đề tương tự khi sử dụng trình biên dịch lỗi thời (VisualDSP) trên nền tảng nhúng chưa hỗ trợ C++ 11 (và vì vậy tôi không thể sử dụng constexpr).

Tôi không cần phải đánh giá độ dài chuỗi trong trình biên dịch trước, nhưng tôi cần tối ưu hóa nó thành một nhiệm vụ duy nhất.

Chỉ trong trường hợp ai đó cần này trong tương lai, đây là giải pháp cực kỳ hacky của tôi mà phải làm việc trên các trình biên dịch thậm chí không hấp dẫn như miễn là họ làm tối ưu hóa thích hợp:

#define STRLENS(a,i)  !a[i] ? i : // repetitive stuff 
#define STRLENPADDED(a)  (STRLENS(a,0) STRLENS(a,1) STRLENS(a,2) STRLENS(a,3) STRLENS(a,4) STRLENS(a,5) STRLENS(a,6) STRLENS(a,7) STRLENS(a,8) STRLENS(a,9) -1) 
#define STRLEN(a)   STRLENPADDED((a "\0\0\0\0\0\0\0\0\0")) // padding required to prevent 'index out of range' issues. 

vĩ mô strlen này sẽ cung cấp cho bạn theo chiều dài của chuỗi ký tự mà bạn cung cấp, miễn là dài hơn 10 ký tự. Trong trường hợp của tôi điều này là đủ, nhưng trong trường hợp OPs macro có thể cần phải được mở rộng (rất nhiều). Vì nó là rất lặp đi lặp lại bạn có thể dễ dàng viết một kịch bản để tạo ra một vĩ mô chấp nhận 1000 ký tự.

PS: Đây chỉ là một nhánh đơn giản của vấn đề mà tôi đã thực sự cố gắng khắc phục, đây là một giá trị HASH được tính toán tĩnh cho một chuỗi nên tôi không cần sử dụng bất kỳ chuỗi nào trong hệ thống nhúng của mình. Trong trường hợp bất kỳ ai quan tâm (nó có thể đã cứu tôi một ngày tìm kiếm và giải quyết), điều này sẽ làm một mã hóa FNV trên một chuỗi nhỏ có thể được tối ưu hóa thành một nhiệm vụ duy nhất:

#ifdef _MSC_BUILD 
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5ULL 
#define HASH_TYPE    int 
#else // properly define for your own compiler to get rid of overflow warnings 
#define HASH_FNV_OFFSET_BASIS 0x811c9dc5UL 
#define HASH_TYPE    int 
#endif 
#define HASH_FNV_PRIME   16777619 
#define HASH0(a)    (a[0] ? ((HASH_TYPE)(HASH_FNV_OFFSET_BASIS * HASH_FNV_PRIME)^(HASH_TYPE)a[0]) : HASH_FNV_OFFSET_BASIS) 
#define HASH2(a,i,b)   ((b * (a[i] ? HASH_FNV_PRIME : 1))^(HASH_TYPE)(a[i] ? a[i] : 0)) 
#define HASHPADDED(a)   HASH2(a,9,HASH2(a,8,HASH2(a,7,HASH2(a,6,HASH2(a,5,HASH2(a,4,HASH2(a,3,HASH2(a,2,HASH2(a,1,HASH0(a)))))))))) 
#define HASH(a)     HASHPADDED((a "\0\0\0\0\0\0\0\0\0")) 
Các vấn đề liên quan