restriction on using #define'd functions/inline functions inside Assembly files - c

Is there any restriction on using #define'd functions/inline functions inside Assembly files.
I referred bsd kernel in which two different implementations are defined.
One is macro and other is a normal function ( both are for same function)
In the c file splx is defined asfunction,
http://ftp.hu.freebsd.org/pub/netbsd/NetBSD-release-4-0/src/sys/arch/arm/omap/omap_intr.c
Whereas in h header file splx is defined as macro,
http://ftp.hu.freebsd.org/pub/netbsd/NetBSD-release-4-0/src/sys/arch/arm/omap/omap_intr.h
My understanding is c file definition is used in assembly files whereas macro definition is used in all other functions where the header file is included.
I think I m not clear why assembly is coming into picture here. Basically there are two definitions , one in the c file and another in h file for splx. When I just comment out splx definition in C fle, I get some errors in the compilation of Assembly files.(cpu.S) Thatz why I thought function definition is used(as in c file) while compiling assembly file, whereas macro definition is used for all other files include the h file.
Now my question is: Why can't assembly file too cannot use the macro definition by including the header file?

In the header file, splx is defined as
void splx(int)
void _setsoftintr(int);
#if !defined(EVBARM_SPL_NOINLINE)
#define splx(new) omap_splx(new)
#define _spllower(ipl) omap_spllower(ipl)
#define _setsoftintr(si) omap_setsoftintr(si)
#endif /* !EVBARM_SPL_NOINTR */
I'm not sure why you're referring to assembly files when this language is clearly C, but I see nothing wrong with these declarations - splx is a function, but if EVBARM_SPL_NOINLINE is defined then the macro is used to remap all uses of splx to splx_omap. This is a valid use of the preprocessor, and is not redefining splx - rather using some trickery to modify code to use splx_omap.
This works because the preprocessor runs before the compiler, so any occurence of splx will be replaced by splx_omap before compilation takes place. Some people would find this disturbing but it's one of the capabilities of the preprocessor and is quite useful (when proper precautions are observed).

Related

Aren't header-only C "libraries" wasteful?

