GCC पर विशेष जोर देने के साथ C (C C ++ नहीं) में संकलित समय स्थिर अभिसरण प्राप्त करने का सबसे अच्छा तरीका क्या है?
जवाबों:
C11 मानक _Static_assert
कीवर्ड जोड़ता है ।
यह gcc-4.6 के बाद से लागू किया गया है :
_Static_assert (0, "assert1"); /* { dg-error "static assertion failed: \"assert1\"" } */
पहले स्लॉट को एक अभिन्न स्थिर अभिव्यक्ति होने की आवश्यकता है। दूसरा स्लॉट एक निरंतर स्ट्रिंग शाब्दिक है जो लंबा ( _Static_assert(0, L"assertion of doom!")
) हो सकता है ।
मुझे ध्यान देना चाहिए कि यह हाल के संस्करणों में भी लागू किया गया है।
error: expected declaration specifiers or '...' before 'sizeof'
लाइन मिलती है static_assert( sizeof(int) == sizeof(long int), "Error!);
(मैं जिस तरह से C C C ++ का उपयोग नहीं कर रहा हूं)
_Static_assert( sizeof(int) == sizeof(long int), "Error!");
मेरे macine पर मुझे त्रुटि मिलती है।
error: expected declaration specifiers or '...' before 'sizeof'
और error: expected declaration specifiers or '...' before string constant
(वह "Error!"
स्ट्रिंग का उल्लेख कर रहा है) (यह भी: मैं -std = c11 के साथ संकलित कर रहा हूं। जब एक फ़ंक्शन के अंदर घोषणा डालते हैं तो सभी अच्छी तरह से काम करता है (विफल रहता है और उम्मीद के
_Static_assert
नहीं किया C ++ ish static_assert
। आपको static_assert मैक्रो प्राप्त करने के लिए `#include <assert.h> की आवश्यकता है।
यह फंक्शन और नॉन-फंक्शन स्कोप (लेकिन स्ट्रक्चर्स, यूनियनों के अंदर नहीं) में काम करता है।
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
STATIC_ASSERT(1,this_should_be_true);
int main()
{
STATIC_ASSERT(1,this_should_be_true);
}
यदि संकलन समय की पुष्टि का मिलान नहीं किया जा सकता है, तो जीसीसी द्वारा लगभग एक बुद्धिमान संदेश उत्पन्न होता है sas.c:4: error: size of array ‘static_assertion_this_should_be_true’ is negative
मैक्रो को टाइपडिफ के लिए एक अनूठा नाम उत्पन्न करने के लिए परिवर्तित किया जा सकता है (यानी नाम __LINE__
के अंत में संक्षिप्त static_assert_...
करें)
एक टर्नरी के बजाय, यह भी इस्तेमाल किया जा सकता है #define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[2*(!!(COND))-1]
जो जंग खाए पुराने cc65 (6502 cpu के लिए) कंपाइलर पर भी काम करता है।
अद्यतन:
पूर्णता के लिए, यहाँ संस्करण के साथ है__LINE__
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(!!(COND))*2-1]
// token pasting madness:
#define COMPILE_TIME_ASSERT3(X,L) STATIC_ASSERT(X,static_assertion_at_line_##L)
#define COMPILE_TIME_ASSERT2(X,L) COMPILE_TIME_ASSERT3(X,L)
#define COMPILE_TIME_ASSERT(X) COMPILE_TIME_ASSERT2(X,__LINE__)
COMPILE_TIME_ASSERT(sizeof(long)==8);
int main()
{
COMPILE_TIME_ASSERT(sizeof(int)==4);
}
UPDATE2: जीसीसी विशिष्ट कोड
जीसीसी 4.3 (मुझे लगता है) ने "त्रुटि" और "चेतावनी" फ़ंक्शन विशेषताओं को पेश किया। यदि उस विशेषता वाले किसी फ़ंक्शन को कॉल मृत कोड उन्मूलन (या अन्य उपायों) के माध्यम से समाप्त नहीं किया जा सकता है, तो एक त्रुटि या चेतावनी उत्पन्न होती है। इसका उपयोग उपयोगकर्ता परिभाषित विफलता विवरण के साथ संकलन समय जोर देने के लिए किया जा सकता है। यह निर्धारित करने के लिए रहता है कि डमी फ़ंक्शन का सहारा लिए बिना नामस्थान के दायरे में उनका उपयोग कैसे किया जा सकता है:
#define CTC(X) ({ extern int __attribute__((error("assertion failure: '" #X "' not true"))) compile_time_check(); ((X)?0:compile_time_check()),0; })
// never to be called.
static void my_constraints()
{
CTC(sizeof(long)==8);
CTC(sizeof(int)==4);
}
int main()
{
}
और यह इस तरह दिखता है:
$ gcc-mp-4.5 -m32 sas.c
sas.c: In function 'myc':
sas.c:7:1: error: call to 'compile_time_check' declared with attribute error: assertion failure: `sizeof(int)==4` not true
-Og
) अक्सर काम करने के लिए पर्याप्त हो सकता है, हालांकि, और डिबगिंग में हस्तक्षेप नहीं करना चाहिए। यदि कोई __OPTIMIZE__
(और __GNUC__
) परिभाषित नहीं है, तो कोई स्टैटिक ऐसर को एक नो-ऑप या रनटाइम एस्टर बनाने पर विचार कर सकता है।
__LINE__
संस्करण 4.1.1 में संस्करण के समान कुछ का उपयोग करता हूं ... कभी-कभी झुंझलाहट के साथ जब दो अलग-अलग हेडर एक ही संख्या रेखा पर एक होते हैं!
मुझे पता है कि इस प्रश्न का स्पष्ट रूप से उल्लेख किया गया है, लेकिन यहाँ पूर्णता के लिए Microsoft संकलक के लिए एक ट्वीक है।
नकारात्मक आकार के सरणी का उपयोग करते हुए टाइपडीफ एक सभ्य त्रुटि को थूकने के लिए सीएल को राजी नहीं करता है । यह सिर्फ कहता है error C2118: negative subscript
। एक शून्य-चौड़ाई बिटफील्ड इस संबंध में बेहतर किराया करता है। चूंकि इसमें एक संरचना टाइप करना शामिल है, हमें वास्तव में अद्वितीय प्रकार के नामों का उपयोग करने की आवश्यकता है। __LINE__
सरसों में कटौती नहीं करता है - COMPILE_TIME_ASSERT()
हेडर और स्रोत फ़ाइल में एक ही लाइन पर होना संभव है , और आपका संकलन टूट जाएगा। __COUNTER__
बचाव के लिए आता है (और यह 4.3 के बाद से जीसीसी में है)।
#define CTASTR2(pre,post) pre ## post
#define CTASTR(pre,post) CTASTR2(pre,post)
#define STATIC_ASSERT(cond,msg) \
typedef struct { int CTASTR(static_assertion_failed_,msg) : !!(cond); } \
CTASTR(static_assertion_failed_,__COUNTER__)
अभी
STATIC_ASSERT(sizeof(long)==7, use_another_compiler_luke)
अंडर cl
देता है:
C2149 त्रुटि: 'static_assertion_failed_use_another_compiler_luke': बिट फ़ील्ड का नाम शून्य चौड़ाई नहीं हो सकता
Gcc भी एक समझदार संदेश देता है:
त्रुटि: बिट-फ़ील्ड 'static_assertion_failed_use_another_compiler_luke' के लिए शून्य चौड़ाई
से विकिपीडिया :
#define COMPILE_TIME_ASSERT(pred) switch(0){case 0:case pred:;}
COMPILE_TIME_ASSERT( BOOLEAN CONDITION );
मैं समाधान का उपयोग करने की अनुशंसा नहीं करूंगा typedef
:
#define STATIC_ASSERT(COND,MSG) typedef char static_assertion_##MSG[(COND)?1:-1]
typedef
संकलन समय पर मूल्यांकन करने के लिए कीवर्ड के साथ सरणी घोषणा की गारंटी नहीं है। उदाहरण के लिए, ब्लॉक स्कोप में निम्न कोड संकलित होगा:
int invalid_value = 0;
STATIC_ASSERT(invalid_value, this_should_fail_at_compile_time_but_will_not);
मैं इसके बजाय (C99 पर) यह सिफारिश करूंगा:
#define STATIC_ASSERT(COND,MSG) static int static_assertion_##MSG[(COND)?1:-1]
की वजह से static
कीवर्ड, सरणी संकलन समय पर परिभाषित किया जाएगा। ध्यान दें कि यह अभिकर्ता केवल उसी काम करेगा COND
जिसके साथ संकलन समय पर मूल्यांकन किया जाता है। यह उन शर्तों के साथ काम नहीं करेगा (जैसे संकलन विफल हो जाएगा) स्मृति में मूल्यों पर आधारित स्थितियों के साथ, जैसे कि चर को दिए गए मान।
यदि STATIC_ASSERT () मैक्रो का उपयोग कर रहे हैं __LINE__
, तो यह संभव है कि एक .c फ़ाइल में प्रविष्टि और हेडर फ़ाइल में एक अलग प्रविष्टि के बीच लाइन नंबर क्लैश से बचना संभव हो __INCLUDE_LEVEL__
।
उदाहरण के लिए :
/* Trickery to create a unique variable name */
#define BOOST_JOIN( X, Y ) BOOST_DO_JOIN( X, Y )
#define BOOST_DO_JOIN( X, Y ) BOOST_DO_JOIN2( X, Y )
#define BOOST_DO_JOIN2( X, Y ) X##Y
#define STATIC_ASSERT(x) typedef char \
BOOST_JOIN( BOOST_JOIN(level_,__INCLUDE_LEVEL__), \
BOOST_JOIN(_assert_on_line_,__LINE__) ) [(x) ? 1 : -1]
क्लासिक तरीका एक सरणी का उपयोग कर रहा है:
char int_is_4_bytes_assertion[sizeof(int) == 4 ? 1 : -1];
यह काम करता है क्योंकि अगर यह दावा सही है कि सरणी का आकार 1 है और यह वैध है, लेकिन यदि यह गलत है तो -1 का आकार संकलन त्रुटि देता है।
अधिकांश संकलक चर का नाम दिखाएंगे और कोड के दाईं ओर इंगित करेंगे जहां आप दावे के बारे में अंतिम टिप्पणी छोड़ सकते हैं।
#define STATIC_ASSERT()
प्रकार के मैक्रो में लपेटना और आपके सामान्य उदाहरणों से अधिक सामान्य उदाहरण और नमूना संकलक आउटपुट STATIC_ASSERT()
प्रदान करना आपको बहुत अधिक उत्थान देगा और इस तकनीक को और अधिक समझ में आएगा।
पर्ल से, विशेष रूप से perl.h
लाइन 3455 ( <assert.h>
पहले से शामिल है):
/* STATIC_ASSERT_DECL/STATIC_ASSERT_STMT are like assert(), but for compile
time invariants. That is, their argument must be a constant expression that
can be verified by the compiler. This expression can contain anything that's
known to the compiler, e.g. #define constants, enums, or sizeof (...). If
the expression evaluates to 0, compilation fails.
Because they generate no runtime code (i.e. their use is "free"), they're
always active, even under non-DEBUGGING builds.
STATIC_ASSERT_DECL expands to a declaration and is suitable for use at
file scope (outside of any function).
STATIC_ASSERT_STMT expands to a statement and is suitable for use inside a
function.
*/
#if (defined(static_assert) || (defined(__cplusplus) && __cplusplus >= 201103L)) && (!defined(__IBMC__) || __IBMC__ >= 1210)
/* static_assert is a macro defined in <assert.h> in C11 or a compiler
builtin in C++11. But IBM XL C V11 does not support _Static_assert, no
matter what <assert.h> says.
*/
# define STATIC_ASSERT_DECL(COND) static_assert(COND, #COND)
#else
/* We use a bit-field instead of an array because gcc accepts
'typedef char x[n]' where n is not a compile-time constant.
We want to enforce constantness.
*/
# define STATIC_ASSERT_2(COND, SUFFIX) \
typedef struct { \
unsigned int _static_assertion_failed_##SUFFIX : (COND) ? 1 : -1; \
} _static_assertion_failed_##SUFFIX PERL_UNUSED_DECL
# define STATIC_ASSERT_1(COND, SUFFIX) STATIC_ASSERT_2(COND, SUFFIX)
# define STATIC_ASSERT_DECL(COND) STATIC_ASSERT_1(COND, __LINE__)
#endif
/* We need this wrapper even in C11 because 'case X: static_assert(...);' is an
error (static_assert is a declaration, and only statements can have labels).
*/
#define STATIC_ASSERT_STMT(COND) STMT_START { STATIC_ASSERT_DECL(COND); } STMT_END
यदि static_assert
उपलब्ध (से <assert.h>
) है, तो इसका उपयोग किया जाता है। अन्यथा, यदि स्थिति झूठी है, तो नकारात्मक आकार के साथ एक बिट-फ़ील्ड घोषित किया जाता है, जो संकलन विफल होने का कारण बनता है।
STMT_START
/ STMT_END
विस्तार मैक्रो नहीं है do
/ while (0)
क्रमश।
_Static_assert()
अब C के सभी संस्करणों के लिए gcc में परिभाषित किया गया है, और static_assert()
C ++ 11 और बाद में परिभाषित किया गया हैSTATIC_ASSERT()
इसलिए निम्न सरल मैक्रो निम्न में काम करता है:g++ -std=c++11
) या बाद काgcc -std=c90
gcc -std=c99
gcc -std=c11
gcc
(कोई std निर्दिष्ट नहीं)STATIC_ASSERT
निम्नानुसार परिभाषित करें :
/* For C++: */
#ifdef __cplusplus
#ifndef _Static_assert
#define _Static_assert static_assert /* `static_assert` is part of C++11 or later */
#endif
#endif
/* Now for gcc (C) (and C++, given the define above): */
#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed")
अब इसका उपयोग करें:
STATIC_ASSERT(1 > 2); // Output will look like: error: static assertion failed: "(1 > 2) failed"
Gcc 4.8.4 का उपयोग करके उबंटू में परीक्षण किया गया:
उदाहरण 1: अच्छा gcc
आउटपुट (यानी: STATIC_ASSERT()
कोड काम करता है, लेकिन स्थिति झूठी थी, जिससे संकलन-समय जोर पड़ता है):
$ gcc -Wall -o-static_assert static_assert.c &&//atic_assert
static_assert.c: फ़ंक्शन में 'main'
static_assert.c: 78: 38: त्रुटि: स्टेटिक असेसमेंट विफल: "(1> 2) विफल"
#define STATIC_ASSERT (test_for_true) ) _Static_assert ((test_for_true), "(" #test_for_true ") विफल")
^
static_assert.c: 88: 5: नोट: मैक्रो के विस्तार में 'STATIC_ASSERT "
STATIC_ASSERT (1> 2);
^
उदाहरण 2: अच्छा g++ -std=c++11
आउटपुट (यानी: STATIC_ASSERT()
कोड काम करता है, लेकिन स्थिति झूठी थी, जिससे संकलन-समय जोर पड़ता है):
$ g ++ -Wall -std = c ++ 11 -o static_assert static_assert.c &&//aticatic_assert
static_assert.c: फ़ंक्शन में 'int main ()'
static_assert.c: 74: 32: त्रुटि: static assertion विफल: (1> 2) विफल
#define _Static_assert static_assert / *static_assert
C ++ 11 का हिस्सा है या बाद में * /
^
static_assert.c: 78: 38: ध्यान दें: मैक्रो के विस्तार में '_Static_assert'
#deineine STATIC_ASSERT (test_for_true) _Static_assert (test_tr_ueert)। "(" #test_for_true ") विफल")
^
static_assert.c: 88: 5: नोट: मैक्रो 'STATIC_ASSERT'
STATIC_ASSERT (1> 2) के विस्तार में;
^
उदाहरण 3: असफल C ++ आउटपुट (यानी: एस्टर कोड ठीक से काम नहीं करता है, क्योंकि यह C ++ 11 से पहले C ++ के संस्करण का उपयोग कर रहा है ):
$ g ++ -Wall -oall_assert static_assert.c &&/static_assert
static_assert.c: 88: 5: 5: चेतावनी: पहचानकर्ता 'static_assert' C ++ 11 [-WL ++ +
x- कॉमर्स ] STATIC_ASSERT (1> 2 ) में एक कीवर्ड है );
^
static_assert.c: फ़ंक्शन में 'int main ()'
static_assert.c: 78: 99: त्रुटि: 'static_assert' को इस दायरे में घोषित नहीं किया गया था
# STATIC_ASSERT (test_for_true )_Static_assert ((test_for_true), "(#test_forue) ) विफल ")
^
static_assert.c: 88: 5: ध्यान दें: मैक्रो 'STATIC_ASSERT'
STATIC_ASSERT (1> 2) के विस्तार में;
^
/*
static_assert.c
- test static asserts in C and C++ using gcc compiler
Gabriel Staples
4 Mar. 2019
To be posted in:
1. /programming/987684/does-gcc-have-a-built-in-compile-time-assert/987756#987756
2. /programming/3385515/static-assert-in-c/7287341#7287341
To compile & run:
C:
gcc -Wall -o static_assert static_assert.c && ./static_assert
gcc -Wall -std=c90 -o static_assert static_assert.c && ./static_assert
gcc -Wall -std=c99 -o static_assert static_assert.c && ./static_assert
gcc -Wall -std=c11 -o static_assert static_assert.c && ./static_assert
C++:
g++ -Wall -o static_assert static_assert.c && ./static_assert
g++ -Wall -std=c++98 -o static_assert static_assert.c && ./static_assert
g++ -Wall -std=c++03 -o static_assert static_assert.c && ./static_assert
g++ -Wall -std=c++11 -o static_assert static_assert.c && ./static_assert
-------------
TEST RESULTS:
-------------
1. `_Static_assert(false, "1. that was false");` works in:
C:
gcc -Wall -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c90 -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c99 -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c11 -o static_assert static_assert.c && ./static_assert YES
C++:
g++ -Wall -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++98 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++03 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++11 -o static_assert static_assert.c && ./static_assert NO
2. `static_assert(false, "2. that was false");` works in:
C:
gcc -Wall -o static_assert static_assert.c && ./static_assert NO
gcc -Wall -std=c90 -o static_assert static_assert.c && ./static_assert NO
gcc -Wall -std=c99 -o static_assert static_assert.c && ./static_assert NO
gcc -Wall -std=c11 -o static_assert static_assert.c && ./static_assert NO
C++:
g++ -Wall -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++98 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++03 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++11 -o static_assert static_assert.c && ./static_assert YES
3. `STATIC_ASSERT(1 > 2);` works in:
C:
gcc -Wall -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c90 -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c99 -o static_assert static_assert.c && ./static_assert YES
gcc -Wall -std=c11 -o static_assert static_assert.c && ./static_assert YES
C++:
g++ -Wall -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++98 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++03 -o static_assert static_assert.c && ./static_assert NO
g++ -Wall -std=c++11 -o static_assert static_assert.c && ./static_assert YES
*/
#include <stdio.h>
#include <stdbool.h>
/* For C++: */
#ifdef __cplusplus
#ifndef _Static_assert
#define _Static_assert static_assert /* `static_assert` is part of C++11 or later */
#endif
#endif
/* Now for gcc (C) (and C++, given the define above): */
#define STATIC_ASSERT(test_for_true) _Static_assert((test_for_true), "(" #test_for_true ") failed")
int main(void)
{
printf("Hello World\n");
/*_Static_assert(false, "1. that was false");*/
/*static_assert(false, "2. that was false");*/
STATIC_ASSERT(1 > 2);
return 0;
}
static_assert
मैक्रो इन है तो इतना जटिल क्यों assert.h
?
static_assert()
सी। में बिल्कुल भी उपलब्ध नहीं है। यहां भी देखें: en.cppreference.com/w/cpp/language/static_assert --it शो static_assert
"(C ++ 11 के बाद से)" मौजूद है। मेरे उत्तर की सुंदरता यह है कि यह gcc के C90 और बाद में, साथ ही किसी भी C ++ 11 और बाद में, C ++ 11 के बजाय और बाद में, जैसे काम करता है static_assert()
। इसके अलावा, मेरे जवाब के बारे में क्या जटिल है? यह केवल एक युगल है #define
।
static_assert
C11 से C में परिभाषित किया गया है। यह एक मैक्रो है जो फैलता है _Static_assert
। en.cppreference.com/w/c/error/static_assert । इसके अतिरिक्त और आपके उत्तर के विपरीत _Static_assert
g99 में c99 और c90 में उपलब्ध नहीं है (केवल gnu99 और gnu90 में)। यह मानक के अनुरूप है। मूल रूप से आप बहुत सारे अतिरिक्त काम करते हैं, केवल तभी लाभ होता है जब g9090 और gnu99 के साथ संकलित किया जाता है और जो वास्तविक usecase को तुच्छ रूप से छोटा कर देता है।
आप में से कुछ वास्तव में बुनियादी और पोर्टेबल चाहते हैं, लेकिन C ++ 11 सुविधाओं के लिए उपयोग नहीं है, मैं सिर्फ बात लिखी है। सामान्य रूप से
उपयोग करें STATIC_ASSERT
(यदि आप चाहें तो इसे एक ही फ़ंक्शन में दो बार लिख सकते हैं) और GLOBAL_STATIC_ASSERT
पहले पैरामीटर के रूप में एक अद्वितीय वाक्यांश के साथ फ़ंक्शन के बाहर का उपयोग करें ।
#if defined(static_assert)
# define STATIC_ASSERT static_assert
# define GLOBAL_STATIC_ASSERT(a, b, c) static_assert(b, c)
#else
# define STATIC_ASSERT(pred, explanation); {char assert[1/(pred)];(void)assert;}
# define GLOBAL_STATIC_ASSERT(unique, pred, explanation); namespace ASSERTATION {char unique[1/(pred)];}
#endif
GLOBAL_STATIC_ASSERT(first, 1, "Hi");
GLOBAL_STATIC_ASSERT(second, 1, "Hi");
int main(int c, char** v) {
(void)c; (void)v;
STATIC_ASSERT(1 > 0, "yo");
STATIC_ASSERT(1 > 0, "yo");
// STATIC_ASSERT(1 > 2, "yo"); //would compile until you uncomment this one
return 0;
}
स्पष्टीकरण:
पहले यह जांचता है कि क्या आपके पास असली मुखर है, जिसे आप निश्चित रूप से उपलब्ध होने पर उपयोग करना चाहते हैं।
यदि आप इसे अपने pred
आइकॉन से प्राप्त नहीं करते हैं , और इसे अपने आप से विभाजित करते हैं। यह दो काम करता है।
यदि यह शून्य, आईडी एस्ट है, अभिकथन विफल हो गया है, तो यह शून्य त्रुटि से विभाजन का कारण होगा (अंकगणित मजबूर है क्योंकि यह एक सरणी घोषित करने की कोशिश कर रहा है)।
यदि यह शून्य नहीं है, तो यह सरणी आकार को सामान्य कर देता है 1
। इसलिए यदि दावा पारित हो गया, तो आप इसे वैसे भी विफल नहीं करना चाहेंगे, क्योंकि आपके विधेय का मूल्यांकन -1
(अमान्य), या 232442
(बड़े पैमाने पर अंतरिक्ष की बर्बादी, आईडीके अगर इसे बाहर अनुकूलित किया जाएगा)।
इसके लिए STATIC_ASSERT
इसे ब्रेसिज़ में लपेटा जाता है, यह इसे एक ब्लॉक बनाता है, जो चर को मापता हैassert
, मतलब आप इसे कई बार लिख सकते हैं।
यह इसे भी डाल देता है void
, जो कि छुटकारा पाने का एक ज्ञात तरीका हैunused variable
चेतावनी।
के लिए GLOBAL_STATIC_ASSERT
, बजाय एक कोड ब्लॉक में होने का, यह एक नाम स्थान उत्पन्न करता है। कार्यों के बाहर नाम स्थान की अनुमति है। unique
यदि आप इसे एक से अधिक बार उपयोग करते हैं, तो किसी भी परस्पर विरोधी परिभाषा को रोकने के लिए एक पहचानकर्ता की आवश्यकता होती है।
मेरे लिए GCC और VS'12 C ++ पर काम किया
यह "हटाए गए अप्रयुक्त" विकल्प सेट के साथ काम करता है। मैं वैश्विक मापदंडों की जांच करने के लिए एक वैश्विक फ़ंक्शन का उपयोग कर सकता हूं।
//
#ifndef __sassert_h__
#define __sassert_h__
#define _cat(x, y) x##y
#define _sassert(exp, ln) \
extern void _cat(ASSERT_WARNING_, ln)(void); \
if(!(exp)) \
{ \
_cat(ASSERT_WARNING_, ln)(); \
}
#define sassert(exp) _sassert(exp, __LINE__)
#endif //__sassert_h__
//-----------------------------------------
static bool tab_req_set_relay(char *p_packet)
{
sassert(TXB_TX_PKT_SIZE < 3000000);
sassert(TXB_TX_PKT_SIZE >= 3000000);
...
}
//-----------------------------------------
Building target: ntank_app.elf
Invoking: Cross ARM C Linker
arm-none-eabi-gcc ...
../Sources/host_if/tab_if.c:637: undefined reference to `ASSERT_WARNING_637'
collect2: error: ld returned 1 exit status
make: *** [ntank_app.elf] Error 1
//
इसने कुछ पुराने gcc के लिए काम किया। क्षमा करें कि मैं भूल गया कि वह कौन सा संस्करण था:
#define _cat(x, y) x##y
#define _sassert(exp, ln)\
extern char _cat(SASSERT_, ln)[1]; \
extern char _cat(SASSERT_, ln)[exp ? 1 : 2]
#define sassert(exp) _sassert((exp), __LINE__)
//
sassert(1 == 2);
//
#148 declaration is incompatible with "char SASSERT_134[1]" (declared at line 134) main.c /test/source/controller line 134 C/C++ Problem
_Static_assert
C11 मानक का हिस्सा है और कोई भी संकलक जो C11 का समर्थन करता है, उसके पास होगा।