Is calling atoi without stdlib undefined behaviour? - c

Is calling atoi without including stdlib.h undefined behaviour?
I can't find where I have included stdlib.h in my project, even though I have used atoi.
The thing is actually atoi has been working fine - it has been parsing integers correctly every time the software has been used.
It is some embedded device.
So is there case this can be well defined?
btw. In this line:
#ifdef __cplusplus
#if __cplusplus
extern "C"{
#endif
#endif /* __cplusplus */
#include "sdkGlob.h"
#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */
that header includes stdlib.h but I can't understand in which case it is included. And I am not sure if this cplusplus is defined anywhere. This is a c project anyway.

Prior to C99 it was acceptable to use functions that hadn't previously been declared. The compiler might generate a warning but there would be no error until the linker either didn't find the function or found a function of the same name with a signature other than the one that the compiler had guessed. Luckily for you, the compiler always guesses a return type of int.
In C99 it became necessary for function declarations to be visible but not all compilers strictly enforce the rule.
As per Random832's comment, it's also quite possible that sdkGlob simply includes stdlib for itself.
As to your other question: sdkGlob is always included but if run through a C++ compiler rather than a C compiler you also get the extern "C"{ .. } wrapping. That tells the C++ compiler not to mangle the names so that you can link against a version of that module that was built using an ordinary C compiler. It's the normal way to provide plain C libraries in a way that allows them to be used by both C and C++ code.

The short answer
Two possibilities:
It's probable that sdkGlob.h include stdlib.h or define its own version of atoi.
Some compilers, like GCC, resolve missing #include and even hide the errors or warnings. Run gcc -Wall and check if warnings appears.
About ifndef
The #ifdef __cplusplus sections are used by C++ compilers. Here, you're saying '*if and if only the code is being compiled by a C++ compiler, do ... *'.
The C-only version of your code:
#include "sdkGlob.h"
The C++-only version of your code:
extern "C"{
#include "sdkGlob.h"
}

Related

Using macros with the same name in different header files

I use macros like #DEBUG to print some additional debugging info and even possibly do something differently to help me with debugging. For example:
in header a.h:
#define DEBUG 1
in src a.c:
#include "a.h"
int func_a () {
/*some code*/
#if DEBUG
//do this
#endif
}
What will happen if I use a macro with the same name in another file ?
header b.h
#define DEBUG 1
#if DEBUG
# define PRINT 1
#elif
#define PRINT 0
#endif
src b.c
#include "a.h"
#include "b.h"
int func_b () {
/*some code*/
#if PRINT
//do this
#endif
/*some code*/
#if DEBUG
//do this
#endif
}
What will happen if I change the value of #DEBUG in one of the headers? I saw in some other answers that redefining a macro is not allowed in the C standard. But when I compile with GCC using the -Wall flag I see no errors or warnings.
What will happen if I use a macro with the same name in another file ?
It depends. C does not allow an identifier that is already defined as a macro name at some point in a translation unit to be defined again at that point, unless the redefinition specifies an identical replacement list. This is a language constraint, so conforming implementations will emit a diagnostic about violations they perceive. Compilers may reject code that contains violations, and if they nevertheless accept such code then the resulting behavior is undefined as far as C is concerned.
In practice, implementations that do accept such violations have two reasonable choices (and a universe of unreasonable ones):
ignore the redefinition, or
process the redefinition as if it were proceeded by an #undefine directive specifying the affected macro name.
Implementations of which I am aware accept such redefinitions and implement the latter option, at least by default.
If your headers are defining macros solely for their own internal use then you may be able to address the issue by exercising some discipline:
Each header puts all its #include directives at the beginning, before any definition of the possibly-conflicting macro(s).
Each header #undefines the possibly-conflicting macro at the end, under all conditional-compilation scenarios in which the macro may be defined in the first place.
On the other hand, if the macro is intended to be referenced by files that use the header(s) where it is defined then undefining it within the header would defeat the purpose. Under some circumstances, probably including yours, you can address that by defining the macro only conditionally in each header:
#if !defined(DEBUG)
#define DEBUG 1
#endif
That will avoid redefinition, instead using (only) the first definition encountered, which may even come from compiler command-line arguments. If you do this, however, it is essential that all the default definitions specified in that way be the same, else changing your headers' inclusion order will have unexpected effects code that depends on which definition is used.

Why cant i check if i have included stdlib.h on tdm-gcc compiler?

I'm writing a header file in C and need stdlib.h for it to work. But, when I check if _STDLIB_H is defined, the pre-processor says it's not, even if I include the file. I have tried it on multiple compilers, where it works on most but not on tdm-gcc. How can I fix this?
Looking at stdlib.h source code, it seems like the macro to look for in tdm-gcc might be _TR1_STDLIB_H.
So you can try something like:
#if defined _STDLIB_H || defined _TR1_STDLIB_H
For a safer way to check if stdlib.h is properly included, you should check for a macro that the C standard requires the file to define.
I may be missing something, but I don't see any requirement in the C standard for stdlib.h to define _STDLIB_H. I think this may just be a common way compilers decided to guard against multiple inclusion.
try something like
#include <stdlib.h>
#ifndef NULL
#error "stdlib.h not included"
#endif
because the C standard requires that stdlib.h defines NULL
But none of this should be technically necessary... I don't know of a preprocessor that won't throw a fatal error if it can't find a file you tried to #include
EDIT:
According to the C standard stdio.h also defines NULL, so perhaps it would be better to check for EXIT_SUCCESS or EXIT_FAILURE

How to #ifdef the __builtin_prefetch function

How do I keep __builtin_prefetch() in my code, but make compilers that do not have it compile successfully? (Just doing nothing where it is found).
__builtin_prefetch() is recognised by the compiler (gcc) not the preprocessor, so you won't be able to detect it using the C preprocessor.
Since an identifier with two leading underscores is reserved for use by the implementation (so any code you use which defines such an identifier has undefined behaviour) I'd do it the other way around.
#ifdef __GNUC__
#define do_prefetch(x) __builtin_prefetch(x)
#else
#define do_prefetch(x)
#endif
and then use
do_prefetch(whatever);
where needed.
That way there is no code emitted unless it is actually needed.
Since __builtin_prefetch() accepts a variable number of arguments, you might want to adapt the above to use variadic macros (C99 and later) - if you use it with different numbers of arguments in different places in your code.
It is not exactly the best solution, but it will disable __builtin_prefetch() on all other compilers other than GCC.
#ifndef __GNUC__
# define __builtin_prefetch(x)
#endif

How to #ifdef by CompilerType ? GCC or VC++

I used #ifdef Win32 for safe calls alike sprintf_s but now I want to build project with MinGW and it's just wrong now. I need to use #ifdef VC++ or somehow like that. Is it possible?
#ifdef __clang__
/*code specific to clang compiler*/
#elif __GNUC__
/*code for GNU C compiler */
#elif _MSC_VER
/*usually has the version number in _MSC_VER*/
/*code specific to MSVC compiler*/
#elif __BORLANDC__
/*code specific to borland compilers*/
#elif __MINGW32__
/*code specific to mingw compilers*/
#endif
See the "Microsoft-Specific Predefined Macros" table of Visual C predefined macros
You could check for _MSC_VER.
Preferably, you should resort to using portable symbols. I understand sometimes those symbols may not be defined, so you can see the Predef project for an extensive list of preprocessor macros regarding standards, compilers, libraries, operating systems and architectures that aren't portable.
However, the function you specifically mention in this question has been included within the C11 standard as a part of Annex K.3, the bounds-checking interfaces (library).
K.3.1.1p2 states:
The functions, macros, and types declared or defined in K.3 and its subclauses are declared and defined by their respective headers if __STDC_WANT_LIB_EXT1__ is defined as a macro which expands to the integer constant 1 at the point in the source file where the appropriate header is first included
Thus, you should place preference upon checking __STDC_WANT_LIB_EXT1__, and only use compiler-specific symbols when that doesn't exist.

Clang C Compiler 'class' keyword reserved?

Hi I am compiling ffmpeg using xcode, which I believe uses clang for compilation. In ffmpeg there is a struct with a member variable named 'class' I believe this is perfectly fine in C but clang is trying to parse it as a keyword. Any idea how to fix? Basically the following in a cpp file will cause the error:
extern C {
typedef struct {
int class;
} SomeStruct;
}
It tries to interpret class as a keyword.
FYI the file that is throwing the error in ffmpeg is libavcodec/mpegvideo.h and I need to include this to have access to the MpegEncContext struct to pull out motion map info.
EDIT
The above code sample was just to demonstrate the error. But perhaps its fixable in another way. In my actual code I have it like this:
#ifdef __cplusplus
extern "C" {
#endif
#include "libavcodec/mpegvideo.h"
#include "libavformat/avformat.h"
#if __cplusplus
} //Extern C
#endif
How would I get that to include the two files as C files and not C++?
Thanks
It's completely fine in C. When you build that as C++, you encounter an error because class is a C++ keyword.
As far as fixing it, you would normally choose an identifier other than class. However, ffmpeg developers may not be so agreeable with that change. Therefore, you may need to either:
restrict the visibility of that header to C translations
or edit your own copy in order to use it in C++ translations
Fortunately, you are also using a C compiler which has good support of C99 features in this case. C Compilers which do not support C99 well are particularly troublesome with ffmpeg sources (because you would then compile the whole program as C++ for the C99 features, and the conflict count would be much higher).
(there are other dirty tricks you could do to try to work around the problem, but i will not mention them)
Basically the following in a cpp file will cause the error
.cpp files are processed as C++ files, not C, and class is a reserved word in C++.
If you don't have a choice to rename anything in those header files, you could just replace the class token by something else
#ifdef __cplusplus
extern "C" {
# define class videoClass
#endif
#include "libavcodec/mpegvideo.h"
#include "libavformat/avformat.h"
#if __cplusplus
# undef class
} //Extern C
#endif
This is quite a dirty hack, but for such badly interfaced code you don't have much choice. The real solution would be to have all the struct members in these files use names that us some sort of prefix or so, as it is done in the network layer code. There all members have some prefixes as ss_ or sa_ and such problems are very unlikely to occur.

Resources