I'm looking at a header-only C "library": https://github.com/zserge/jsmn/blob/master/jsmn.h
As far as I can understand, this code will be compiled into every object file where the .c file includes jsmn.h, wasting space.
(The file's function definitions are inside #ifndef JSMN_HEADER, so you could use this as a "traditional" header file by defining JSMN_HEADER.)
Why hasn't it been written as a "traditional" .c and .h pair?
Is the linker clever enough to dedup function identical definitions between object files? I would have expected "duplicate symbol" errors.
What advantage does putting code in headers give in C? (Not C++.)
From where do you get the function definitions if you use #define JSMN_HEADER before importing?
Is jsmn.h being header-only a clever trick, from which I can learn?
The header expands into one of the following, depending on the macros defined:
No macros — function definitions (public functions are non-static, private ones are).
JSMN_HEADER — function declarations (for public functions only).
JSMN_STATIC — static function definitions (for both private and public functions).
If only a single TU needs the library, you can freely choose between (1) and (3).
If more than one TU needs the library, you need (1) in one of the TUs and (2) in all others. Then the only thing that's "wasted" is preprocessor time for skipping function definitions for (2), but it shouldn't matter since they're so tiny.
In this case, trying to go with (1) for all TUs would give you "duplicate symbol" linker errors. Trying to go with (3) for all TUs would silently duplicate the symbols, which would be wasteful.
Why hasn't it been written as a "traditional" .c and .h pair?
For supposed convenience of distributing and using the library.
Is the linker clever enough to dedup function identical definitions between object files? I would have expected "duplicate symbol" errors.
It's probably not clever enough, but it doesn't need to be.
You're expected to define the macros so that only a single TU has the definitions.
What advantage does putting code in headers give in C?
Less source files to distribute.
From where do you get the function definitions if you use #define JSMN_HEADER before importing?
From your other TU that didn't define this macro before including the header.
Is jsmn.h being header-only a clever trick, from which I can learn?
Yes.

Confusion between header file macro declaration and pre-processor macro declaration

I am new to C, so please help me with an answer before downvoting, it will help me a lot.
The definition of header file states that-
A header file consists of C function declaration and macro definitions to be shared between different files.
And the definition of C Preprocessor states that-
The C preprocessor is a macro preprocessor that transforms your program before it is compiled.All preprocessor directives begin with the # symbol.
My question is the macro declaration are done using # symbol in a program, does it depend on inclusion or exclusion of any header file, also how to find whether a particular file has a pre-defined macro declaration in it.
For example-
Say a file 'ani.h' has a macro declaration,
#define anii 2
So, once I include this file, I am allowed to use the CNAME i.e. aniidirectly?
It is easier if you look at this form the view of what the pre-processor actually does.
It reads a file and replaces text and then output a new file. The new file is sent to the compiler. The pre-proc knows nothing about C code, its just a text manipulation engine
#include xxxx
says, 'replace this line by the contents of that file'
#define FOO BAR
says, 'whenever you see FOO replace it by BAR
There are also some simple conditionals: #if etc
A macro is simply a FOO BAR replacement, usually FOO is small and BAR is large.
Although they can be used to do some nice metaprogramming tricks as well as conditional programming, macros most basic use is to make programmers lives easier via syntactic sugaring. Before compiling your code, the preprocessor module will substitute all the macros by the terms they represent, so everything you define must have been declared somewhere above the point where the macro is first used. So if you do:
#include <stdio.h>
#include <math.h>
#define MY_MACRO(x) for(int i=0; i<(x); ++i) printf("%d\n", func((x),i);
int func(int n, int m) {return pow(n, m);}
int main()
{
int a = 10;
MY_MACRO(a)
return 0;
}
The preprocessor will substitute all occurrences of MY_MACRO in your code by the loop that was defined after it. The code will then be sent to compilation. When the compiler reaches the line where the macro is used, it is necessary that printf and func are declared somewhere above this line, just as if you were writing the code without the macro. (Note that printf and pow are declared in the headers included before the definition and func is declared after the definition, but them three are declared before the first use of the macro.)
In what concerns to knowing which macros are declared inside some lib and which aren't, I believe the only way is to check the header files you are using or to read their documentation. But if you know that some specific macro may or may not be declared, you can test it using the code below:
#ifdef SOME_MACRO
printf("SOME_MACRO defined!\n");
#else
printf("SOME_MACRO not defined!\n");
#endif

Is there a case when a C function can be defined within a header file?

Is there a case when a function can be defined within a header file? I was told by person whose opinion I respect that there are cases when a function can be defined in a header file included by multiple C source files. However, I could not find any. Just confirm, I define the function in-line in a header file but that also did not work. I will but have not found any answers yet. There is no practical requirement as such. I just wanted to see if there is some part of the C standard that I don't know of which will allow this. Thanks for any answers
Yes, but only if it is declared as static inline.
Functions that are declared simply as inline behave exactly like functions that are defined with no modifiers, except that they may be inlined within the translation unit that they're defined as inline in. They still have global scope, so including them in a header file will result in errors, as the function will be multiply defined.
static inline functions, on the other hand, do not have global scope — they only exist where they are used, more in line (ha ha) with the way you probably think of inline functions. As such, they're appropriate for use in header files.
No C function should not be defined in Header files.
function declaration can go in Header files.
But function definition should not ever go in header files.
Reason:
If function defination goes in header files then header will be included by multifple c files and when they are going to compile they will give error for multi defination of same files.
static inline function can be defined in Header files.
But that should not be used because
The "static" keyword in "static inline" is harmful in the situation
where a "static inline" function gets included and compiled in N
different files and does not get inlined. In this situation, one would
typically want the N copies of this function to get merged into one,
to avoid code bloat. But the "static" keyword prevents that, forcing
the linker to not merge these redundant functions.
As a side note to the answers/discussion on inline functions, I believe that theoretically one could define a function in a header in the same way as in a normal .c file, providing the header was only included once and in single location.
Though I'm not sure if the standard explicitly forbids this or not, it follows from the idea that the contents of a header file are essentially being copied and pasted into the top of the source file in which it is included from which point of view, there would be no issue.

C: Are #define directives global?

I'm somewhat confused by #define statements. In libraries, they seem to be a means of communication across different files, with lots of #ifdefs and #ifndefs.
Having said that, I now have two files file1.c and file2.c compiled together, with #define TEST 10 inside file2.c. Yet, when I use TEST inside file2.c the compiler gives the following error message:
'TEST' undeclared (first use in this function)
Are #define directives global?
#defines are not global, they are just a substitution where ever they are used (if declared in the same compile unit)
They are not globals, they are not symbols, they are irrelevant at linkage, they are only relevant at pre-compilation.
#defined macros are global in that they do not follow normal C scoping rules. The textual substitution from the macro will be applied (almost) anywhere the macro name appears after its #define. (Notable exceptions are if the macro name is part of a comment or part of a string literal.)
If you define a macro in a header file, any file that #includes that header file will inherit that macro (whether desired or not), unless the file explicitly undefines it afterward with #undef.
In your example, file2.c does not know about the TEST macro. How would it know to pick up the #define from file1.c? By magic? Since macros perform textual substitution on the source code, there is no representation of them in the generated object files. file2.c therefore needs to know that substitution rule itself, and if you want that shared across multiple files, that #define needs to live in a common header file that your .c files #include.
If you're asking specifically about how many of the #ifdefs that you see in libraries work, many of them are likely checking against pre-defined macro names provided by the compilation environment. For example, a C99 compiler defines a __STDC_VERSION__ macro that specifies the language version; a Microsoft compiler defines an _MSC_VER macro. (Often these predefined macros start with leading underscores since those names are reserved for the compiler.)
Additionally, most compilers allow defining simple macros as command-line arguments. For example, you might compile your code via gcc -DNDEBUG file1.c to compile file.c with NDEBUG defined to disable asserts.
In case somebody reads this later, and to add some practical information:
Some environments like atmel, vs, or iar, allow you to define global #define directives. They basically pass these defined values to the precompiler in some commandline format.
You can do the same in batch commands or makefiles, etc.
Arduino always adds a board variant (usually located at hardware\arduino\variants) to all compilations. At that point you can create a new board that contains your global define directives, and use it that way. For example, you can define a mega2560(debug) board out of the original mega2560 that contains some debug directives. You will add a reference to that variant in "boards.txt", by copy pasting some text, and properly modifying it.
At the end of the day, you will have to give that global hfile or global directive to the compiler in one way or another.
you should make a file1.h and put your defines there. Then in file2.c
#include "file1.h"
easy as a pie :)

