468,457 Members | 1,603 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,457 developers. It's quick & easy.

max strlen at compile time?



Hi,

can I use the preprocessor, using sizeof(a)/sizeof(a[0]) to yield an
error for too long strings?

Like:

#define CRYPT(a) \
#if sizeof(a)/sizeof(a[0]) 31 \
xCRYPT(a) \
#else\
#error xy\
#endif

(which of course doe not work)
--
-Gernot
int main(int argc, char** argv) {printf
("%silto%c%cf%cgl%ssic%ccom%c", "ma", 58, 'g', 64, "ba", 46, 10);}

________________________________________
Looking for a good game? Do it yourself!
GLBasic - you can do
www.GLBasic.com
Aug 1 '06 #1
14 4040
Gernot Frisch said:
>

Hi,

can I use the preprocessor, using sizeof(a)/sizeof(a[0]) to yield an
error for too long strings?
No, the preprocessor doesn't resolve uses of sizeof - that's done by the
compiler later on.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Aug 1 '06 #2
In article <jK******************************@bt.com>,
Richard Heathfield <in*****@invalid.invalidwrote:
>can I use the preprocessor, using sizeof(a)/sizeof(a[0]) to yield an
error for too long strings?
>No, the preprocessor doesn't resolve uses of sizeof - that's done by the
compiler later on.
However, sizeof does produce a constant value, and there have been
tricks posted here in the past to detect errors of this kind at
compile time.

-- Richard
Aug 1 '06 #3
Richard Tobin said:
In article <jK******************************@bt.com>,
Richard Heathfield <in*****@invalid.invalidwrote:
>>can I use the preprocessor, using sizeof(a)/sizeof(a[0]) to yield an
error for too long strings?
>>No, the preprocessor doesn't resolve uses of sizeof - that's done by the
compiler later on.

However, sizeof does produce a constant value, and there have been
tricks posted here in the past to detect errors of this kind at
compile time.
Yes, but he specifically asked about the preprocessor. (Yeah, I know, the
subject line says "compile time"...)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Aug 1 '06 #4

"Richard Heathfield" <in*****@invalid.invalidschrieb im Newsbeitrag
news:Bd********************@bt.com...
Richard Tobin said:
>In article <jK******************************@bt.com>,
Richard Heathfield <in*****@invalid.invalidwrote:
>>>can I use the preprocessor, using sizeof(a)/sizeof(a[0]) to yield
an
error for too long strings?
>>>No, the preprocessor doesn't resolve uses of sizeof - that's done
by the
compiler later on.

However, sizeof does produce a constant value, and there have been
tricks posted here in the past to detect errors of this kind at
compile time.

Yes, but he specifically asked about the preprocessor. (Yeah, I
know, the
subject line says "compile time"...)
Very nice. So - can somone please show me how to check for max
stringlength at _compile time_?
Aug 2 '06 #5
Gernot Frisch said:
>
"Richard Heathfield" <in*****@invalid.invalidschrieb im Newsbeitrag
news:Bd********************@bt.com...
<snip>
>>
Yes, but he specifically asked about the preprocessor. [...]

Very nice. So - can somone please show me how to check for max
stringlength at _compile time_?
Oh, okay. Let's take your original example:

#define CRYPT(a) \
#if sizeof(a)/sizeof(a[0]) 31 \
xCRYPT(a) \
#else\
#error xy\
#endif

Now let me just hack that to give a useful name that doesn't look silly when
quoted in ordinary text:

#define CRYPT(Array) \
#if sizeof(Array)/sizeof(Array[0]) 31 \
xCRYPT(Array) \
#else\
#error xy\
#endif

What we want, then, is a compile-time error if the size of Array exceeds 31.
Here's how:

char Array[SUSPECT_LENGTH] = {0};
char Error_ArrayIsTooLong[((sizeof Array / sizeof Array[0] <= OKAY_LENGTH) *
2) - 1] = {0};

With OKAY_LENGTH set at 31 and SUSPECT_LENGTH at 31, I get:

gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-Wno-conversion -ffloat-store -O2 -g -pg -c -o foo.o foo.c
foo.c: In function `main':
foo.c:9: warning: unused variable `Error_ArrayIsTooLong'

With OKAY_LENGTH set at 31 and SUSPECT_LENGTH at 32, I get:

gcc -W -Wall -ansi -pedantic -Wformat-nonliteral -Wcast-align
-Wpointer-arith -Wbad-function-cast -Wmissing-prototypes
-Wstrict-prototypes -Wmissing-declarations -Winline -Wundef
-Wnested-externs -Wcast-qual -Wshadow -Wconversion -Wwrite-strings
-Wno-conversion -ffloat-store -O2 -g -pg -c -o foo.o foo.c
foo.c: In function `main':
foo.c:9: size of array `Error_ArrayIsTooLong' is negative
foo.c:9: warning: unused variable `Error_ArrayIsTooLong'
make: *** [foo.o] Error 1

QED.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)
Aug 2 '06 #6
What we want, then, is a compile-time error if the size of Array
exceeds 31.
Here's how:

char Array[SUSPECT_LENGTH] = {0};
char Error_ArrayIsTooLong[((sizeof Array / sizeof Array[0] <=
OKAY_LENGTH) *
2) - 1] = {0};
foo.c: In function `main':
foo.c:9: size of array `Error_ArrayIsTooLong' is negative
foo.c:9: warning: unused variable `Error_ArrayIsTooLong'

Very clever! Thank you.
Aug 2 '06 #7
Richard Heathfield writes:
What we want, then, is a compile-time error if the size of Array
exceeds 31. Here's how:

char Array[SUSPECT_LENGTH] = {0};
char Error_ArrayIsTooLong[((sizeof Array / sizeof Array[0] <= OKAY_LENGTH) *
2) - 1] = {0};
A lot of compilers are lax about error checking in one way or another -
I think I've seen one which converted that negative size to unsigned,
for example. So I prefer to violate two constraints, just in case:

#define CHECK_CONSTRAINT(name, test) \
typedef struct { \
int constraint_##name: (test) ? 1 : -999; \
} constraint_##name[(test) ? 1 : -999]

CHECK_CONSTRAINT(Array_size, sizeof Array/sizeof Array[0] <= OKAY_LENGTH)

--
Hallvard
Aug 2 '06 #8

"Hallvard B Furuseth" <h.**********@usit.uio.noschrieb im
Newsbeitrag news:hb**************@bombur.uio.no...
Richard Heathfield writes:
>What we want, then, is a compile-time error if the size of Array
exceeds 31. Here's how:

char Array[SUSPECT_LENGTH] = {0};
char Error_ArrayIsTooLong[((sizeof Array / sizeof Array[0] <=
OKAY_LENGTH) *
2) - 1] = {0};

A lot of compilers are lax about error checking in one way or
another -
I think I've seen one which converted that negative size to
unsigned,
for example. So I prefer to violate two constraints, just in case:

#define CHECK_CONSTRAINT(name, test) \
typedef struct { \
int constraint_##name: (test) ? 1 : -999; \
} constraint_##name[(test) ? 1 : -999]

CHECK_CONSTRAINT(Array_size, sizeof Array/sizeof Array[0] <=
OKAY_LENGTH)
how about this:

{
const char err_str_too_long[
(sizeof(str)/sizeof(str[0]) <= 32)+1
] ={0,0};
}

which makes an [1] or a [2], and yields an error:
error C2078: too many initializers

which is quite informative, I think...

Is it x-compiler compatible?
Aug 2 '06 #9
Gernot Frisch writes:
>"Hallvard B Furuseth" <h.**********@usit.uio.noschrieb im
>>Richard Heathfield writes:
>>What we want, then, is a compile-time error if the size of Array
exceeds 31. Here's how:
(...)

how about this:

{
const char err_str_too_long[
(sizeof(str)/sizeof(str[0]) <= 32)+1
] ={0,0};
}

