Role of __WORDSIZE in compilation - c

Below are the contents of /usr/include/x86_64-linux-gnu/gnu/stubs-32.h file:
#include <bits/wordsize.h>
#if __WORDSIZE == 32
# include <gnu/stubs-32.h>
#elif __WORDSIZE == 64
# include <gnu/stubs-64.h>
#else
# error "unexpected value for __WORDSIZE macro"
#endif
I am on 64 Bit machine, so the result of
#include<stdio.h>
main()
{
printf("Word size : %d\n",__WORDSIZE);
}
is
Word size : 64
So here is the question, what is the role of the system variable __WORDSIZE?
I am developing a 32 bit application( using mingw 32 bit compiler) and since my __WORDSIZE is 64 bit, the file /usr/include/x86_64-linux-gnu/gnu/stubs-32.h ultimately results in including /usr/include/x86_64-linux-gnu/gnu/stubs-64.h. I am confused about this part. What are the consequences of this action? Is this normal and if not how can I forcibly include /usr/include/x86_64-linux-gnu/gnu/stubs-32.h?
Thank You in advance.

It is a manifest constant, intended for internal use by the compiler implementation exclusively; that its name is prefixed by two underscores is a clear indicator that it is not intended for use in user space.

Related

C error: missing binary operator before token

I'm working on building a custom version of openwrt with a build tool and keep running into a error I cant seem to fix.
heres the code block its dating back to.
#include <signal.h>
#if ! HAVE_STACK_T && ! defined stack_t
typedef struct sigaltstack stack_t;
#endif
#ifndef SIGSTKSZ
# define SIGSTKSZ 16384
#elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384
/* libsigsegv 2.6 through 2.8 have a bug where some architectures use
more than the Linux default of an 8k alternate stack when deciding
if a fault was caused by stack overflow. */
# undef SIGSTKSZ
# define SIGSTKSZ 16384
#endif
heres the out put error
In file included from /usr/include/signal.h:328,
from ./signal.h:52,
from c-stack.c:49:
c-stack.c:55:26: error: missing binary operator before token "("
55 | #elif HAVE_LIBSIGSEGV && SIGSTKSZ < 16384
| ^~~~~~~~
First of all please note that this is not standard C but POSIX extensions. POSIX has the nasty habit of poisoning standard libraries with non-standard, non-conforming extensions.
This means that if you compile with -std=c17 or equivalent instead of -std=gnu17 (default), gcc will strip off all non-standard, non-conforming POSIX junk. And then those things will not be found at all even if you include signal.h, which in turn can give you very confusing compiler errors.
That being said, I think you perhaps meant to do:
#elif defined(HAVE_LIBSIGSEGV) && SIGSTKSZ < 16384
As for how you can find out what SIGSTKSZ is without digging through some library header, here's a simple trick that gives you the exact macro definition:
#include <stdio.h>
#include <signal.h>
#define STR(s) #s
#define WHAT_ARE_YOU(x) puts(STR(x))
int main (void)
{
WHAT_ARE_YOU(SIGSTKSZ);
}
When compiling as GNU C on some random Linux machine, I get 8192.
You could also do gcc -E to view the preprocessor output (which may be a bit confusing to read since it expands all headers). Doing that for the above example gives puts("8192");.

CHAR_WIDTH undeclared

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.
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).

C preprocessor macro

