Is "unix" restricted keyword in C? - c

This code does not compile for me on GCC version 4.3.2 (Debian 4.3.2-1.1)
main() {
int unix;
}
I've checked the C keywords list and "unix" is not one of them.
Why am I getting the following error?
unix.c:2: error: expected identifier or ‘(’ before numeric constant

unix is not a identifier reserved by the Standard.
If you compile with -std=c89 or -std=c99 the gcc compiler will accept the program as you expected.
From gcc manual ( https://gcc.gnu.org/onlinedocs/cpp/System-specific-Predefined-Macros.html ), the emphasis is mine.
... However,
historically system-specific macros
have had names with no special prefix;
for instance, it is common to find
unix defined on Unix systems. For all
such macros, GCC provides a parallel
macro with two underscores added at
the beginning and the end. If unix is
defined, __unix__ will be defined too.
There will never be more than two
underscores; the parallel of _mips is
__mips__.

unix is one of the defines the preprocessor uses in gcc
to get a list of defs use
gcc -dM -E -x c /dev/null
(-dM tells gcc to debugdump the defs -E tells it to stop after prepreocessing and -x c /dev/null tells him to pretend /dev/null is a c file)

Run your code through the preprocessor to find out what the compiler is actually seeing:
gcc -E unix.c
Then see if your variable unix is preserved or converted by the preprocessor.

It is not a keyword.
It is a predefined macro to identify the type of system. On Unix and Unix like systems it is defined to be 1.
To disable this use the -ansi option:
In C mode, this is equivalent to -std=c89. In C++ mode, it is equivalent to -std=c++98.
This turns off certain features of GCC that are incompatible with ISO C90 (when compiling C code), or of standard C++ (when compiling C++ code), such as the "asm" and "typeof" keywords, and predefined macros such as "unix" and "vax" that identify the type of system you are using. It also enables the undesirable and rarely used ISO trigraph feature. For the C compiler, it disables recognition of C++ style // comments as well as the "inline" keyword.

I'm gona take a wild stab at this and guess that gcc effectively #defined unix as 1 on UNIX systems.
try
main(){
printf("%d", unix);
}
and see what you get.

To answer your question, no unix is not a reserved word in C.
However, the symbol unix is most likely defined by the preprocessor either because you include a header file or because the compiler defines it.

Related

How to include -D_POSIX_C_SOURCE=200809 when you compile the code

I am doing an assignment which states: "The skeleton code given uses getopt. If you compile the code with -std=c99, there will be compilation
error. To fix the error, include -D_POSIX_C_SOURCE=200809 when you compile the code."
I am very new to this. Ordinarily I compile a C program with GCC (program name) and then I type ./a.out.
What am I required to do here?
The sentence “To fix the error, include -D_POSIX_C_SOURCE=200809 when you compile the code” means to include the characters -D_POSIX_C_SOURCE=200809 in the command you use to compile the program.
For example, if you normally use gcc -o foo foo.c, change it to gcc -o foo -D_POSIX_C_SOURCE=200809 foo.c.
This is a command line argument that tells the compiler to define a preprocessor macro named _POSIX_C_SOURCE to be replaced by 200809. This preprocessor macro is used by various header files to adapt to different versions of POSIX (by using #if statements to test the macro). For example, if you specify _POSIX_C_SOURCE to be 200809 or leave it undefined, the headers will not declare routines that were only added to POSIX after the 2008-09 version of POSIX. Among other things, this avoids causing conflicts with programs written before then that might have happened to use names of those routines for other purposes (since they would have had no way of knowing what names POSIX header would define in the future).
You can also define the macro in your source code, before any headers that use it are included, with:
#define _POSIX_C_SOURCE 200809
The getopt function is a relatively recent addition to the Single UNIX Specification/POSIX Standard. While Linux doesn't comply with POSIX, it does roughly use this standard as a reference point. However, it's mostly implementing XSH (System Headers) of POSIX '03 or earlier by default for compatibility. If you want more recent additions exposed (Note: #JonathanLeffler mentions that getopt is there for quite some time already, but Linux doesn't expose it by default anyway), you can tell the GNU libc (the C Library commonly used on GNU/Linux systems) to also provide some of that functionality which are hidden behind Feature Test Macros. Lookup the man-page man -s 7 feature_test_macros 2 in combination with man -s 3 getopt 1 for more. Basically, in the respective headers there's some code similar to the following:
#if _POSIX_C_SOURCE >= 200809L
/* declaration of getopt() and other newer functions */
#endif
If you then include that file and do not define the feature test macro to have a value greater than (newer/more recent than) the date of that POSIX standard you need (2008-09), the C Preprocessor will throw away all those forward declarations, making your code error out.
Using -DFOO=bar you #define FOO bar on the command line for the standard C Compiler. By the way, the GNU C Compiler also sets some of such flags when you use -std=c99.
In the end, your command line should look more or less like this:
$ c99 -D_POSIX_C_SOURCE=200809L -o foo foo.c
This will compile and link foo.c to the output file foo adhering to the C99 standard and using features from POSIX '08 3.

getchar_unlocked() implicit declaration in C99

Using getchar_unlocked and compiling with --std=c99 flag gives warningas follows-
warning: implicit declaration of function ‘getchar_unlocked’ [-Wimplicit-function-declaration]
Does not give any warning if compiled without flag.Is there any way to work around with it ?
Starting from C99 you must have a visible function prototype before calling a function. While the earlier C standard would just stupidly assume that any function unknown to the compiler has the format int func (params), which in turn would cause severe bugs most of the time.
Properly declare a prototype for getchar_unlocked and the bug will go away.
Note that there is no such function present in any standard library. It seems you might have to include some non-standard library for the compiler to find the function.
_unlocked versions of get... functions are POSIX extensions. They are not part of the standard functions of C99. The full list of get... functions is given in 7.19.1.5: getwc, getwchar, getc, getchar, and gets (deprecated).
When the function is not on this list, C99-compliant compiler must warn you that your program may not compile with other C99-compliant compilers.
Dialect selection options like -ansi and -std=c99 cause the compiler to define certain macros (in addition to altering the accepted dialect).
Library header files react to those macros.
Precisely how they react is quite system-dependent (the compiler doesn't provide a C library), but a common behavior you can broadly expect is that if you use one of these flags alone (without any other "feature selection macro"), it has the effect of hiding the declarations of functions, macros and other global symbols which are not in the specified ISO C dialect.
ISO C knows nothing about getchar_unlocked. The presence of such a declaration in <stdio.h> (normally an ISO C header) is a POSIX extension, which is basically nonconforming, since getchar_unlocked is an identifier that strictly conforming C programs can use, even if they include <stdio.h>. When you use -ansi or -std=c99, the <stdio.h> header listens up and whips itself into ISO-C-conforming shape, hiding such extensions.
On well-behaved POSIX systems, you can request that you want an ISO C dialect and that you want certain rudimentary 1990-ish POSIX features to be visible in header files, for instance like this:
gcc -std=c99 -D_POSIX_SOURCE ...
^^^^^ "feature selection macro"
There is a whole science to these feature selection macros, too broad for this question and answer; some forms of them have values, like -D_XOPEN_SOURCE=500. _POSIX_SOURCE doesn't need an argument; it is just defined or not, but _POSIX_C_SOURCE is numeric.
I just checked glibc and Cygwin: on both, _POSIX_SOURCE is enough to reveal the getchar_unlocked declaration. It is quite old, dating back to POSIX.1 1996.
Beware: on some systems, multiple feature selection macros don't play along reasonably; they give you a set intersection rather than union, so that -D_POSIX_SOURCE and -D_BSD_SOURCE together end up meaning "Declare to me only those handful of functions that are specific to classic BSD that have been standardized in POSIX too", which means that next to nothing is declared.
getchar_unlocked is not a C standard function.
Compiling it forcing c99 standard does not support it natively.

What is the difference between the "c99" and "gcc" commands with appropriate flags?

Up until today I always read on the Internet how gcc is the best compiler for C (at least for the student level of programing, followed closely by Clang).
However in "21st Century C" Mr Ben Klemens suggests that c99 is better(?) than running gcc -std=c99 (actual line is [page 11]: everybody else switched to C99 being the default a long
time ago...)
I wasn't able to find anything on the subject of c99 compiler, so my question is:
Is there any difference between those commands and if there are, which one is better?
EDIT: The standard C99 is clearly metioned in the paragraph, however from the beginning the suggested method of compiling is the command:
gcc erf.c -o erf -lm -g -Wall -O3 -std=gnu11
However on page 11 the author states:
The POSIX standard specifies that c99 be present on your system, so the
compiler-agnostic version of the above line would be:
c99 erf.c -o erf -lm -g -Wall -O3
This seems to suggest there is a difference in those 2 commands. I wasn't able to find any additional info nor was it clear to me from the text, what the second line is exactly (no man page for c99 on my Cygwin either).
C99 is the 1999 edition of the ISO C standard. It replaced the 1990 standard, and has been (officially, at least) replaced by the 2011 standard.
What you're asking about, though, is the c99 command (I've updated your question's title to clarify that).
POSIX specifies a c99 command. The requirements are documented here. It is "an interface to the standard C compilation system".
On typical Linux systems, the c99 command /usr/bin/c99 is a small shell script that invokes the gcc commmand. It invokes gcc with the -std=c99 option. It also checks whether the user has already specified an equivalent option, so it doesn't use the same option twice. If an incompatible option has been given, such as c99 -std=c90, it terminates with an error message.
Given such an implementation, the command
c99 [args]
is exactly equivalent to
gcc -std=c99 [args]
As I mentioned above, the C99 standard has been officially superseded by the C11 standard. gcc version 5 (the current latest release is 5.3.1) has reasonably good support but not 100% complete support for C11. POSIX has not (yet) specified a c11 command.
There's nothing wrong with using the C99 standard if you don't need C11-specific features -- or even the C90 standard if you don't need C99-specific features.
In my PDF copy of the book, the discussion about using c99 instead of gcc -std=c99 seems to be on page 10, not 11.
And what is being discussed is not that c99 is "better" than gcc, but that you might be able to more easily use C99-standard compiler features with the c99 command, since you don't then need to know the specific option to enable C99 features or whether the default for the compiler is C99 or C89.
On my system, the command c99 is just an alias or link for gcc that has the -std=c99 set by default (and complains if a non-C99 standard is specified with the -std= option). I imagine that or something similar is true on most systems with a c99 compiler command.
In fact, on my system c99 is a link to a shell script:
#! /bin/sh
# Call the appropriate C compiler with options to accept ANSI/ISO C
# The following options are the same (as of gcc-3.3):
# -std=c99
# -std=c9x
# -std=iso9899:1999
# -std=iso9899:199x
extra_flag=-std=c99
for i; do
case "$i" in
-std=c9[9x]|-std=iso9899:199[9x])
extra_flag=
;;
-std=*|-ansi)
echo >&2 "`basename $0` called with non ISO C99 option $i"
exit 1
;;
esac
done
exec gcc $extra_flag ${1+"$#"}
Try c99 --version on a typical Linux box. You will get the version and name of the compiler which is gcc.
c99 is just a shortcut to the c99 compliant compiler on your machine. That way you don't have to care about the actual compiler used. POSIX also requires some common command line options the compiler has to understand. If that is gcc, it shall enable c99 compliant features. This should be identical to gcc -std=c99.
gcc provides additional features which are enabled by default [1] when called by its native name and by the -std=gccXX option in addition to the CXX standard. For older versions, some of these extensions became part of the next C standard either directly or with slightly different syntax. A typical and appreciated extension for C90 is support for C++-style line-comments:
// this is not allowed in pure C90
For c99/gnu99 things are less obvious, but might still add some usefull features.
On other POSIX systems, e.g. Unix, you may find a different compiler. It shall still be available by the name c99.
Note that the current and only valid C standard is C11 since 2011. So if you want to use the new features (e.g. atomics, thread-support), you have to deviate from the pure POSIX-path. Yet it is likely POSIX might be updated some day.
[1] The default version of the C standard depends on the version of gcc. pre5 used C90, while gcc 5.x uses C11.

GCC options for strict C90 code?

I am trying to find what is the combination of gcc flags to use when testing strict C90 conformance. According to previous post: GCC options for strictest C code?, I should only need a --std=c90.
However here is what I tried:
$ cat t.c
#include <stdint.h> /* added in C99 */
int main()
{
uint64_t t;
return 0;
}
$ gcc -std=c90 -ansi -pedantic t.c
The above does work well (no warnings/errors produced).
Does anyone knows of:
gcc flags to have strict ISO/IEC 9899:1990 conformance
A different compiler (tcc, clang...) with different set of flags ?
EDIT:
Sorry for my wording, yes I would really like to mimic a strictly conforming C90 compiler, in other word it should fail if the code tries to use any feature added later (C99 comes to mind). So pthread include header ought to emit a warning when compiled in what GNU/GCC calls C90 mode (just like stdint.h header should produce a warning without C99). -pedantic nicely warns me about usage of long long, I do not see why it should not warn me about uint64_t.
I used the terminology of ISO/IEC 9899:1990 as quoted from:
http://en.wikipedia.org/wiki/C_(programming_language)#ANSI_C_and_ISO_C
In 1990, the ANSI C standard (with formatting changes) was adopted by
the International Organization for Standardization (ISO) as ISO/IEC
9899:1990, which is sometimes called C90. Therefore, the terms "C89"
and "C90" refer to the same programming language.
EDIT2:
GCC documentation are actually quite clear:
Some features that are part of the C99 standard are accepted as
extensions in C90 mode, and some features that are part of the C11
standard are accepted as extensions in C90 and C99 modes.
So my question is rephrased into:
Is there a compiler + standard include header on a linux system which strictly conforms to C90 ?
C90 compliance doesn't mean that the compiler can't offer other headers that aren't mentioned in the C90 standard. (sys/socket.h, for instance.) If you want to disallow these for some strange reason, you can pass the -I option to add an extra include path, and in that path put versions of all the C99-only headers which are simply #error Don't include me.
Keep in mind here that GCC itself is a conforming freestanding implementation of the C standard specified; such an implementation only supplies a small subset of the standard header files, and practically none of the actual functionality of the C standard library, instead relying on another party -- glibc on Linux systems, for instance -- to supply the C standard library's functionality.
What you seek is something that not only warns you when you are using a C99/C11/GNU language feature that is not in C90, but when you use a library function that is not defined by C90 itself. Sadly, the compiler alone cannot do this for the reason stated above -- it is aloof to what libc it is used with. On glibc systems, the C standard library will pick up on the macros defined by -std=c90 or -ansi:
The macro __STRICT_ANSI__ is predefined when the -ansi option is used. Some header files may notice this macro and refrain from declaring certain functions or defining certain macros that the ISO standard doesn't call for; this is to avoid interfering with any programs that might use these names for other things.
and give you some help by turning off gratuitous extensions:
If you compile your programs using ‘gcc -ansi’, you get only the ISO C library features, unless you explicitly request additional features by defining one or more of the feature macros.
However, this only covers extensions and POSIX-but-not-ISO C functions; it will not save you if a function's behavior is specified differently in ISO C and POSIX.1!

C compiler preprocessor output

C compilers supports generating the preprocessor output file with .i extension.
As far as I know, this is true for Microsoft (Visual Studio), ARM, Keil and some GNU compilers.
They usually use the compiler switch -E or -P for that.
There's also the compiler switch -C to retain comments.
Is the creation of preprocessor files a standard in ANSI-C, or is this compiler specific?
Is the option -C also a standard?
EDIT:
To be more precise: This is about the support for creation of the .i file, not the compiler switch syntax or names.
It is not standardized in the ISO C standard.
However most compilers seem to have -E for generating prepro output. This is reasonable as the prepro output is often very useful for debugging.
Here is a list of compilers I checked:
gcc
pcc
clang
ctc (TriCore)
Tasking C166
Wind River (DIAB)
All these compilers allow writing the prepro output to any file (with any extension). The .i is definitely not standard.
The option -C for retaining comments seems to be rather specific.
The C programming language standard doesn't specify anything about how compilers are invoked.
It might be an "ad hoc" standard, but it's not something that is controlled in any official fashion "globally". There are local standards, such as POSIX that can specify things like these, but that would of course not cover compilers implemented for non-POSIX environments.

Resources