Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #63510 > unrolled thread

What is the output of this program ?

Started byRahul Kumar <rahulkumar5july@gmail.com>
First post2015-06-18 06:45 -0700
Last post2015-06-18 10:14 -0700
Articles 19 — 7 participants

Back to article view | Back to comp.lang.c


Contents

  What is the output of this program ? Rahul Kumar <rahulkumar5july@gmail.com> - 2015-06-18 06:45 -0700
    Re: What is the output of this program ? James Kuyper <jameskuyper@verizon.net> - 2015-06-18 10:10 -0400
    Re: What is the output of this program ? Richard Heathfield <rjh@cpax.org.uk> - 2015-06-18 15:22 +0100
      Re: What is the output of this program ? Keith Thompson <kst-u@mib.org> - 2015-06-18 08:07 -0700
        Re: What is the output of this program ? Richard Heathfield <rjh@cpax.org.uk> - 2015-06-18 16:11 +0100
      Re: What is the output of this program ? Ralf Damaschke <rwspam@gmx.de> - 2015-06-18 18:48 +0000
        Re: What is the output of this program ? Richard Heathfield <rjh@cpax.org.uk> - 2015-06-18 23:01 +0100
      Re: What is the output of this program ? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-11 08:31 -0700
        Re: What is the output of this program ? jadill33@gmail.com - 2015-07-13 07:51 -0700
          Re: What is the output of this program ? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-15 02:51 -0700
            Re: What is the output of this program ? jadill33@gmail.com - 2015-07-15 05:55 -0700
              Re: What is the output of this program ? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-20 10:01 -0700
        Re: What is the output of this program ? Richard Heathfield <rjh@cpax.org.uk> - 2015-07-13 22:07 +0100
          Re: What is the output of this program ? Keith Thompson <kst-u@mib.org> - 2015-07-13 14:16 -0700
          Re: What is the output of this program ? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-15 02:11 -0700
            Re: What is the output of this program ? Richard Heathfield <rjh@cpax.org.uk> - 2015-07-15 10:58 +0100
              Re: What is the output of this program ? Tim Rentsch <txr@alumni.caltech.edu> - 2015-07-20 10:05 -0700
    Re: What is the output of this program ? James Kuyper <jameskuyper@verizon.net> - 2015-06-18 12:26 -0400
      Re: What is the output of this program ? Keith Thompson <kst-u@mib.org> - 2015-06-18 10:14 -0700

#63510 — What is the output of this program ?

FromRahul Kumar <rahulkumar5july@gmail.com>
Date2015-06-18 06:45 -0700
SubjectWhat is the output of this program ?
Message-ID<b3e47c82-8ba3-4d5d-bf40-6f87a390b15a@googlegroups.com>
#include <stdio.h>

struct s
{
	int a:4;
	char b:5;
	int c:7;
	unsigned f1:1;
	unsigned f2:24;
	unsigned :3;
	int :3;// anonymous b.f. -- not accessible
	int :0;	// significance -- align to next word boundary -- 47 bit < 64 bit -- align to 64 bit(8byte)
	unsigned f3:6;	// 70 bit
	unsigned :0; 	// ????? -- 96
	unsigned f4:8;	//104 -- 13 byte -- 16 byte size
}x;

int main()
{
	printf("%d\n",sizeof(x));
}

how to calculate output of this program,please help me,i am just confused with it.

[toc] | [next] | [standalone]


#63513

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-06-18 10:10 -0400
Message-ID<mluje8$ke4$1@dont-email.me>
In reply to#63510
On 06/18/2015 09:45 AM, Rahul Kumar wrote:
> #include <stdio.h>
> 
> struct s
> {
> 	int a:4;
> 	char b:5;
> 	int c:7;
> 	unsigned f1:1;
> 	unsigned f2:24;
> 	unsigned :3;
> 	int :3;// anonymous b.f. -- not accessible
> 	int :0;	// significance -- align to next word boundary -- 47 bit < 64 bit -- align to 64 bit(8byte)
> 	unsigned f3:6;	// 70 bit
> 	unsigned :0; 	// ????? -- 96
> 	unsigned f4:8;	//104 -- 13 byte -- 16 byte size
> }x;
> 
> int main()
> {
> 	printf("%d\n",sizeof(x));
> }
> 
> how to calculate output of this program,please help me,i am just confused with it.

The only reliable way is to compile and execute it. Different
implementations of C are allowed to give different results for the size.
This is because the C standard allows implementations a lot of freedom
to insert padding bytes in structures, and padding bits in between
bit-fields. There are some restrictions, but no upper limit on the size.
It also depends upon the value of CHAR_BIT, but that's less likely to be
an issue.
-- 
James Kuyper

[toc] | [prev] | [next] | [standalone]


#63514

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-06-18 15:22 +0100
Message-ID<mluk3u$nk3$1@dont-email.me>
In reply to#63510
On 18/06/15 14:45, Rahul Kumar wrote:
> #include <stdio.h>
>
> struct s
> {
> 	int a:4;
> 	char b:5;
> 	int c:7;
> 	unsigned f1:1;
> 	unsigned f2:24;
> 	unsigned :3;
> 	int :3;// anonymous b.f. -- not accessible
> 	int :0;	// significance -- align to next word boundary -- 47 bit < 64 bit -- align to 64 bit(8byte)
> 	unsigned f3:6;	// 70 bit
> 	unsigned :0; 	// ????? -- 96
> 	unsigned f4:8;	//104 -- 13 byte -- 16 byte size
> }x;
>
> int main()
> {
> 	printf("%d\n",sizeof(x));
> }
>
> how to calculate output of this program,please help me,i am just confused with it.

 From N1570 6.7.2.1(5):

A bit-field shall have a type that is a qualified or unqualified version 
of _Bool, signed int, unsigned int, or some other implementation-defined 
type. It is implementation-defined whether atomic types are permitted.

So char b:5 is only permitted if your implementation specifically 
documents the fact in its conformance documentation.

With the exception of char (which is guaranteed to be 1 byte, where a 
byte must be *at least* 8 bits wide), the C standard does not specify 
byte sizes for types (well, not for vanilla types, anyway, and we're 
only concerned with vanilla types here). Therefore, the correct way to 
calculate the size of the struct is to use sizeof, which is what you've 
done.

