Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CHAR_WIDTH undeclared

Tags:

c

gcc

I get the error ‘CHAR_WIDTH’ undeclared when I try to compile this simple program:

#include <stdio.h>
#include <limits.h>

int main()
{
  printf("CHAR_BIT = %d\n", CHAR_BIT);
  printf("CHAR_WIDTH = %d\n", CHAR_WIDTH);
  return (0);
}

with

gcc ./show_char_width.c -o show_char_width

and gcc: GNU C17 (Ubuntu 8.3.0-6ubuntu1) version 8.3.0 (x86_64-linux-gnu) compiled by GNU C version 8.3.0, GMP version 6.1.2, MPFR version 4.0.2, MPC version 1.1.0, isl version isl-0.20-GMP, kernel: 5.0.0-37-generic.

As stated here CHAR_WIDTH should be defined in limits.h which is included in my program. So why I get this error?

With the -v option I found that the library will be searched in those directories:

#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/8/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/8/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include

/usr/lib/gcc/x86_64-linux-gnu/8/include-fixed contain a limits.h that include syslimits.h from the same dir which in turn include the next limits.h, that from my understanding should be located in the /usr/include directory.

The CHAR_WIDTH macro is indeed defined in those files but under some conditions that exceed my actual knowledge.

The conditions I found untill now are:


/* The integer width macros are not defined by GCC's <limits.h> before
   GCC 7, or if _GNU_SOURCE rather than
   __STDC_WANT_IEC_60559_BFP_EXT__ is used to enable this feature.  */
#if __GLIBC_USE (IEC_60559_BFP_EXT)
# ifndef CHAR_WIDTH
#  define CHAR_WIDTH 8
# endif

and :

#ifdef __STDC_WANT_IEC_60559_BFP_EXT__
/* TS 18661-1 widths of integer types.  */
# undef CHAR_WIDTH
# define CHAR_WIDTH __SCHAR_WIDTH__

That's why I need your help.

Note: I get the same error with all other macros described in A.5.1 notably: SCHAR_WIDTH, INT_WIDTH, LONG_WIDTH, etc.

like image 533
pliski Avatar asked Dec 06 '19 11:12

pliski


1 Answers

CHAR_WIDTH isn't standard, nor are any other *_WIDTH macros, but the width of a character type must be the same as CHAR_BIT anyway*.

As for *_WIDTH macros in general, they aren't strictly needed as they are compile-time-computable from the maximum value of the corresponding unsigned type, i.e., you can have a #define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax) that expands to an integer constant expression that's also usable in preprocessor conditionals (#if), though implementations are a little bit obscure (see Is there any way to compute the width of an integer type at compile-time?), e.g.:

#define WIDTH_FROM_UNSIGNED_MAX(UnsignedMax) POW2_MINUS1_BITS_2039(UnsignedMax)
/* Number of bits in inttype_MAX, or in any (1<<k)-1 where 0 <= k < 2040 */
#define POW2_MINUS1_BITS_2039(X) ((X)/((X)%255+1) / 255%255*8 + 7-86/((X)%255+12))

//compile-time test it, assuming uint{8,16,32,64}_t exist
#include <inttypes.h>
#if WIDTH_FROM_UNSIGNED_MAX(UINT8_MAX) != 8
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT16_MAX) != 16
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT32_MAX) != 32
    #error
#endif
#if WIDTH_FROM_UNSIGNED_MAX(UINT64_MAX) != 64
    #error
#endif

Some people just do CHAR_BIT * sizeof(integer_type), but that isn't strictly portable, because it assumes integer_type doesn't have padding bits (it usually doesn't but theoretically it can have them), and can't use it in #if conditionals either.


*Unfortunately, to glean this info, you need jump all over the standard:

The width of an integer type is (slightly indirectly) defined as the number of its nonpadding bits (6.2.6.2p6).

6.2.6.2p2 says signed char doesn't have any padding bits. Because of how integers can be represented in C (6.2.6.2p2), that implies unsigned char can't have any padding bits either, and since char must have the same limits as either signed char or unsigned char (5.2.4.2.1p2) while having the same sizeof value (namely 1, 6.5.3.4p4), a plain char can't have any padding bits either, and so CHAR_BIT == width of (char|signed char|unsigned char).

like image 143
PSkocik Avatar answered Nov 16 '22 01:11

PSkocik