F
Francois Grieu
In C99:
6.7.5.2p1: "... the expression shall have an integer type. If the
expression is a constant expression, it shall have a value greater than
zero."
6.7.5.2p2: "... If an identifier is declared to be an object with static
storage duration, it shall not have a variable length array type."
6.7.5.2p4: "... If the size is an integer constant expression and the
element type has a known constant size, the array type is not a variable
length array type; otherwise, the array type is a variable length array
type."
6.7.5.2p5: "If the size is an expression that is not an integer constant
expression expression: if it occurs in a declaration at function
prototype scope, it is treated as if it were replaced by *; otherwise,
each time it is evaluated it shall have a value greater than zero."
Yes; also relevant is 6.6p6
An integer constant expression (.. used to specify .. the size of an
array ..) shall have integer type and shall only have operands
that are integer constants, enumeration constants, character
constants, sizeof expressions whose results are integer constants,
and floating constants that are the immediate operands of casts.
Cast operators in an integer constant expression shall only
convert arithmetic types to integer types, except as part of an
operand to the sizeof operator.
I read that as C99 NOT allowing (except in automatic context, as a
VLA) even basic use of floating point as in
struct foo * bar[(unsigned)(1000*2.718)];
Whether or not that's permitted depends upon precisely what you mean
by that phrase - it's not clear from context.
I was hoping for (not tested)
// select temporary type
#include <limits.h>
#ifdef ULLONG_MAX
#define UTMP static const unsigned long long
#else
#define UTMP static const unsigned long
#endif
#define EXPECTED 15000
UTMP kExpected = EXPECTED;
UTMP kRoot2 = 12*12*Expected;
// we want ceil(sqrt(12*12*Expected)), use Newton/Rapson
UTMP kExTmp0 = (uwl)3<<(kRoot2>>30 > 0 ? 15 :
kRoot2>>24 > 0 ? 12 :
kRoot2>>18 > 0 ? 9 :
kRoot2>>12 > 0 ? 6 : 3);
UTMP kExTmp1 = (kExTmp0+kRoot2/kExTmp0)/2;
UTMP kExTmp2 = (kExTmp1+kRoot2/kExTmp1)/2;
UTMP kExTmp3 = (kExTmp2+kRoot2/kExTmp2)/2;
UTMP kExTmp4 = (kExTmp3+kRoot2/kExTmp3)/2;
UTMP kExTmp5 = (kExTmp4+kRoot2/kExTmp4)/2;
UTMP kExTmp6 = (kExTmp5+kRoot2/kExTmp5)/2;
UTMP kExTmp7 = (kExTmp6+kRoot2/kExTmp6)/2;
UTMP kExTmp8 = (kExTmp7+kRoot2/kExTmp7)/2;
UTMP kExTmp9 = (kExTmp8+kRoot2/kExTmp8)/2;
UTMP kExTmpA = (kExTmp9+kRoot2/kExTmp9)/2;
UTMP kExTmpB = (kExTmpA+kRoot2/kExTmpA)/2;
UTMP kExTmpC = (kExTmpB+kRoot2/kExTmpB)/2;
UTMP kRoot = kExTmpC+(kExTmpB>kExTmpC?1:0);
struct foo * bar[kExpected+kRoot];
Is that valid in C11?
Francois Grieu