The correct way to /print/ size_t values, however, is not %d, but %zd. 
(If your compiler doesn't support %zd then it probably doesn't support 
anonymous bitfields, either.)

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#63522

FromKeith Thompson <kst-u@mib.org>
Date2015-06-18 08:07 -0700
Message-ID<lnbngdjbs0.fsf@nuthaus.mib.org>
In reply to#63514
Richard Heathfield <rjh@cpax.org.uk> writes:
[...]
> The correct way to /print/ size_t values, however, is not %d, but %zd. 
> (If your compiler doesn't support %zd then it probably doesn't support 
> anonymous bitfields, either.)

It's "%zu", since size_t is an unsigned type.  "%zd" is likely to work
for reasonable values (it's vanishingly unlikely that the size of this
particular struct would be that big).

If your implementation doesn't support "%zu", you can use "%lu" and cast
the value to unsigned long, which will work as long as the value doesn't
exceed ULONG_MAX.

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#63523

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-06-18 16:11 +0100
Message-ID<mlun0i$340$1@dont-email.me>
In reply to#63522
On 18/06/15 16:07, Keith Thompson wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
> [...]
>> The correct way to /print/ size_t values, however, is not %d, but %zd.
>> (If your compiler doesn't support %zd then it probably doesn't support
>> anonymous bitfields, either.)
>
> It's "%zu", since size_t is an unsigned type.

What was I thinking?

And to save you the trouble, I'll add:
s/hat w//

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#63547

FromRalf Damaschke <rwspam@gmx.de>
Date2015-06-18 18:48 +0000
Message-ID<pan.2015.06.18.18.48.09@y2plugh.fqdn.th-h.de>
In reply to#63514
Richard Heathfield schrieb:

> (If your compiler doesn't support %zd then it probably doesn't support 
> anonymous bitfields, either.)

Here your memory seems to fade. C89 does not have a 'z' length modifier but it
already has anonymous bit-fields.

[toc] | [prev] | [next] | [standalone]


#63560

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-06-18 23:01 +0100
Message-ID<mlvf1p$bmp$1@dont-email.me>
In reply to#63547
On 18/06/15 19:48, Ralf Damaschke wrote:
> Richard Heathfield schrieb:
>
>> (If your compiler doesn't support %zd then it probably doesn't support
>> anonymous bitfields, either.)
>
> Here your memory seems to fade. C89 does not have a 'z' length modifier but it
> already has anonymous bit-fields.


You're half-right. You're right that C89 does have anonymous bit-fields, 
but it wasn't my memory that was fading. Quite simply, I never knew 
this, ever. But when I went back to C89 to check your outrageous claim, 
it turned out (outrageously) to be true.

Of course, my memory isn't perfect, but on this occasion it was not 
amnesia that did for me - it was ignorance.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#65292

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-07-11 08:31 -0700
Message-ID<kfnr3oeyam1.fsf@x-alumni2.alumni.caltech.edu>
In reply to#63514
Richard Heathfield <rjh@cpax.org.uk> writes:

> The correct way to /print/ size_t values, however, is not %d,
> but %zd.

Isn't this contrary to your rule of limiting yourself
to constructs common to C90, C99 and C11?  ;)

[toc] | [prev] | [next] | [standalone]


#65485

Fromjadill33@gmail.com
Date2015-07-13 07:51 -0700
Message-ID<d5db7c37-4b8e-411d-9c7e-c7176e5ad61e@googlegroups.com>
In reply to#65292
On Saturday, July 11, 2015 at 11:31:26 AM UTC-4, Tim Rentsch wrote:
> Richard Heathfield <r...@cpax.org.uk> writes:
> 
> > The correct way to /print/ size_t values, however, is not %d,
> > but %zd.
> 
> Isn't this contrary to your rule of limiting yourself
> to constructs common to C90, C99 and C11?  ;)

Yeah, C90 plus <stdint.h>/<inttypes.h> is what I aim for supporting,
to the point of providing my own wrapper if it doesn't exist since I
find it so useful.

Since %zd isn't available on C90 platforms, I resort to making a
format specifier, based on an existing stdint.h file or a wrapper.

\code
/*
 * Even if the Microsoft C Runtime library is linked by a C99 supported
 * implementation, the printf modifier "z" may still not work.
 */
#if defined(__STDC__) && defined(__STDC_VERSION__)
#  if (__STDC__ && __STDC_VERSION__ >= 199901L)
#    if defined(_WIN32) || defined(__WIN32__)
       /* Microsoft Runtime does not support the 'z' modifier. */
#    else
#      define inttypes_priusize_defined
#      define PRIoSIZE  "zo"
#      define PRIuSIZE  "zu"
#      define PRIxSIZE  "zx"
#      define PRIXSIZE  "zX"
#    endif
#  endif
#endif

#if !defined(inttypes_priusize_defined)
#  if (SIZE_MAX == UINT16_MAX)
#    define PRIoSIZE  PRIo16
#    define PRIuSIZE  PRIu16
#    define PRIxSIZE  PRIx16
#    define PRIXSIZE  PRIX16
#  elif (SIZE_MAX == UINT32_MAX)
#    define PRIoSIZE  PRIo32
#    define PRIuSIZE  PRIu32
#    define PRIxSIZE  PRIx32
#    define PRIXSIZE  PRIX32
#  elif !defined(ANSI_C_PSTDINT)
#    if defined(UINT64_MAX) && (SIZE_MAX == UINT64_MAX)
#      define PRIoSIZE  PRIo64
#      define PRIuSIZE  PRIu64
#      define PRIxSIZE  PRIx64
#      define PRIXSIZE  PRIX64
#    else
#      error "Platform not supported"
#    endif
#  else
#    error "Platform not supported"
#  endif
#endif
\endcode

Not a pretty solution, but I've found it useful in my attempt to
stay as close to C90 as I can.  And one can add a prefix to PRI
if they don't like the namespace clash.

I'd almost make a case that C99 should have a PRI[ouxX]SIZE in
addition to %zd, but too much water under that bridge.  Same for
PTR[di]PTRDIFF and PRI[diouxX]LL.

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#65608

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-07-15 02:51 -0700
Message-ID<kfnk2u1u4sw.fsf@x-alumni2.alumni.caltech.edu>
In reply to#65485
jadill33@gmail.com writes:

