435,131 Members | 1,728 Online + Ask a Question
Need help? Post your question and get tips & solutions from a community of 435,131 IT Pros & Developers. It's quick & easy.

Trap representations for unsigned integers

 P: n/a If uMyInt_t is an unsigned integral type, is the following a necessary and sufficient condition that uMyInt_t has no trap representation? (uMyInt_t)(-1) >CHAR_BIT*sizeof(uMyInt_t)-1 That is, I'm asking wheter it equals 0 whenever uMyInt_t has trap representations, equals a nonzero value whenever uMyInt_t has no trap representation, and never triggers undefined behaviour. -- #include char s[]="\16Jsa ukenethr ,cto haCr\n";int main(void){*s*=5;* s%=23;putchar(s[s]);return*s-14?main():!putchar(9[s+*s]);} Apr 21 '07 #1
17 Replies

 P: n/a Army1987 wrote: If uMyInt_t is an unsigned integral type, is the following a necessary and sufficient condition that uMyInt_t has no trap representation? (uMyInt_t)(-1) >CHAR_BIT*sizeof(uMyInt_t)-1 No. If uMyInt_t has padding bits, you will right-shift by a number greater than (or equal to) the number of value bits, and for that the behaviour is undefined. Apr 21 '07 #2

 P: n/a Army1987 wrote: If uMyInt_t is an unsigned integral type, is the following a necessary and sufficient condition that uMyInt_t has no trap representation? (uMyInt_t)(-1) >CHAR_BIT*sizeof(uMyInt_t)-1 That is, I'm asking wheter it equals 0 whenever uMyInt_t has trap representations, equals a nonzero value whenever uMyInt_t has no trap representation, and never triggers undefined behaviour. I think there are at least two problems with this test. First, if uMyInt_t has padding bits the shift count may be too large and lead to undefined behavior ("may" because of possible promotion to int or unsigned int). Second, the presence of padding bits does not imply the existence of trap representations: the extra bits may just be along for the ride. The best way to detect padding bits may be to count the number of 1's in (uMyInt_t)-1, or to compare the numeric value of (uMyInt_t)-1 to the "expected" quantity. The first test is easy at run time but difficult or impossible at preprocessing time; the second has problems, too (what type should you use to form the expected value?). I can think of no reliable way to determine whether trap representations exist; if you find there are no padding bits you can deduce that there are no traps, but that's as far as I think you can get. -- Eric Sosman es*****@acm-dot-org.invalid Apr 21 '07 #3

 P: n/a "Harald van D?k" If uMyInt_t is an unsigned integral type, is the following anecessary and sufficient condition that uMyInt_t has no traprepresentation?(uMyInt_t)(-1) >CHAR_BIT*sizeof(uMyInt_t)-1 No. If uMyInt_t has padding bits, you will right-shift by a number greater than (or equal to) the number of value bits, and for that the behaviour is undefined. Is ( DBL_MAX >= (uMyInt_t)(-1) || (puts("Your DS9K is about to self-\ destruct. Get a real computer."), exit(1)), /* On the DeathStation 9000 exit(1) activates self-destruction */ ceil(log2((uMyInt_t)(-1))) >= CHAR_BIT*sizeof(uMyInt_t) ) any better? Apr 21 '07 #4

 P: n/a Army1987 wrote: "Harald van D?k" CHAR_BIT*sizeof(uMyInt_t)-1 No. If uMyInt_t has padding bits, you will right-shift by a number greater than (or equal to) the number of value bits, and for that the behaviour is undefined. Is ( DBL_MAX >= (uMyInt_t)(-1) || (puts("Your DS9K is about to self-\ destruct. Get a real computer."), exit(1)), /* On the DeathStation 9000 exit(1) activates self-destruction */ ceil(log2((uMyInt_t)(-1))) >= CHAR_BIT*sizeof(uMyInt_t) ) any better? On the DS9K, DBL_MAX would be large enough, but CHAR_BIT * sizeof(uMuInt_t) would give the wrong result because SIZE_MAX is too small. :) Seriously though, your current expression is already no longer an integer constant expression, so at this point there's no downside to just writing a function. Apr 21 '07 #5

 P: n/a "Eric Sosman" If uMyInt_t is an unsigned integral type, is the following anecessary and sufficient condition that uMyInt_t has no traprepresentation?(uMyInt_t)(-1) >CHAR_BIT*sizeof(uMyInt_t)-1That is, I'm asking wheter it equals 0 whenever uMyInt_t has traprepresentations, equals a nonzero value whenever uMyInt_t has notrap representation, and never triggers undefined behaviour. [snip] Second, the presence of padding bits does not imply the existence of trap representations: the extra bits may just be along for the ride. So I'll replace "necessary and sufficient condition" with "sufficient condition". What I was thinking of is something like: #include unsigned char randchar(); /* Get a random integer from 0 to UCHAR_MAX */ unsigned long longrand() { unsigned long result; if (NO_TRAP(unsigned long)) { int i; unsigned char res[sizeof result]; for (i=0; i

 P: n/a "Harald van D?k" Is( DBL_MAX >= (uMyInt_t)(-1) || (puts("Your DS9K is about to self-\destruct. Get a real computer."), exit(1)),/* On the DeathStation 9000 exit(1) activates self-destruction */ceil(log2((uMyInt_t)(-1))) >= CHAR_BIT*sizeof(uMyInt_t) )any better? On the DS9K, DBL_MAX would be large enough, but CHAR_BIT * sizeof(uMuInt_t) would give the wrong result because SIZE_MAX is too small. :) On C99 I might use (uintmax_t)CHAR_BIT*sizeof(uMyInt_t)... Seriously though, your current expression is already no longer an integer constant expression, so at this point there's no downside to just writing a function. I was thinking of using a macro, so I could write NO_PADDING(size_t), NO_PADDING(unsigned int), etc. There's no way to do that with a function. Apr 21 '07 #7

 P: n/a Army1987 wrote: "Eric Sosman" CHAR_BIT*sizeof(uMyInt_t)-1 That is, I'm asking wheter it equals 0 whenever uMyInt_t has trap representations, equals a nonzero value whenever uMyInt_t has no trap representation, and never triggers undefined behaviour. [snip] Second, the presence of padding bits does not imply the existence of trap representations: the extra bits may just be along for the ride. So I'll replace "necessary and sufficient condition" with "sufficient condition". What I was thinking of is something like: #include unsigned char randchar(); /* Get a random integer from 0 to UCHAR_MAX */ unsigned long longrand() { unsigned long result; if (NO_TRAP(unsigned long)) { int i; unsigned char res[sizeof result]; for (i=0; i

 P: n/a Army1987 wrote: "Harald van D?k" = (uMyInt_t)(-1) || (puts("Your DS9K is about to self-\ destruct. Get a real computer."), exit(1)), /* On the DeathStation 9000 exit(1) activates self-destruction */ ceil(log2((uMyInt_t)(-1))) >= CHAR_BIT*sizeof(uMyInt_t) ) any better? On the DS9K, DBL_MAX would be large enough, but CHAR_BIT * sizeof(uMuInt_t) would give the wrong result because SIZE_MAX is too small. :) On C99 I might use (uintmax_t)CHAR_BIT*sizeof(uMyInt_t)... And on C90, you can use a cast to unsigned long. Seriously though, your current expression is already no longer an integer constant expression, so at this point there's no downside to just writing a function. I was thinking of using a macro, so I could write NO_PADDING(size_t), NO_PADDING(unsigned int), etc. There's no way to do that with a function. You could do #define NO_PADDING(type) (count_bits((type) -1) == sizeof(type)) where count_bits accepts an unsigned long / uintmax_t. Apr 21 '07 #9

 P: n/a Harald van DÄ³k wrote: You could do #define NO_PADDING(type) (count_bits((type) -1) == sizeof(type)) .... == sizeof(type) * CHAR_BIT Apr 21 '07 #10

 P: n/a "Harald van D?k"

 P: n/a Harald van DÄ³k (CHAR_BIT - 1) >1) != 0) result = (result << CHAR_BIT) | randchar(); -- Peter Apr 23 '07 #12

 P: n/a "Peter Nilsson" Harald van D?k (CHAR_BIT - 1) >1) != 0) result = (result << CHAR_BIT) | randchar(); Or something more readable: #include #if __STDC_VERSION__ >= 199901L #include #else #define uintmax_t unsigned long #endif int count_bits(uintmax_t n) { int result = 1; while (n/=2) result++; return result; } #define PADDING(t) ( CHAR_BIT*sizeof(t) - count_bits((t)(-1)) ) unsigned long longrand() { size_t i; unsigned long result = 0; size_t bytes = sizeof result - PADDING(unsigned long)/CHAR_BIT; for (i=0; i

 P: n/a "Army1987" #if __STDC_VERSION__ >= 199901L #include #else #define uintmax_t unsigned long #endif Why are you using #define rather than typedef? The test for __STDC_VERSION__ *should* work, but unfortunately in real life it may not be reliable. The __STDC_VERSION__ macro typically tells you whether the compiler claims to support C99; this may or may not tell you whether the #include #else typedef unsigned long uintmax_t #endif but, alas, that doesn't exist. Configuration systems like GNU autoconf can be helpful, but the details are off-topic. -- Keith Thompson (The_Other_Keith) ks***@mib.org San Diego Supercomputer Center <* "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister" Apr 24 '07 #14

 P: n/a Peter Nilsson wrote: > Harald van DÄ³k (CHAR_BIT - 1) >1) != 0) result = (result << CHAR_BIT) | randchar(); (result << CHAR_BIT) is undefined if sizeof(result) equals one. -- pete Apr 28 '07 #15

 P: n/a "pete" >Harald van DÄ³k (CHAR_BIT - 1) >1) != 0) result = (result << CHAR_BIT) | randchar(); (result << CHAR_BIT) is undefined if sizeof(result) equals one. if sizeof result is 1, then m is UCHAR_MAX, and m >(CHAR_BIT - 1) >1 is 0. So the body loop is never done then. (I still wonder why uns_var >value_bits and uns_var << value_bits are undefined. uns_var * 2**value_bits modulo 2**value_bits is 0, and so is floor(uns_var / 2**value_bits). That's what uns_var >value_bits-1 >1 and uns_var << value_bits-1 << 1 do. Maybe I'll post that to comp.std.c.) Apr 28 '07 #16

 P: n/a Army1987 wrote, On 28/04/07 10:28: (I still wonder why uns_var >value_bits and uns_var << value_bits are undefined. uns_var * 2**value_bits modulo 2**value_bits is 0, and so is floor(uns_var / 2**value_bits). That's what uns_var >value_bits-1 >1 and uns_var << value_bits-1 << 1 do. Maybe I'll post that to comp.std.c.) The most probable reason for it being undefined is because the way processors will treat it if you use assembler instructions to do it varies. -- Flash Gordon Apr 28 '07 #17

 P: n/a "Army1987" (CHAR_BIT - 1) >1) != 0) result = (result << CHAR_BIT) | randchar(); Or something more readable: But less correct. ;-) #include #define PADDING(t) ( CHAR_BIT*sizeof(t) - count_bits((t)(-1))) Why are people so hung up on calculating the number of padding bits? unsigned long longrand() { size_t i; unsigned long result = 0; size_t bytes = sizeof result - PADDING(unsigned long) /CHAR_BIT; for (i=0; i

This discussion thread is closed

Replies have been disabled for this discussion. 