The problem:
I'm writing a general C library for an LCD in a microcontroller project.
up to 8 LCDs with various sizes(e.g. 128*96 or 64*48) in various addresses may be added (e.g. LCD3 and LCD7). but only one of them is actively coded at a time. so I thought for a mechanism to do so.
in the code, there is a definition for CLCD_ROWS and CLCD_COLS which correspond to the Active display size.
#define CLCD_ROWS // Active LCD rows
#define CLCD_COLS // Active LCD columns
and there's definitions for the various LCDs. for example, if we have LCD3 and LCD7 connected, we define their sizes with :
#define CLCD_ROWS3 96
#define CLCD_COLS3 64
#define CLCD_ROWS7 128
#define CLCD_COLS7 32
The question:
I've written a [wrong] macro to redefine the values of CLCD_ROWS and CLCD_COLS :
#define cLcd_setActiveI2CcLcd(X) \
CLCD_ROWS = CLCD_ROWS##X \
CLCD_COLS = CLCD_COLS##X
and in my main code I call the macro:
cLcd_setActiveI2CcLcd(7);
which gives me an error of "missing ;".
it is easy to implement it with variables. but since these values are hardcoded , I thought they are "preprocessable" since need every bit of RAM in a low end MCU.
Is my approach about preprocessing this values, correct ?
What is the right way to write a macro for that purpose ?
I'm using a C99 compiler.
First things first, your method of using function-type macro is wrong. Even if you fix the error you have, the macro will not do CLCD_ROWS equal to CLCD_ROWS7, but to CLCD_ROWSX (that is how macros work, it concatenates the thing you give, not its value). Instead if you want to use macros for reducing RAM usage you can change your code to:
1st Solution
#define ROW_COLS 7 // change this if you use different display
#if ROW_COLS == 7
#define CLCD_ROWS 128
#define CLCD_COLS 32
#elif ROW_COLS == 3
#define CLCD_ROWS 96
#define CLCD_COLS 64
#endif
2nd Solution
If you want dynamically change the size of your display in the runtime, you can do it like this:
static int display_cnt;
#define CLCD_ROWS ((display_cnt == 3) ? 96 : 128)
#define CLCD_COLS ((display_cnt == 3) ? 64 : 32)
So when you change the value of display_cnt variable, the macro will automatically change its value.

Is it possible to output a variable from a header file?