> On Saturday, July 11, 2015 at 11:31:26 AM UTC-4, Tim Rentsch wrote:
>> Richard Heathfield <r...@cpax.org.uk> writes:
>>
>>> The correct way to /print/ size_t values, however, is not %d,
>>> but %zd.
>>
>> Isn't this contrary to your rule of limiting yourself
>> to constructs common to C90, C99 and C11?  ;)
>
> Yeah, C90 plus <stdint.h>/<inttypes.h> is what I aim for supporting,
> to the point of providing my own wrapper if it doesn't exist since I
> find it so useful.

Making your own wrapper sounds like a great approach.

> Since %zd isn't available on C90 platforms, I resort to making a
> format specifier, based on an existing stdint.h file or a wrapper.

Note incidentally that the defined() calls for __STDC__,
UINT64_MAX, and __STDC_VERSION__ are not necessary in the code
you give.  Also, strictly speaking SIZE_MAX is not defined in
C90.  More on the last point further down.

> \code
> /*
>  * Even if the Microsoft C Runtime library is linked by a C99 supported
>  * implementation, the printf modifier "z" may still not work.
>  */
> #if defined(__STDC__) && defined(__STDC_VERSION__)
> #  if (__STDC__ && __STDC_VERSION__ >= 199901L)
> #    if defined(_WIN32) || defined(__WIN32__)
>        /* Microsoft Runtime does not support the 'z' modifier. */
> #    else
> #      define inttypes_priusize_defined
> #      define PRIoSIZE  "zo"
> #      define PRIuSIZE  "zu"
> #      define PRIxSIZE  "zx"
> #      define PRIXSIZE  "zX"
> #    endif
> #  endif
> #endif
>
> #if !defined(inttypes_priusize_defined)
> #  if (SIZE_MAX == UINT16_MAX)
> #    define PRIoSIZE  PRIo16
> #    define PRIuSIZE  PRIu16
> #    define PRIxSIZE  PRIx16
> #    define PRIXSIZE  PRIX16
> #  elif (SIZE_MAX == UINT32_MAX)
> #    define PRIoSIZE  PRIo32
> #    define PRIuSIZE  PRIu32
> #    define PRIxSIZE  PRIx32
> #    define PRIXSIZE  PRIX32
> #  elif !defined(ANSI_C_PSTDINT)
> #    if defined(UINT64_MAX) && (SIZE_MAX == UINT64_MAX)
> #      define PRIoSIZE  PRIo64
> #      define PRIuSIZE  PRIu64
> #      define PRIxSIZE  PRIx64
> #      define PRIXSIZE  PRIX64
> #    else
> #      error "Platform not supported"
> #    endif
> #  else
> #    error "Platform not supported"
> #  endif
> #endif
> \endcode
>
> Not a pretty solution, but I've found it useful in my attempt
> to stay as close to C90 as I can.

I like the idea but I would suggest a slightly different
approach in implementing it (shown below).

> And one can add a prefix to PRI if they don't like the
> namespace clash.

Personally I would favor preserving the PRI_ forms for the
extended names.  As a safety measure a, eg, #ifdef PRIuSIZE
could check for potential collisions.

> I'd almost make a case that C99 should have a PRI[ouxX]SIZE in
> addition to %zd, but too much water under that bridge.  Same
> for PTR[di]PTRDIFF and PRI[diouxX]LL.

I agree on PTR[di]PTRDIFF.  Not sure I see the point for
PRI[diouxX]LL, except maybe for symmetry, in which case maybe
there should be PRI[diouxX]L and PRI[diouxX] as well.  You
could add those to your wrapper.

Now here is my suggested alternative for how to do a wrapper.
Note that all I am addressing here is definitions for PRI*SIZE,
not any of the other PRI* names that <inttypes.h> provides,
which I consider a separate topic.

The basic idea is to rely on C99 headers only if running in C99
mode, and apply a heuristic if that is not the case.  If SIZE_MAX
is defined, it seems likely that size_t will be the first of
{unsigned, unsigned long, unsigned long long} that matches the
range of size_t.  If SIZE_MAX is not available, a simple
heuristic is illustrated in the example;  presumably this would
be extended if/when platforms are encountered that need special
casing.  To prevent possible mismatches from silently going
wrong, a santity check is put in that functions (no pun intended)
as a "static assert" of sorts.

I tried this out on a couple of different platforms in both C90
and C99, it compiled cleanly (including a test use of PRIuSIZE)
in all cases (and ran correctly showing that the PRIuSIZE use
actually works).

Okay, here we go...


#include <limits.h>
#include <stddef.h>
#if __STDC_VERSION__ > 199900
#include <stdint.h>
#endif

#ifdef  SIZE_MAX

#   if    SIZE_MAX == UINT_MAX
#               define SIZE_T_LENGTH_MODIFIER   ""
#               define SIZE_T_UNDERLYING_TYPE   unsigned
#   elif  SIZE_MAX == ULONG_MAX
#               define SIZE_T_LENGTH_MODIFIER   "l"
#               define SIZE_T_UNDERLYING_TYPE   unsigned long
#   elif  SIZE_MAX == ULLONG_MAX
#               define SIZE_T_LENGTH_MODIFIER   "ll"
#               define SIZE_T_UNDERLYING_TYPE   unsigned long long
#   else
#               error No suitable type found for size_t underlying type.
#   endif

#else /* SIZE_MAX is not available, make an educated guess. */

#   if  UINT_MAX == ULONG_MAX
#               define SIZE_T_LENGTH_MODIFIER   ""
#               define SIZE_T_UNDERLYING_TYPE   unsigned
#   else
#               define SIZE_T_LENGTH_MODIFIER   "l"
#               define SIZE_T_UNDERLYING_TYPE   unsigned long
#   endif

#endif

extern int (*size_t_underlying_static_check)( size_t * );
extern int (*size_t_underlying_static_check)( SIZE_T_UNDERLYING_TYPE * );