Using Definitions in C Header Files?

I'm currently learning the C programming language (coming from Java) and I'm a bit confused as to how to define a macro.
In order for other code to use the macro, the header file must have it. But if I define the macro in the header file, then the source file can't use it. Do I have to define it in both or do I have to #include the source file's own header file?
Source files virtually always include their "own" header file -- i.e., a header that declares the functions defined in a source file. Declaring a function before actually defining it is perfectly legal and often desirable: you may get compile errors if the header is accidentally mismatched, and that's a good thing.
First #include is essentially like directly inserting the file in your file. It is run by the compiler pre-processor, which is run before the compiler. Google C preprocessor for more info...
Typically setup is:
#include "macros.h"
...
printf("Macro value %d\n", MACRO_HERE(1) );
and in your header file, macros.h
#ifndef MACROS_H_
#define MACROS_H_
#define MACRO_HERE( n ) ( n + 1 )
#endif
The wrapped #ifdef(s) prevent the macro from being redefined if you later have another include file which also includes macro.h
See also: #pragma once (which is widely used in many compilers also)
You can define it both in the header or the implementation file, but it needs to be visible to the translation unit you use it in.
If it's for use just inside one implementation file, define it in that file only.
If more files use the macro, define it in a header and include that header wherever you need the macro.

Resources