which makes an [1] or a [2], and yields an error:
error C2078: too many initializers

which is quite informative, I think...
Heh. Quite fitting for that particular error. gcc only gives a warning
about it though. Compilation only fails if you use gcc -pedantic-errors.
Hmm. I'll suggest to change that and see what they say. It's not a bug
do behave like that, just unexpected.

One matter I didn't notice at first is that your and Richard's variants
generate data, while mine doesn't (it just makes a typedef).

--
Hallvard
Aug 2 '06 #10
Gernot Frisch wrote:
>>What we want, then, is a compile-time error if the size of Array
exceeds 31.
Here's how:

char Array[SUSPECT_LENGTH] = {0};
char Error_ArrayIsTooLong[((sizeof Array / sizeof Array[0] <=
OKAY_LENGTH) *
2) - 1] = {0};

>>foo.c: In function `main':
foo.c:9: size of array `Error_ArrayIsTooLong' is negative
foo.c:9: warning: unused variable `Error_ArrayIsTooLong'

Very clever! Thank you.
Your problem can be generalized to "how to program an elegant and robust
static assert" (compile time assert). Here is what I use (open to any
improvement):

#define cos_STATIC_ASSERT(cond) \
struct cos_PP_CAT(STATIC_ASSERT_,__LINE__) { \
enum { cos_PP_CAT(STATIC_ASSERT_,__LINE__) = !(cond) } _; \
int STATIC_ASSERT[(cond) ? 1 : -1]; \
}

where

#define cos_PP_CAT( a,b) cos_PP_CAT_(a,b)
#define cos_PP_CAT_(a,b) a##b

This should give a meaningfull error message with most compilers.
The enum is there to forbid the use of sizeof at runtime (c99) and to
ensure consistent behavior between c89 and c99.

a+, ld.
Aug 2 '06 #11
One matter I didn't notice at first is that your and Richard's
variants
generate data, while mine doesn't (it just makes a typedef).
That's a point!
Aug 3 '06 #12
Laurent Deniau posted:
int STATIC_ASSERT[(cond) ? 1 : -1];

Would you not prefer a simple typedef?

(COMPASS = Compile-time assert)

Something like:

typedef COMPASS(expr) char[(expr) ? 2 : -2 ];

--

Frederick Gotham
Aug 3 '06 #13
Frederick Gotham <fg*******@SPAM.comwrites:
Laurent Deniau posted:
> int STATIC_ASSERT[(cond) ? 1 : -1];


Would you not prefer a simple typedef?

(COMPASS = Compile-time assert)

Something like:

typedef COMPASS(expr) char[(expr) ? 2 : -2 ];
verify.h from gnulib is a refined version of the idea of a
compile-time assert. I won't post it here, because it's about
150 lines long (mostly comments), but I'd recommend taking a look
at on the web:
http://cvs.savannah.gnu.org/viewcvs/...in&root=gnulib

I found it very educational.
--
"The way I see it, an intelligent person who disagrees with me is
probably the most important person I'll interact with on any given
day."
--Billy Chambless
Aug 3 '06 #14
Frederick Gotham wrote:
Laurent Deniau posted:

> int STATIC_ASSERT[(cond) ? 1 : -1];

Would you not prefer a simple typedef?
why?
(COMPASS = Compile-time assert)

Something like:

typedef COMPASS(expr) char[(expr) ? 2 : -2 ];
This may not detect some problems at compile time but at runtime in c99.

a+, ld.

Aug 4 '06 #15

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

45 posts views Thread by Matt Parkins | last post: by
12 posts views Thread by Nollie | last post: by
21 posts views Thread by sugaray | last post: by
33 posts views Thread by apropo | last post: by
66 posts views Thread by roy | last post: by
7 posts views Thread by Duke | last post: by
53 posts views Thread by a\\/b | last post: by
11 posts views Thread by Bill Cunningham | last post: by
reply views Thread by NPC403 | last post: by
1 post views Thread by subhajit12345 | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.