#define PRIoSIZE  SIZE_T_LENGTH_MODIFIER "o"
#define PRIuSIZE  SIZE_T_LENGTH_MODIFIER "u"
#define PRIxSIZE  SIZE_T_LENGTH_MODIFIER "x"
#define PRIXSIZE  SIZE_T_LENGTH_MODIFIER "X"


What do you think?

[toc] | [prev] | [next] | [standalone]


#65619

Fromjadill33@gmail.com
Date2015-07-15 05:55 -0700
Message-ID<a1a0cdd6-5586-4fe7-8630-ca1b801b2386@googlegroups.com>
In reply to#65608
On Wednesday, July 15, 2015 at 5:51:57 AM UTC-4, Tim Rentsch wrote:
> ja...@gmail.com writes:
> 
> > On Saturday, July 11, 2015 at 11:31:26 AM UTC-4, Tim Rentsch wrote:
> >> Richard Heathfield <r...@cpax.org.uk> writes:
> >>
> >>> The correct way to /print/ size_t values, however, is not %d,
> >>> but %zd.
> >>
> >> Isn't this contrary to your rule of limiting yourself
> >> to constructs common to C90, C99 and C11?  ;)
> >
> > Yeah, C90 plus <stdint.h>/<inttypes.h> is what I aim for supporting,
> > to the point of providing my own wrapper if it doesn't exist since I
> > find it so useful.
> 
> Making your own wrapper sounds like a great approach.
> 
> > Since %zd isn't available on C90 platforms, I resort to making a
> > format specifier, based on an existing stdint.h file or a wrapper.
> 
> Note incidentally that the defined() calls for __STDC__,
> UINT64_MAX, and __STDC_VERSION__ are not necessary in the code
> you give.  Also, strictly speaking SIZE_MAX is not defined in
> C90.  More on the last point further down.

Ah yes, I forgot to include that about SIZE_MAX in my post.  My wrapper
file is quite long (> 1000 lines), and I didn't want my post to go
overboard.

Here is how I approached the definition of SIZE_MAX in my wrapper.
Unfortunately, my wrapper has dependencies defined in a couple of other
headers, but hopefully it's clear what I'm trying to do.  Of course,
in C90, this relies on previous definitions of UINTnMAX defined in the
wrapper.

\code
/*
 * If SIZE_MAX is not defined, the typical substitute is to use a
 * macro defined to something like ((size_t)-1) or (~(size_t)0).
 * This definition does not work if one wants to define a fprintf
 * modifier macro like PRIuSIZE to print size_t values.  Defining
 * the set of PRI[ouxX]SIZE modifier macros requires a SIZE_MAX
 * definition that is compatible with preprocessor comparisons.
 *
 * Instead, a different route is needed to define SIZE_MAX.  One
 * observation is that if one knows the size of 'size_t', one can
 * infer what its SIZE_MAX value should be.  Unfortunately the
 * compiler is not able to evaluate the 'sizeof' operator during
 * the preprocessing phase, so one must depend on an external
 * indicator of the size of 'size_t'.
 *
 * One common auto-configuration tool called Autoconf can run a
 * test to determine its size that results in a symbol named
 * 'SIZEOF_SIZE_T', defined to 'sizeof (size_t)'.  That symbol may
 * be defined within a Makefile or in a configuration file like
 * config.h.  If the 'SIZEOF_SIZE_T' symbol is not found, the backup
 * plan is to check 'size_t' for compatibility with either 'uint64_t'
 * or 'unsigned long', and verify that assertion by checking that
 * 'sizeof (size_t) == sizeof (unsigned long)'.  If the assertion is
 * invalid, the developer will need to resolve the issue manually,
 * either by defining the value of 'SIZEOF_SIZE_T' or modifying
 * pstdint.h to resolve the conflict.
 */
#if !defined(SIZE_MAX)
#  if defined(SIZEOF_SIZE_T) && (CHAR_BIT == 8)
#    if (SIZEOF_SIZE_T == 2)
#      define SIZE_MAX UINT16_MAX
       C_STATIC_ASSERT (sizeof (size_t) == sizeof (uint16_t),
                        SIZE_MAX_is_compatible_with_uint16_t);
#    elif (SIZEOF_SIZE_T == 4)
#      define SIZE_MAX UINT32_MAX
       C_STATIC_ASSERT (sizeof (size_t) == sizeof (uint32_t),
                        SIZE_MAX_is_compatible_with_uint32_t);
#    elif defined(UINT64_MAX) && (SIZEOF_SIZE_T == 8)
#      define SIZE_MAX UINT64_MAX
       C_STATIC_ASSERT (sizeof (size_t) == sizeof (uint64_t),
                        SIZE_MAX_is_compatible_with_uint64_t);
#    else
#      error "Platform not supported."
#    endif
#  else
     /*
      * The C99 standard quotes the following recommended practice.
      *
      * 7.17  Common definitions <stddef.h>
      *
      * 4     The types used for size_t and ptrdiff_t should not
      *       have an integer conversion rank greater than that of
      *       signed long int unless the implementation supports
      *       objects large enough to make this necessary.
      *
      * If this assertion is not valid, then one must manually
      * define 'SIZEOF_SIZE_T'.
      *
      * On 64-bit Microsoft platforms, the constant ULONG_MAX will
      * not work because unsigned long is 32-bits while size_t is
      * 64-bits.
      */
#    if defined(_WIN64)
       define SIZE_MAX UINT64_MAX
       C_STATIC_ASSERT (sizeof (size_t) == sizeof (uint64_t),
                        SIZE_MAX_is_compatible_with_uint64_t);
#    else
#      define SIZE_MAX ULONG_MAX
       C_STATIC_ASSERT (sizeof (size_t) == sizeof (unsigned long),
                        SIZE_MAX_is_compatible_with_unsigned_long);
#    endif
#  endif
#endif
\endcode

