|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Roman Mashak <mrv@tusur.ru> wrote:
> I came across this method of checking the sizes: > static union > { > char int8_t_incorrect[sizeof( int8_t) == 1]; > char uint8_t_incorrect[sizeof( uint8_t) == 1]; > char int16_t_incorrect[sizeof( int16_t) == 2]; > char uint16_t_incorrect[sizeof(uint16_t) == 2]; > char int32_t_incorrect[sizeof( int32_t) == 4]; > char uint32_t_incorrect[sizeof(uint32_t) == 4]; > }; > It was recommended to use this declaration in order to let compiler "report > typedef errors automatically". I'm not sure I clearly understand what the > above statement does. It's my understanding that if intN_t/uintN_t types > exist on a platfrom, 'sizeof' operator returns a proper size of them.... and > then what? I guess it's meant to provoke the compiler to emit an error message (or at least a warning) in the case that int8_ta and uint8_t don't have a size of 1, int8_t/uint8_t don't have a size of 2 etc. since in that case e.g. 'sizeof( int8_t ) == 1' woukd be false and thus result in the value 0. And then you would try to create an array of length 0 which isn't legal. I don't know if this is a good idea, I guess I would instead use something that tests if CHAR_BITS is 8 since that seems to be what all that boils down to. Regards, Jens -- \ Jens Thoms Toerring ___ jt@toerring.de \__________________________ http://toerring.de |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
Jens Thoms Toerring <jt@toerring.de> wrote:
> I guess it's meant to provoke the compiler to emit an error > message (or at least a warning) in the case that int8_ta and > uint8_t don't have a size of 1, int8_t/uint8_t don't have a > size of 2 etc. Sorry, make that "int16_t/uint16_t don't have a size of 2"... Regards, Jens -- \ Jens Thoms Toerring ___ jt@toerring.de \__________________________ http://toerring.de |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
On Thu, 29 May 2008 20:36:31 -0700, Roman Mashak wrote:
> Hello, > > I came across this method of checking the sizes: > > static union > { > char int8_t_incorrect[sizeof( int8_t) == 1]; > char uint8_t_incorrect[sizeof( uint8_t) == 1]; > [...] > }; > > It was recommended to use this declaration in order to let compiler > "report typedef errors automatically". I'm not sure I clearly understand > what the above statement does. It's my understanding that if > intN_t/uintN_t types exist on a platfrom, 'sizeof' operator returns a > proper size of them.... and then what? The == operator evaluates to 0 if its operands compare unequal, and to 1 if they compare equal. Normally, this result is used as a boolean value, but it is a plain old int. (1 == 1) == 1. (1 == 2) == 0. So an array of length (sizeof(int8_t) == 1) is an array of length 1, if sizeof(int8_t) == 1, or else an array of length 0. When you define an array of length 0 the compiler will let you know you're doing something wrong. So when sizeof(int8_t) != 1, the compiler will complain. Not that sizeof(int8_t) could possibly be anything other than 1. And when int8_t and int16_t both exist, sizeof(int16_t) cannot possibly be anything other than 2, and when int8_t and int32_t both exist, sizeof(int32_t) cannot possibly be anything other than 4. So the checks are fairly pointless in this case; you could just as well simply make sure the types exist, by using them. But the idea can be applied meaningfully to other checks. |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On May 30, 6:36 am, "Roman Mashak" <m...@tusur.ru> wrote:
> Hello, > > I came across this method of checking the sizes: > > static union > { > char int8_t_incorrect[sizeof( int8_t) == 1]; > char uint8_t_incorrect[sizeof( uint8_t) == 1]; > > char int16_t_incorrect[sizeof( int16_t) == 2]; > char uint16_t_incorrect[sizeof(uint16_t) == 2]; > > char int32_t_incorrect[sizeof( int32_t) == 4]; > char uint32_t_incorrect[sizeof(uint32_t) == 4]; > > }; > > It was recommended to use this declaration in order to let compiler "report > typedef errors automatically". I'm not sure I clearly understand what the > above statement does. It's my understanding that if intN_t/uintN_t types > exist on a platfrom, 'sizeof' operator returns a proper size of them.... and > then what? If intN_t types are available, they are two's complement no padding signed integers with exact width N. Reference, 7.18.1.1 Exact-width integer types. These tests are not needed. |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
Harald van Dijk <truedfx@gmail.com> wrote:
> On Thu, 29 May 2008 20:36:31 -0700, Roman Mashak wrote: > > Hello, > > > > I came across this method of checking the sizes: > > > > static union > > { > > char int8_t_incorrect[sizeof( int8_t) == 1]; > > char uint8_t_incorrect[sizeof( uint8_t) == 1]; > > [...] > > }; > > > > It was recommended to use this declaration in order to let compiler > > "report typedef errors automatically". I'm not sure I clearly understand > > what the above statement does. It's my understanding that if > > intN_t/uintN_t types exist on a platfrom, 'sizeof' operator returns a > > proper size of them.... and then what? > The == operator evaluates to 0 if its operands compare unequal, and to 1 > if they compare equal. Normally, this result is used as a boolean value, > but it is a plain old int. (1 == 1) == 1. (1 == 2) == 0. So an array of > length (sizeof(int8_t) == 1) is an array of length 1, if > sizeof(int8_t) == 1, or else an array of length 0. When you define an > array of length 0 the compiler will let you know you're doing something > wrong. So when sizeof(int8_t) != 1, the compiler will complain. > Not that sizeof(int8_t) could possibly be anything other than 1. And when > int8_t and int16_t both exist, sizeof(int16_t) cannot possibly be anything > other than 2, and when int8_t and int32_t both exist, sizeof(int32_t) > cannot possibly be anything other than 4. But if you have e.g. a machine where CHAR_BITS is 16 wouldn't then sizeof(int16_t) be 1 and that of sizeof(int32_t) be 2? I have never had a chance to use such machines but it would seem logical to me. Regards, Jens -- \ Jens Thoms Toerring ___ jt@toerring.de \__________________________ http://toerring.de |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
On Thu, 29 May 2008 21:05:37 +0000, Jens Thoms Toerring wrote:
> Harald van Dijk <truedfx@gmail.com> wrote: [ snip ] >> And when int8_t and int16_t both exist, sizeof(int16_t) cannot possibly >> be anything other than 2, [ snip ] > But if you have e.g. a machine where CHAR_BITS is 16 wouldn't then > sizeof(int16_t) be 1 [ snip ] Correct. However, on a machine where CHAR_BIT is anything other than 8, int8_t cannot be defined. In other words, if int8_t exists, you already know that CHAR_BIT is equal to 8. |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
On Thu, 29 May 2008 21:28:00 +0000, Szabolcs Borsanyi wrote:
> That's strange. 7.18.1.1 says > > 1 The typedef name intN_t designates a signed integer type with width N, > no padding bits, and a two's complement representation. Thus, int8_t > denotes a signed integer type with a width of exactly 8 bits. > > and also: > > 3 These types are optional. However, if an implementation provides > integer types with widths of 8, 16, 32, or 64 bits, it shall define the > corresponding typedef names. > > Does that imply that if an implementation provides 32 or 16-bit int with > one's complement representation, that it has to define int32_t, which > has, in turn, two's component representation. You are correct, and the text has already been changed to 3 These types are optional. However, if an implementation provides integer types with widths of 8, 16, 32, or 64 bits, no padding bits, and (for the signed types) that have a two's complement representation, it shall define the corresponding typedef names. in an attempt to address precisely that issue. It doesn't manage to do so entirely, though: if an implementation provides a 32-bit ones' complement signed int, and a 32-bit unsigned int, both without padding bits, then 7.18.1.1p3 requires that the implementation define uint32_t, and 7.18.1p1 states that if an implementation provides uint32_t, it must also provide int32_t. |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Harald van D©¦k <true...@gmail.com> wrote:
> ... > When you define an array of length 0 the compiler > will let you know you're doing something wrong. It is a constraint violation. Unfortunately, it's also not an uncommon extension to allow zero sized arrays, particularly at the end of a struct. So, I prefer ((need) ? 1 : -1) for compile time asserts. -- Peter |
|
|
|
#9 |
|
Messages: n/a
Hébergeur: |
On Thu, 29 May 2008 14:57:57 -0700, Peter Nilsson wrote:
> Harald van Dijk <true...@gmail.com> wrote: >> ... >> When you define an array of length 0 the compiler will let you know >> you're doing something wrong. > > It is a constraint violation. Unfortunately, it's also not an uncommon > extension to allow zero sized arrays, particularly at the end of a > struct. So, I prefer ((need) ? 1 : -1) for compile time asserts. I agree, that's a better idea. However, I seem to recall reading that implementations exist that accept negative array length constants as well, and that it's even safer to use bit-field widths because of that. struct check { int member : (... ? 1 : -1); }; As far as standard C is concerned, all are equivalent, as all violate a constraint if the check fails, but in practise, it's good to do whatever's reasonably possible to ensure the diagnostic is a fatal one. |
|
|
|
#10 |
|
Messages: n/a
Hébergeur: |
"Roman Mashak" <mrv@tusur.ru> wrote in message news:g1m4gu$vf7$1@relay.tomsk.ru... > Hello, > > I came across this method of checking the sizes: > > static union > { > char int8_t_incorrect[sizeof( int8_t) == 1]; > char uint8_t_incorrect[sizeof( uint8_t) == 1]; > > char int16_t_incorrect[sizeof( int16_t) == 2]; > char uint16_t_incorrect[sizeof(uint16_t) == 2]; > > char int32_t_incorrect[sizeof( int32_t) == 4]; > char uint32_t_incorrect[sizeof(uint32_t) == 4]; > > }; Its better to report failure case as -1, not 0. [...] |
|
|
|
#11 |
|
Messages: n/a
Hébergeur: |
On Thu, 29 May 2008 20:36:31 -0700, "Roman Mashak" <mrv@tusur.ru>
wrote in comp.lang.c: > Hello, > > I came across this method of checking the sizes: This is a pretty stupid idea, and extremely non-portable. Who's not-so-bright idea is it? > static union > { > char int8_t_incorrect[sizeof( int8_t) == 1]; > char uint8_t_incorrect[sizeof( uint8_t) == 1]; There are implementations where this code will break, even with a C99 compiler. There are architectures that don't have 8-bit bytes, and therefore are prohibited from defining these types. They are required to, and do, define (u)int_least8_t and (u)int_fast8_t types. > char int16_t_incorrect[sizeof( int16_t) == 2]; > char uint16_t_incorrect[sizeof(uint16_t) == 2]; There are platforms where this will break because there are no 16-bit integer types, There are also platforms that have these types, but their size is one byte, CHAR_BIT being 16. > char int32_t_incorrect[sizeof( int32_t) == 4]; > char uint32_t_incorrect[sizeof(uint32_t) == 4]; Of course, there are platforms where size of these types is 2, and others where their size is 1. > }; > > It was recommended to use this declaration in order to let compiler "report Who is the "genius" who recommended this? What are this person's qualifications? > typedef errors automatically". I'm not sure I clearly understand what the > above statement does. It's my understanding that if intN_t/uintN_t types > exist on a platfrom, 'sizeof' operator returns a proper size of them.... and > then what? An error generated compiling this program does not indicate "typedef errors". Instead it indicates an error in the understanding of the person who wrote the declaration and makes that claim. That person assumes that all compilers are like the few he/she is familiar with. The "proper size" (u)int32_t, if it exists on an implementation, can be 4, 2, or 1. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://c-faq.com/ comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html |
|
|
|
#12 |
|
Messages: n/a
Hébergeur: |
Hello,
I came across this method of checking the sizes: static union { char int8_t_incorrect[sizeof( int8_t) == 1]; char uint8_t_incorrect[sizeof( uint8_t) == 1]; char int16_t_incorrect[sizeof( int16_t) == 2]; char uint16_t_incorrect[sizeof(uint16_t) == 2]; char int32_t_incorrect[sizeof( int32_t) == 4]; char uint32_t_incorrect[sizeof(uint32_t) == 4]; }; It was recommended to use this declaration in order to let compiler "report typedef errors automatically". I'm not sure I clearly understand what the above statement does. It's my understanding that if intN_t/uintN_t types exist on a platfrom, 'sizeof' operator returns a proper size of them.... and then what? With best regards, Roman Mashak. E-mail: mrv@tusur.ru |
|
|
|
#13 |
|
Messages: n/a
Hébergeur: |
"Roman Mashak" <mrv@tusur.ru> wrote in message news:g1nsl5$6no$1@relay.tomsk.ru... > Hello, Jack! > You wrote on Thu, 29 May 2008 20:38:35 -0500: > > JK> This is a pretty stupid idea, and extremely non-portable. Who's > JK> not-so-bright idea is it? > http://www.oreillynet.com/pub/a/netw...hael_barr.html > > [skip] > What portable way would you suggest? Checking the CHAR_BITS? [...] Try something like: #include <limits.h> typedef char atomic_word8; typedef short atomic_word16; typedef int atomic_word32; typedef char atomic_word_sizeof_static_assert[ sizeof(atomic_word8) == 8 / CHAR_BIT && sizeof(atomic_word16) == 16 / CHAR_BIT && sizeof(atomic_word32) == 32 / CHAR_BIT ? 1 : -1 ]; |
|
|
|
#14 |
|
Messages: n/a
Hébergeur: |
In article <k2mu34tkv26f6c8h0qn3o0jksr1mod4rcm@4ax.com>,
Jack Klein <jackklein@spamcop.net> wrote: >> I came across this method of checking the sizes: >This is a pretty stupid idea, and extremely non-portable. Who's >not-so-bright idea is it? What's unportable about it? It will cause the compilation to fail if the types are unavailable or are implemented wrongly, which is presumably the idea. -- Richard -- In the selection of the two characters immediately succeeding the numeral 9, consideration shall be given to their replacement by the graphics 10 and 11 to facilitate the adoption of the code in the sterling monetary area. (X3.4-1963) |
|
|
|
#15 |
|
Messages: n/a
Hébergeur: |
Roman Mashak <mrv@tusur.ru> wrote:
> Hello, Jens! > You wrote on 29 May 2008 20:54:28 GMT: > [skip] > JTT> I guess it's meant to provoke the compiler to emit an error > JTT> message (or at least a warning) in the case that int8_ta and > JTT> uint8_t don't have a size of 1, int8_t/uint8_t don't have a > JTT> size of 2 etc. since in that case e.g. 'sizeof( int8_t ) == 1' > JTT> woukd be false and thus result in the value 0. And then you > JTT> would try to create an array of length 0 which isn't legal. > I integrated the above code in the test example and compiled it twice with > 'gcc -W -Wall -std=c99...' and 'gcc -W -Wall -std=c89...'. No error was > emmited in the second case. Should it have been? That then probably means that on your system an int8_t/uint8_t has a size of of 1, and int16_t/uint16_t has a size of 2 etc. And, no it also shouldn't emit an error message for the C89 case since in order to compile it even in C99 mode you must have included <stdint.h> (or some other header file that automatically includes <stdint.h>)- in that header file the types (int8_t,...) are defined. And if they are defined in that header file and that header file exists and is included, then they are defined regardless if you compile in C89 or C99 mode. After having had a look at the article you got that from it is clearer what this is all about. Before C99 the existence of a header file named <stdint.h> wasn't required and so all these types weren't required to be defined. Thus some people would do it themselves with typedefs like this typedef signed char int8_t; typedef unsigned char uint8_t; typedef short int int16_t; typedef unsigned short int uint16_t; typedef int int32_t; typedef unsigned int uint32_t; But this would break on a system where e.g. an int has only 16 and not 32 bits. So the whole thing proposed in that article was meant as a check if the assumptions made when creating these typedefs were correct for the machine you are compiling it on. But if you have a <stdint.h> header file coming with your system it's rather useless (unless you're paranoid if the implementation you are using got it really right;-) to do these kind of checks, they should always succeed. Regards, Jens -- \ Jens Thoms Toerring ___ jt@toerring.de \__________________________ http://toerring.de |
|
|
|
#16 |
|
Messages: n/a
Hébergeur: |
Hello, Jens!
You wrote on 29 May 2008 20:54:28 GMT: [skip] JTT> I guess it's meant to provoke the compiler to emit an error JTT> message (or at least a warning) in the case that int8_ta and JTT> uint8_t don't have a size of 1, int8_t/uint8_t don't have a JTT> size of 2 etc. since in that case e.g. 'sizeof( int8_t ) == 1' JTT> woukd be false and thus result in the value 0. And then you JTT> would try to create an array of length 0 which isn't legal. I integrated the above code in the test example and compiled it twice with 'gcc -W -Wall -std=c99...' and 'gcc -W -Wall -std=c89...'. No error was emmited in the second case. Should it have been? JTT> I don't know if this is a good idea, I guess I would instead JTT> use something that tests if CHAR_BITS is 8 since that seems JTT> to be what all that boils down to. With best regards, Roman Mashak. E-mail: mrv@tusur.ru |
|
|
|
#17 |
|
Messages: n/a
Hébergeur: |
Hello, Jack!
You wrote on Thu, 29 May 2008 20:38:35 -0500: JK> This is a pretty stupid idea, and extremely non-portable. Who's JK> not-so-bright idea is it? http://www.oreillynet.com/pub/a/netw...hael_barr.html [skip] What portable way would you suggest? Checking the CHAR_BITS? With best regards, Roman Mashak. E-mail: mrv@tusur.ru |
|
|
|
#18 |
|
Messages: n/a
Hébergeur: |
On Fri, 30 May 2008 12:34:30 -0700, "Roman Mashak" <mrv@tusur.ru>
wrote in comp.lang.c: > Hello, Jack! > You wrote on Thu, 29 May 2008 20:38:35 -0500: > > JK> This is a pretty stupid idea, and extremely non-portable. Who's > JK> not-so-bright idea is it? > http://www.oreillynet.com/pub/a/netw...hael_barr.html > > [skip] > What portable way would you suggest? Checking the CHAR_BITS? The header <stdint.h> provides minimum and maximum macros for the exact width integer types, if and only if those particular types are defined. As someone else already pointed out, if int8_t and uint8_t exist, the wider types, if they exist as they almost certainly will, will have the sizes you check for. Still, it's much easier to do something like this: #include <stdint.h> #ifndef INT8_MAX ....do something about it #endif But if the types you need are there, why do you care what their sizes are in bytes? Are you actually expecting a compiler to come with errors in its <stdint.h> header? In the Barr article you quote, he is talking about a way of testing a home brew <stdint.h> for a compiler that doesn't come with one. Frankly, anybody who can't get this right on the first try probably shouldn't be trying. -- Jack Klein Home: http://JK-Technology.Com FAQs for comp.lang.c http://c-faq.com/ comp.lang.c++ http://www.parashift.com/c++-faq-lite/ alt.comp.lang.learn.c-c++ http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html |
|
|
|
#19 |
|
Messages: n/a
Hébergeur: |
Hello, Jack!
You wrote on Fri, 30 May 2008 21:41:48 -0500: ??>> Hello, Jack! ??>> You wrote on Thu, 29 May 2008 20:38:35 -0500: ??>> JK>>> This is a pretty stupid idea, and extremely non-portable. Who's JK>>> not-so-bright idea is it? ??>> http://www.oreillynet.com/pub/a/netw...hael_barr.html ??>> ??>> [skip] ??>> What portable way would you suggest? Checking the CHAR_BITS? JK> The header <stdint.h> provides minimum and maximum macros for the JK> exact width integer types, if and only if those particular types are JK> defined. [skip] I got this yet, thanks though. With best regards, Roman Mashak. E-mail: mrv@tusur.ru |
|
![]() |
| Outils de la discussion | |
|
|