Suppose I have a header file with lines like this:
#if LONG_BIT != 8 * SIZEOF_LONG
/* 04-Oct-2000 LONG_BIT is apparently (mis)defined as 64 on some recent
* 32-bit platforms using gcc. We try to catch that here at compile-time
* rather than waiting for integer multiplication to trigger bogus
* overflows.
*/
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?)."
#endif
I would like to output the value of LONG_BIT and SIZEOF_LONG. Is it possible to do this, or is that impossible from a header file?
_Static_assert in C or static_assert in C++ can test conditions and display a string, and the string can be constructed with preprocessor expansions:
#define LONG_BIT 64
#define SIZEOF_LONG 4
#define StringizeHelper(x) #x
#define Stringize(x) StringizeHelper(x)
_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
"LONG_BIT is " Stringize(LONG_BIT) " but must be 8 * "
Stringize(SIZEOF_LONG) ".");
Output with Clang:
x.c:7:1: error: static_assert failed "LONG_BIT is 64 but must be 8 * 4."
_Static_assert(LONG_BIT == 8 * SIZEOF_LONG,
^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
1 error generated.
You have a few values to test in that case. You could test the plausible ones one by one like a switch/case statement, with a default just in case.
Standalone example. The 2 first define statements are here for the test, remove from final code
// completely bogus/incoherent values just to test
#define LONG_BIT 32
#define SIZEOF_LONG 4444
// operational test from now on
#if LONG_BIT != 8 * SIZEOF_LONG
#if LONG_BIT == 32
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size 32"
#elif LONG_BIT == 64
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size 64"
#else
#error "pp897: LONG_BIT definition appears wrong for platform (bad gcc/glibc config?): size ???"
#endif
#endif
compilation output:
test.c:7:2: error: #error "pp897: LONG_BIT definition appears wrong for platfo
rm (bad gcc/glibc config?): size 32"
This method is compatible with all standards including C89
With GCC or Clang (at least), you can print out the values of preprocessor macros:
#define LONG_BIT 60
#pragma message "LONG_BIT is " STRINGIFY(LONG_BIT)
But that won't get you the value of sizeof(long), which is not a preprocessor construct. It also won't do arithmetic; LONG_BIT needs to be an actual number for that to produce the desired message.
That doesn't work with #error, which doesn't do macro substitutions in the text.
Here, STRINGIFY has the usual two-stage definition:
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
You can also write the whole message inside the arguments, at least in this case, but watch out for unexpected expansions:
#pragma message STRINGIFY(LONG BIT is LONG_BIT)

How to convert between a dev_t and major/minor device numbers?

I'm trying to write a portable program that deals with ustar archives. For device files, these archives store the major and minor device numbers. However, the struct stat as laid out in POSIX only contains a single st_rdev member of type dev_t described with “Device ID (if file is character or block special).”
How can I convert between a pair of major and minor device numbers and a single st_rdev member as returned by stat() in a portable manner?
While all POSIX programming interfaces use the device number (of type dev_t) as is, FUZxxl pointed out in a comment to this answer that the common UStar file format -- most common tar archive format -- does split the device number into major and minor. (They are typically encoded as seven octal digits each, so for compatibility reasons one should limit to 21-bit unsigned major and 21-bit unsigned minor. This also means that mapping the device number to just the major or just the minor is not a reliable approach.)
The following include file expanding on Jonathon Reinhart's answer, after digging on the web for the various systems man pages and documentation (for makedev(), major(), and minor()), plus comments to this question.
#if defined(custom_makedev) && defined(custom_major) && defined(custom_minor)
/* Already defined */
#else
#undef custom_makedev
#undef custom_major
#undef custom_minor
#if defined(__linux__) || defined(__GLIBC__)
/* Linux, Android, and other systems using GNU C library */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#elif defined(_WIN32)
/* 32- and 64-bit Windows. VERIFY: These are just a guess! */
#define custom_makedev(dmajor, dminor) ((((unsigned int)dmajor << 8) & 0xFF00U) | ((unsigned int)dminor & 0xFFFF00FFU))
#define custom_major(devnum) (((unsigned int)devnum & 0xFF00U) >> 8)
#define custom_minor(devnum) ((unsigned int)devnum & 0xFFFF00FFU)
#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
/* FreeBSD, OpenBSD, NetBSD, and DragonFlyBSD */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#elif defined(__APPLE__) && defined(__MACH__)
/* Mac OS X */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#elif defined(_AIX) || defined (__osf__)
/* AIX, OSF/1, Tru64 Unix */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#elif defined(hpux)
/* HP-UX */
#include <sys/sysmacros.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#elif defined(sun)
/* Solaris */
#include <sys/types.h>
#include <sys/mkdev.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#else
/* Unknown OS. Try a the BSD approach. */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <sys/types.h>
#if defined(makedev) && defined(major) && defined(minor)
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#endif
#endif
#if !defined(custom_makedev) || !defined(custom_major) || !defined(custom_minor)
#error Unknown OS: please add definitions for custom_makedev(), custom_major(), and custom_minor(), for device number major/minor handling.
#endif
#endif
One could glean additional definitions from existing UStar-format -capable archivers. Compatibility with existing implementations on each OS/architecture is, in my opinion, the most important thing here.
The above should cover all systems using GNU C library, Linux (including Android), FreeBSD, OpenBSD, NetBSD, DragonFlyBSD, Mac OS X, AIX, Tru64, HP-UX, and Solaris, plus any that define the macros when <sys/types.h> is included. Of the Windows part, I'm not sure.
As I understand it, Windows uses device 0 for all normal files, and a HANDLE (a void pointer type) for devices. I am not at all sure whether the above logic is sane on Windows, but many older systems put the 8 least significant bits of the device number into minor, and the next 8 bits into major, and the convention seems to be that any leftover bits would be put (without shifting) into minor, too. Examining existing UStar-format tar archives with references to devices would be useful, but I personally do not use Windows at all.
If a system is not detected, and the system does not use the BSD-style inclusion for defining the macros, the above will error out stopping the compilation. (I would personally add compile-time machinery that could help finding the correct header definitions, using e.g. find, xargs, and grep, in case that happens, with a suggestion to send the addition upstream, too. touch empty.h ; cpp -dM empty.h ; rm -f empty.h should show all predefined macros, to help with identifying the OS and/or C library.)
Originally, POSIX stated that dev_t must be an arithmetic type (thus, theoretically, it might have been some variant of float or double on some systems), but IEEE Std 1003.1, 2013 Edition says it must be an integer type. I would wager that means no known POSIX-y system ever used a floating-point dev_t type. It would seem that Windows uses a void pointer, or HANDLE type, but Windows is not POSIX-compliant anyway.
Use the major() and minor() macros after defining BSD_SOURCE.
The makedev(), major(), and minor() functions are not specified in
POSIX.1, but are present on many other systems.
http://man7.org/linux/man-pages/man3/major.3.html
I have a program based on an antique version of ls for Minix, but much mangled modified by me since then. It has the following code to detect the major and minor macros — and some comments about (now) antique systems where it has worked in the past. It assumes a sufficiently recent version of GCC is available to support #pragma GCC diagnostic ignored etc. You have to be trying pretty hard (e.g. clang -Weverything) to get the -Wunused-macros option in effect unless you include it explicitly.
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-macros"
/* Defines to ensure major and minor macros are available */
#define _DARWIN_C_SOURCE /* In <sys/types.h> on MacOS X */
#define _BSD_SOURCE /* In <sys/sysmacros.h> via <sys/types.h> on Linux (Ubuntu 12.0.4) */
#define __EXTENSIONS__ /* Maybe beneficial on Solaris */
#pragma GCC diagnostic pop
/* From Solaris 2.6 sys/sysmacros.h
**
** WARNING: The device number macros defined here should not be used by
** device drivers or user software. [...] Application software should make
** use of the library routines available in makedev(3). [...] Macro
** routines bmajor(), major(), minor(), emajor(), eminor(), and makedev()
** will be removed or their definitions changed at the next major release
** following SVR4.
**
** #define O_BITSMAJOR 7 -- # of SVR3 major device bits
** #define O_BITSMINOR 8 -- # of SVR3 minor device bits
** #define O_MAXMAJ 0x7f -- SVR3 max major value
** #define O_MAXMIN 0xff -- SVR3 max major value
**
** #define L_BITSMAJOR 14 -- # of SVR4 major device bits
** #define L_BITSMINOR 18 -- # of SVR4 minor device bits
** #define L_MAXMAJ 0x3fff -- SVR4 max major value
** #define L_MAXMIN 0x3ffff -- MAX minor for 3b2 software drivers.
** -- For 3b2 hardware devices the minor is restricted to 256 (0-255)
*/
/* AC_HEADER_MAJOR:
** - defines MAJOR_IN_MKDEV if found in sys/mkdev.h
** - defines MAJOR_IN_SYSMACROS if found in sys/macros.h
** - otherwise, hope they are in sys/types.h
*/
#if defined MAJOR_IN_MKDEV
#include <sys/mkdev.h>
#elif defined MAJOR_IN_SYSMACROS
#include <sys/sysmacros.h>
#elif defined(MAJOR_MINOR_MACROS_IN_SYS_TYPES_H)
/* MacOS X 10.2 - for example */
/* MacOS X 10.5 requires -D_DARWIN_C_SOURCE or -U_POSIX_C_SOURCE - see above */
#elif defined(USE_CLASSIC_MAJOR_MINOR_MACROS)
#define major(x) ((x>>8) & 0x7F)
#define minor(x) (x & 0xFF)
#else
/* Hope the macros are in <sys/types.h> or otherwise magically visible */
#endif
#define MAJOR(x) ((long)major(x))
#define MINOR(x) ((long)minor(x))
You will justifiably not be all that keen on the 'hope the macros are … magically visible' part of the code.
The reference to AC_HEADER_MAJOR is to the macro in the autoconf that deduces this information. It would be relevant if you have a config.h file generated by autoconf.
POSIX
Note that the POSIX pax command defines the ustar format and specifies that it includes devmajor and devminor in the information, but adds:
… Represent character special files and block special files respectively. In this case the devmajor and devminor fields shall contain information defining the device, the format of which is unspecified by this volume of POSIX.1-2008. Implementations may map the device specifications to their own local specification or may ignore the entry.
This means that there isn't a fully portable way to represent the numbers. This is not wholly unreasonable (but it is a nuisance); the meanings of the major and minor device numbers varies across platforms and is unspecified too. Any attempt to create block or character devices via ustar format will only work reasonably reliably if the source and target machines are running the same (version of the same) operating system — though usually they're portable across versions of the same operating system.

Resources