> > \code
> > /*
> >  * Even if the Microsoft C Runtime library is linked by a C99 supported
> >  * implementation, the printf modifier "z" may still not work.
> >  */
> > #if defined(__STDC__) && defined(__STDC_VERSION__)
> > #  if (__STDC__ && __STDC_VERSION__ >= 199901L)
> > #    if defined(_WIN32) || defined(__WIN32__)
> >        /* Microsoft Runtime does not support the 'z' modifier. */
> > #    else
> > #      define inttypes_priusize_defined
> > #      define PRIoSIZE  "zo"
> > #      define PRIuSIZE  "zu"
> > #      define PRIxSIZE  "zx"
> > #      define PRIXSIZE  "zX"
> > #    endif
> > #  endif
> > #endif
> >
> > #if !defined(inttypes_priusize_defined)
> > #  if (SIZE_MAX == UINT16_MAX)
> > #    define PRIoSIZE  PRIo16
> > #    define PRIuSIZE  PRIu16
> > #    define PRIxSIZE  PRIx16
> > #    define PRIXSIZE  PRIX16
> > #  elif (SIZE_MAX == UINT32_MAX)
> > #    define PRIoSIZE  PRIo32
> > #    define PRIuSIZE  PRIu32
> > #    define PRIxSIZE  PRIx32
> > #    define PRIXSIZE  PRIX32
> > #  elif !defined(ANSI_C_PSTDINT)
> > #    if defined(UINT64_MAX) && (SIZE_MAX == UINT64_MAX)
> > #      define PRIoSIZE  PRIo64
> > #      define PRIuSIZE  PRIu64
> > #      define PRIxSIZE  PRIx64
> > #      define PRIXSIZE  PRIX64
> > #    else
> > #      error "Platform not supported"
> > #    endif
> > #  else
> > #    error "Platform not supported"
> > #  endif
> > #endif
> > \endcode
> >
> > Not a pretty solution, but I've found it useful in my attempt
> > to stay as close to C90 as I can.
> 
> I like the idea but I would suggest a slightly different
> approach in implementing it (shown below).
> 
> > And one can add a prefix to PRI if they don't like the
> > namespace clash.
> 
> Personally I would favor preserving the PRI_ forms for the
> extended names.  As a safety measure a, eg, #ifdef PRIuSIZE
> could check for potential collisions.

I agree.

> > I'd almost make a case that C99 should have a PRI[ouxX]SIZE in
> > addition to %zd, but too much water under that bridge.  Same
> > for PTR[di]PTRDIFF and PRI[diouxX]LL.
> 
> I agree on PTR[di]PTRDIFF.  Not sure I see the point for
> PRI[diouxX]LL, except maybe for symmetry, in which case maybe
> there should be PRI[diouxX]L and PRI[diouxX] as well.  You
> could add those to your wrapper.

The motivation for most of these definitions was dealing with Microsoft's
C Runtime (especially when it didn't support C99 printf modifiers).  To
support C99 long long, I felt PRI[diouxX]LL was a method I could portably
print 64-bit integers using either the C99 "ll" or the Microsoft "I64"
definitions.  Since C90 supports fprintf modifiers for the long and int
types, I did not see a motivation to add PRI[diouxX]L or PRI[diouxX] as
extensions.

> Now here is my suggested alternative for how to do a wrapper.
> Note that all I am addressing here is definitions for PRI*SIZE,
> not any of the other PRI* names that <inttypes.h> provides,
> which I consider a separate topic.
> 
> The basic idea is to rely on C99 headers only if running in C99
> mode, and apply a heuristic if that is not the case.  If SIZE_MAX
> is defined, it seems likely that size_t will be the first of
> {unsigned, unsigned long, unsigned long long} that matches the
> range of size_t.  If SIZE_MAX is not available, a simple
> heuristic is illustrated in the example;  presumably this would
> be extended if/when platforms are encountered that need special
> casing.  To prevent possible mismatches from silently going
> wrong, a santity check is put in that functions (no pun intended)
> as a "static assert" of sorts.
> 
> I tried this out on a couple of different platforms in both C90
> and C99, it compiled cleanly (including a test use of PRIuSIZE)
> in all cases (and ran correctly showing that the PRIuSIZE use
> actually works).
> 
> Okay, here we go...
> 
> 
> #include <limits.h>
> #include <stddef.h>
> #if __STDC_VERSION__ > 199900
> #include <stdint.h>
> #endif
> 
> #ifdef  SIZE_MAX
> 
> #   if    SIZE_MAX == UINT_MAX
> #               define SIZE_T_LENGTH_MODIFIER   ""
> #               define SIZE_T_UNDERLYING_TYPE   unsigned
> #   elif  SIZE_MAX == ULONG_MAX
> #               define SIZE_T_LENGTH_MODIFIER   "l"
> #               define SIZE_T_UNDERLYING_TYPE   unsigned long
> #   elif  SIZE_MAX == ULLONG_MAX
> #               define SIZE_T_LENGTH_MODIFIER   "ll"
> #               define SIZE_T_UNDERLYING_TYPE   unsigned long long
> #   else
> #               error No suitable type found for size_t underlying type.
> #   endif
> 
> #else /* SIZE_MAX is not available, make an educated guess. */
> 
> #   if  UINT_MAX == ULONG_MAX
> #               define SIZE_T_LENGTH_MODIFIER   ""
> #               define SIZE_T_UNDERLYING_TYPE   unsigned
> #   else
> #               define SIZE_T_LENGTH_MODIFIER   "l"
> #               define SIZE_T_UNDERLYING_TYPE   unsigned long
> #   endif
> 
> #endif
> 
> extern int (*size_t_underlying_static_check)( size_t * );
> extern int (*size_t_underlying_static_check)( SIZE_T_UNDERLYING_TYPE * );
> 
> #define PRIoSIZE  SIZE_T_LENGTH_MODIFIER "o"
> #define PRIuSIZE  SIZE_T_LENGTH_MODIFIER "u"
> #define PRIxSIZE  SIZE_T_LENGTH_MODIFIER "x"
> #define PRIXSIZE  SIZE_T_LENGTH_MODIFIER "X"
> 
> 
> What do you think?

I like the idea, and it would shorten my file by a bit.  I'm not quite
sure what's going on with the 'underlying_static_check', so can you
explain that in a little more detail?

Thanks again for your time.

Best regards,
John D.

[toc] | [prev] | [next] | [standalone]


#66020

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-07-20 10:01 -0700
Message-ID<kfnk2tun4oz.fsf@x-alumni2.alumni.caltech.edu>
In reply to#65619
jadill33@gmail.com writes:

> On Wednesday, July 15, 2015 at 5:51:57 AM UTC-4, Tim Rentsch wrote:
>> ja...@gmail.com writes:
>>
>> [snipped rather ruthlessly]
>>
>> Note incidentally that the defined() calls for __STDC__,
>> UINT64_MAX, and __STDC_VERSION__ are not necessary in the code
>> you give.  Also, strictly speaking SIZE_MAX is not defined in
>> C90.  More on the last point further down.
>
> Ah yes, I forgot to include that about SIZE_MAX in my post.  My wrapper
> file is quite long (> 1000 lines), and I didn't want my post to go
> overboard.
>
> Here is how I approached the definition of SIZE_MAX in my wrapper.
> [snip]

Okay, glad to see you considered it.

>>> I'd almost make a case that C99 should have a PRI[ouxX]SIZE in
>>> addition to %zd, but too much water under that bridge.  Same
>>> for PTR[di]PTRDIFF and PRI[diouxX]LL.
>>
>> I agree on PTR[di]PTRDIFF.  Not sure I see the point for
>> PRI[diouxX]LL, except maybe for symmetry, in which case maybe
>> there should be PRI[diouxX]L and PRI[diouxX] as well.  You
>> could add those to your wrapper.
>
> The motivation for most of these definitions was dealing with
> Microsoft's C Runtime (especially when it didn't support C99
> printf modifiers). [snip]

Ahh, now I get it.  Very sensible.

>> Now here is my suggested alternative for how to do a wrapper.
>> [snip]
>>
>> #ifdef  SIZE_MAX
>>
>> #   if    SIZE_MAX == UINT_MAX
>> #               define SIZE_T_LENGTH_MODIFIER   ""
>> #               define SIZE_T_UNDERLYING_TYPE   unsigned
>> #   elif  SIZE_MAX == ULONG_MAX
>> #               define SIZE_T_LENGTH_MODIFIER   "l"
>> #               define SIZE_T_UNDERLYING_TYPE   unsigned long
>> #   elif  SIZE_MAX == ULLONG_MAX
>> #               define SIZE_T_LENGTH_MODIFIER   "ll"
>> #               define SIZE_T_UNDERLYING_TYPE   unsigned long long
>> #   else
>> #               error No suitable type found for size_t underlying type.
>> #   endif
>>
>> #else /* SIZE_MAX is not available, make an educated guess. */
>>   [snip]
>> #endif
>>
>> extern int (*size_t_underlying_static_check)( size_t * );
>> extern int (*size_t_underlying_static_check)( SIZE_T_UNDERLYING_TYPE * );
>
> I like the idea, and it would shorten my file by a bit.  I'm not quite
> sure what's going on with the 'underlying_static_check', so can you
> explain that in a little more detail?

Simple idea.  By declaring the function twice, once with
'size_t *' and once with 'SIZE_T_UNDERLYING_TYPE *', which
of course will expand to one of 'unsigned *', etc, the two
declarations will be checked for type compatibility.  Doing
this ensures the type we guessed for size_t matches the
actual type that size_t corresponds to, since otherwise
the type mismatch will produce a diagnostic (and probably
a fatal one, although of course there are no guarantees
about that).

[toc] | [prev] | [next] | [standalone]


#65522

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-07-13 22:07 +0100
Message-ID<mo197q$al6$1@dont-email.me>
In reply to#65292
On 11/07/15 16:31, Tim Rentsch wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>> The correct way to /print/ size_t values, however, is not %d,
>> but %zd.
>
> Isn't this contrary to your rule of limiting yourself
> to constructs common to C90, C99 and C11?  ;)


My answer was posited on the basis that the code was C99 (because of 
anonymous wossnames, which I incorrectly thought were not supported by 
C90). In writing what I would consider to be maximally portable code, I 
would not use %z at all. But, if (as I incorrectly thought) one is using 
C99 anyway, one might as well take advantage of %z.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#65524

FromKeith Thompson <kst-u@mib.org>
Date2015-07-13 14:16 -0700
Message-ID<lnmvyzlpvf.fsf@kst-u.example.com>
In reply to#65522
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 11/07/15 16:31, Tim Rentsch wrote:
>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>
>>> The correct way to /print/ size_t values, however, is not %d,
>>> but %zd.
>>
>> Isn't this contrary to your rule of limiting yourself
>> to constructs common to C90, C99 and C11?  ;)
>
>
> My answer was posited on the basis that the code was C99 (because of 
> anonymous wossnames, which I incorrectly thought were not supported by 
> C90). In writing what I would consider to be maximally portable code, I 
> would not use %z at all. But, if (as I incorrectly thought) one is using 
> C99 anyway, one might as well take advantage of %z.

I mentioned this before, but the correct format for size_t is "%zu", not
"%zd" (since size_t is an unsigned type).

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [next] | [standalone]


#65607

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-07-15 02:11 -0700
Message-ID<kfnoajdu6na.fsf@x-alumni2.alumni.caltech.edu>
In reply to#65522
Richard Heathfield <rjh@cpax.org.uk> writes:

> On 11/07/15 16:31, Tim Rentsch wrote:
>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>
>>> The correct way to /print/ size_t values, however, is not %d,
>>> but %zd.
>>
>> Isn't this contrary to your rule of limiting yourself
>> to constructs common to C90, C99 and C11?  ;)
>
> My answer was posited on the basis that the code was C99 (because of
> anonymous wossnames, which I incorrectly thought were not supported by
> C90).  In writing what I would consider to be maximally portable code,
> I would not use %z at all.  But, if (as I incorrectly thought) one is
> using C99 anyway, one might as well take advantage of %z.

Yes, I see that, and it's quite reasonable.  I was gently
(I hoped) making fun of your position on which parts of
C should be used, which seems to me more uncompromising
than it should be.  Probably I shouldn't have - sorry
about that.

[toc] | [prev] | [next] | [standalone]


#65610

FromRichard Heathfield <rjh@cpax.org.uk>
Date2015-07-15 10:58 +0100
Message-ID<mo5apb$1le$1@dont-email.me>
In reply to#65607
On 15/07/15 10:11, Tim Rentsch wrote:
> Richard Heathfield <rjh@cpax.org.uk> writes:
>
>> On 11/07/15 16:31, Tim Rentsch wrote:
>>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>>
>>>> The correct way to /print/ size_t values, however, is not %d,
>>>> but %zd.

[Aside: that should, of course, be %zu.]

>>>
>>> Isn't this contrary to your rule of limiting yourself
>>> to constructs common to C90, C99 and C11?  ;)
>>
>> My answer was posited on the basis that the code was C99 (because of
>> anonymous wossnames, which I incorrectly thought were not supported by
>> C90).  In writing what I would consider to be maximally portable code,
>> I would not use %z at all.  But, if (as I incorrectly thought) one is
>> using C99 anyway, one might as well take advantage of %z.
>
> Yes, I see that, and it's quite reasonable.  I was gently
> (I hoped) making fun of your position on which parts of
> C should be used, which seems to me more uncompromising
> than it should be.  Probably I shouldn't have - sorry
> about that.

For the avoidance of doubt, my uncompromising position relates to which 
parts of C *I* should use. I do not insist that the world follows my 
lead (although it is most welcome so to do if it chooses).

When people ask about maximally[1] portable solutions, naturally I throw 
my tuppence into the ring, but there are times (albeit not all that many 
of them) when I will take off my zealot hat and chip in to a C99- or 
C11-specific thread.

As for the gentle teasing, I don't mind that at all, and no apology is 
necessary. Them as dishes it out ought to be able to take it, and I 
certainly dish it out on occasion.

[1] well, *almost* maximally. Freestanding implementations are a kettle 
of a different colour.

-- 
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within

[toc] | [prev] | [next] | [standalone]


#66022

FromTim Rentsch <txr@alumni.caltech.edu>
Date2015-07-20 10:05 -0700
Message-ID<kfnfv4in4jd.fsf@x-alumni2.alumni.caltech.edu>
In reply to#65610
Richard Heathfield <rjh@cpax.org.uk> writes:

> On 15/07/15 10:11, Tim Rentsch wrote:
>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>
>>> On 11/07/15 16:31, Tim Rentsch wrote:
>>>> Richard Heathfield <rjh@cpax.org.uk> writes:
>>>>
>>>>> The correct way to /print/ size_t values, however, is not %d,
>>>>> but %zd.
>
> [Aside: that should, of course, be %zu.]
>
>>>> Isn't this contrary to your rule of limiting yourself
>>>> to constructs common to C90, C99 and C11?  ;)
>>>
>>> My answer was posited on the basis that the code was C99 (because of
>>> anonymous wossnames, which I incorrectly thought were not supported by
>>> C90).  In writing what I would consider to be maximally portable code,
>>> I would not use %z at all.  But, if (as I incorrectly thought) one is
>>> using C99 anyway, one might as well take advantage of %z.
>>
>> Yes, I see that, and it's quite reasonable.  I was gently
>> (I hoped) making fun of your position on which parts of
>> C should be used, which seems to me more uncompromising
>> than it should be.  Probably I shouldn't have - sorry
>> about that.
>
> [snip]
>
> As for the gentle teasing, I don't mind that at all, and no apology is
> necessary.  [snip]

I appreciate you taking it in good spirits.  Despite that, I
believe that it was not appropriate to indulge the impulse,
and will try to refrain from indulging similar impulses in
the future.

[toc] | [prev] | [next] | [standalone]


#63530

FromJames Kuyper <jameskuyper@verizon.net>
Date2015-06-18 12:26 -0400
Message-ID<5582F12D.3070708@verizon.net>
In reply to#63510
On 06/18/2015 09:45 AM, Rahul Kumar wrote:
> #include <stdio.h>
> 
> struct s
> {
> 	int a:4;
> 	char b:5;
> 	int c:7;
> 	unsigned f1:1;
> 	unsigned f2:24;
> 	unsigned :3;
> 	int :3;// anonymous b.f. -- not accessible
> 	int :0;	// significance -- align to next word boundary -- 47 bit < 64 bit -- align to 64 bit(8byte)
> 	unsigned f3:6;	// 70 bit
> 	unsigned :0; 	// ????? -- 96
> 	unsigned f4:8;	//104 -- 13 byte -- 16 byte size
> }x;
> 
> int main()
> {
> 	printf("%d\n",sizeof(x));
> }
> 
> how to calculate output of this program,please help me,i am just confused with it.

My first answer was correct, but not particularly detailed. I'll give
you some more details this time.

As Richard has already mentioned, a compiler is not required to accept a
bit-field of type 'char', so this code can only be ported to compilers
that accept that type.
A bit-field width is not allowed to exceed the size in bits of the
corresponding type. Therefore, the declaration of f2 is allowed only on
implementations where "unsigned int" has at least 24 bits.

It is implementation-defined whether a bit-field of type 'int' has a
signed or unsigned type. Since it's almost never a good idea to be
unsure whether a type is signed or unsigned, I recommend replacing "int"
with "signed int" (or, more simply, "signed") in all of the above member
declarations. The same is probably true for any implementation that
allows bit-fields of "char" type. I recommend explicitly declaring "b"
as either "signed char" or "unsigned char", depending upon what you
actually want it to be.

"There may be unnamed padding within a structure object, but not at its
beginning." (6.7.2.1p15). Note that there is no upper limit on the
amount of padding. This is the key thing that makes it impossible to
"calculate" the size of this struct.

In practice, most implementations will align a struct with the strictest
alignment of any of it's members, and align each individual member
according to the alignment requirements of it's type. They will
introduce padding between members only as needed to ensure correct
alignment. The size of a struct must be a multiple of alignment
requirement for the struct, and most implementations will put padding at
the end of a struct only if needed for that purpose. However, you
shouldn't write code that relies upon these things.

If you're using C2011, you can use _Alignof(type) to find out the
alignment requirements for a type, and you can use _Alignas() to impose
stricter alignment requirements on an object than would otherwise apply.
In older versions of C, the only way to find out about such things was
to read the documentation for the compiler.

6.7.2.1p11 says:
> An implementation may allocate any addressable storage unit large enough to hold a bitfield.
> If enough space remains, a bit-field that immediately follows another bit-field in a
> structure shall be packed into adjacent bits of the same unit. If insufficient space remains,
> whether a bit-field that does not fit is put into the next unit or overlaps adjacent units is
> implementation-defined. The order of allocation of bit-fields within a unit (high-order to
> low-order or low-order to high-order) is implementation-defined. The alignment of the
> addressable storage unit is unspecified.

Note that this implies that padding bytes are not permitted between
addressable storage units (ASU). If there's enough space to put the next
bit-field in the same ASU as the previous one, it must be put there. If
there isn't enough room, the implementation has a choice, but only
between two options: a) putting part of the bit-field in the same ASU,
and the rest of it in the next one or b) putting it entirely in the next
ASU. Either way, there's no room for padding bytes between the ASUs.
There might be more than CHAR_BIT consecutive padding bits within an
ASU, but only if the next struct member is not a bit-field small enough
to fit in the available bits.

Because the implementation does get to make that choice, and also
because it gets to choose the size and alignment requirements of the
ASU, there's still considerable freedom for different implementations to
give different sizes to the same struct, even if every member is
bit-field, even though that means that padding bytes between members are
not allowed.

Finally, even if the size of the struct in bits were completely
specified, the value returned by "sizeof x" would depend upon the value
of CHAR_BIT from <limits.h>.

The comments in the struct imply that it was written by someone who
knows about 6.7.2.1p12 - but if it wasn't written by you, you might need
to know this in order to understand what they wrote:

"A bit-field declaration with no declarator, but only a colon and a
width, indicates an unnamed bit-field. As a special case, a bit-field
structure member with a width of 0 indicates that no further bit-field
is to be packed into the unit in which the previous bitfield,
if any, was placed."

Lets examine one of the possibilities. Assume that the ASU has a size
and alignment requirement of 16, and that bit fields which don't fit
always are allocated to the next ASU. Then:

The first ASU will contain a(4 bits) b(5 bits) and c(7 bits). The order
of these fields within the ASU is unspecified.
The next ASU will contain only f1.
f2(24 bits) will be split between the third and fourth ASUs, followed by
the two unnamed bit-fields (3 bits each). How much of f2 will be placed
in the first ASU is unspecified - it could be as little as 14 bits, or
as much as 16 bits. Having two consecutive unnamed bit-fields seems odd
to me. It's not entirely pointless - whether those fields will be split
up or put in the same ASU will depend upon the size of the ASU.
f3(6 bits) will be put in the fifth ASU, and because of the bit-field
with a length of 0, f4(8 bits) will have to be put in the sixth
bit-field, for a total size of 6 ASUs * 16 bits/ASU = 96 bits. If
CHAR_BIT == 8, then sizeof(x) will be 12.

Note that this layout is inconsistent with the comments in the code. I
suspect that those comments were based upon the assumption that the ASU
had a size of 32 bits, rather than 16, neatly demonstrating why there's
no single answer to your question.

[toc] | [prev] | [next] | [standalone]


#63533

FromKeith Thompson <kst-u@mib.org>
Date2015-06-18 10:14 -0700
Message-ID<ln7fr1j5vr.fsf@nuthaus.mib.org>
In reply to#63530
James Kuyper <jameskuyper@verizon.net> writes:
> On 06/18/2015 09:45 AM, Rahul Kumar wrote:
>> #include <stdio.h>
>> 
>> struct s
>> {
>> 	int a:4;
>> 	char b:5;
>> 	int c:7;
>> 	unsigned f1:1;
>> 	unsigned f2:24;
>> 	unsigned :3;
>> 	int :3;// anonymous b.f. -- not accessible
>> 	int :0;	// significance -- align to next word boundary -- 47 bit < 64 bit -- align to 64 bit(8byte)
>> 	unsigned f3:6;	// 70 bit
>> 	unsigned :0; 	// ????? -- 96
>> 	unsigned f4:8;	//104 -- 13 byte -- 16 byte size
>> }x;
>> 
>> int main()
>> {
>> 	printf("%d\n",sizeof(x));
>> }
>> 
>> how to calculate output of this program,please help me,i am just confused with it.
>
> My first answer was correct, but not particularly detailed. I'll give
> you some more details this time.
>
> As Richard has already mentioned, a compiler is not required to accept a
> bit-field of type 'char', so this code can only be ported to compilers
> that accept that type.
> A bit-field width is not allowed to exceed the size in bits of the
> corresponding type. Therefore, the declaration of f2 is allowed only on
> implementations where "unsigned int" has at least 24 bits.

Another complication: the type of a bit field can the layout of the
containing structure, even for bit fields of the same size.  Some
ABIs require this, though there's no hint of it in the C standard.

For example, on my system this program:

    #include <stdio.h>
    int main(void) {
        struct s1 { unsigned char      bf:1; };
        struct s2 { unsigned short     bf:1; };
        struct s3 { unsigned int       bf:1; };
        struct s4 { unsigned long      bf:1; };
        struct s5 { unsigned long long bf:1; };
        printf("%zu %zu %zu %zu %zu\n",
               sizeof (struct s1),
               sizeof (struct s2),
               sizeof (struct s3),
               sizeof (struct s4),
               sizeof (struct s5));
    }

produces this output:

    1 2 4 8 8

Of course the output, and even the legality of the program itself, are
implementation-defined, and the actual output is within the bounds of
what the standard permits.

> It is implementation-defined whether a bit-field of type 'int' has a
> signed or unsigned type. Since it's almost never a good idea to be
> unsure whether a type is signed or unsigned, I recommend replacing "int"
> with "signed int" (or, more simply, "signed") in all of the above member
> declarations. The same is probably true for any implementation that
> allows bit-fields of "char" type. I recommend explicitly declaring "b"
> as either "signed char" or "unsigned char", depending upon what you
> actually want it to be.

It probably doesn't matter whether an anonymous bit field is signed
or unsigned, but yes, specifying `unsigned int` or `signed int`
rather than just `int` is a good habit.  Most bit fields should
probably be unsigned, but it depends on what they're used for.

[...]

-- 
Keith Thompson (The_Other_Keith) kst-u@mib.org  <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something.  This is something.  Therefore, we must do this."
    -- Antony Jay and Jonathan Lynn, "Yes Minister"

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web