What is the difference between global variables and #define in c - c

Whats the reason why there are 2 opportunities :
global variables
symbolic constants with #define ?
So I know what #define does but I don't know what the difference in use is.
Which situation do I must have thus I'm able to decide myself upon the right opportunitie? What is one of the opportunities able to do what the other one doesn't ? I hope that I could clarify what I mean.

Well, global variables can be edited from everywhere.
Basically, in the low level, a variable is stored in RAM memory and created after launching your application, it always has an address in RAM. Defines are just macros, your compiler will just replace your define names with its values in the compilation step.
#define can't be edited, it's just a macros. And #define is not just about values, you can define almost everything that you want, for example:
// Defining a constant
#define PI 3.14
// Defining an expression
#define MIN(x,y) ((x)<(y))?(x):(y)
// Defining a piece of code
#define STOP_TIMER \
clock_gettime(CLOCK_REALTIME, &__t1); \
__lasttime = \
(double) (__t1.tv_sec - __t0.tv_sec) + \
(double) (__t1.tv_nsec - __t0.tv_nsec) / 1000000000.0;
And, in most situations, defines are used to set some OS-specific or hardware-specific values. It's a really powerful thing, because it gives you the opportunity to change things dynamically in the compilation step. For example:
// Example with OS
#ifdef __linux__
#define WELCOME_STRING "welcome to Linux!"
#else
#define WELCOME_STRING "welcome to Windows!"
#endif
// Example with hardware
#if __x86_64__ || __ppc64__
#define USING_64BIT
#else
#define USING_NOT64BIT
#endif

Consider this small example
#define num 5
int number = 5;
num is a macro and number is a global variable.
One important difference is that num is not stored in the memory, num is just the substitute for 5, but number uses memory.
Also, macro's are preprocessor directives, their values cannot be changed like variables.
So, no doing
num = 6;
later in the code. You will have to use #undef to undefine it and define it again to change the value.

Global variables can be accessed and edited from everywhere. #define constants can't be edited, just read.
Examples:
We use #define ERROR 666 to define a programmer pre compile time constant for an error for the whole program.
We use a global variable for a count of how many operations a function did and this value can be read by other functions as well.
There's no point to make the error as a global variable since it shouldn't be edited and you can't use the #define x as a counter.

#define is declared on top of the code, it means before the declaration of the class. And it serves as to define (as the name says) a constant, that can be read but not changed.
A global variable can be accessed globally on the code, and at same time changed.

Related

Distinguish variable and constant in #define macro

I have macros like this:
#define _DDR_0 DDRD
#define _DDR_1 DDRD
#define _DDR_2 DDRD
// ....
#define _PN_0 0
#define _PN_1 1
#define _PN_2 2
// ...
/** Configure pin as output */
#define as_output(pin) sbi(_DDR_##pin, _PN_##pin)
void as_output_n(const uint8_t pin);
It is used like so:
as_output(2);
uint8_t b = 1;
as_output_n(b);
The _n variant is used for variables, the macro for constants (because it's much faster to do this with a macro).
Is there any possible way to make it so you can use as_output always, and depending on it being constant OR a variable, use the macro OR the function?
Macros are expanded by the preprocessor which has no knowledge of what the code does. From the preprocessor's point of view all the macro arguments are simply tokens (with no logical meaning). In this case as_output macro is used to manufacture new code (via token pasting).
So, what you're trying to do, is not possible using just macros (there could be a way if b would be a macro itself, but i guess that's not what you're looking for).
You could use a const array for your _DDR* and PN* values, and an inline function instead of macros.

Symbolic constants in C (#define statement)

After reading through some of K&R's The C Programming Language I came across the #define symbolic constants. I decided to define...
#define INTEGER_EXAMPLE 2
#define CHAR_EXAMPLE 2
...so my question is how does C know if I'm defining an int or a char type?
#define-d names have no types. They just define textual replacements.
What the compiler is seeing is the preprocessed form. If using GCC, try gcc -C -E somesource.c and have a look at the (preprocessed) output.
In the 1980s the preprocessor was a separate program.
Read about the cpp preprocessor, and preprocessor and C preprocessor wikipages.
You could even define ill-defined names like
#define BAD #*?$ some crap $?
And even more scary you can define things which are syntactically incomplete like
#define BADTASTE 2 +
and later code BADTASTE 3
Actually, you want to use parenthesis when defining macros. If you have
#define BADPROD(x,y) x*y
then BADPROD(2+3,4+5) is expanded to 2+3*4+5 which the compiler understands like 2+ (3*4) +5; you really want
#define BETTERPROD(x,y) ((x)*(y))
So that BETTERPROD(2+3,4+5) is expanded to ((2+3)*(4+5))
Avoid side-effects in macro arguments, e.g. BETTERPROD(j++,j--)
In general, use macros with care and have them stay simple.
Regarding these defines, it doesn't, the expanded macros doesn't have a type. The pre-processor which processes the #define is just replacing text within the source code
When you use these defines somewhere, e.g.
int i = INTEGER_EXAMPLE;
This will expand to
int i = 2;
Here the literal 2 (which in this context is an int) is assigned to an int.
You could also do:
char c = INTEGER_EXAMPLE;
Here too, the literal 2 is an int, and it is assigned to a char. 2 is within the limits of a char though, so all is ok.
You could even do:
int INTEGER_EXAMPLE = 2;
This would expand to
int 2 = 2;
Which isn't valid C.
#define STRING VALUE
is just an instruction for the pre-processor to replace the STRING with VALUE
afterwards the compiler will take control and will check the types
It doesn't, this is the preprocessor. The type of the constant is dependent on the context in which it is used. For instance:
#define INT_EXAMPLE 257
char foo = INT_EXAMPLE;
will attempt to assign 257 in a char context which should generate a warning unless char has more than 8 bits on your computer.
#Defines are nothing but literal replacements of values. You might want to use
static const
As it respects scope and is type-safe. Try this:
#define main no_main
int main() // gets replaced as no_main by preprocessor
{
return 0;
}
Should give you linking errors. Or you could try and fool your teacher by this
#define I_Have_No_Main_Function main //--> Put this in header file 1.h
#include"1.h"
int I_Have_No_Main_Function()
{
return 0;
}
It doesn't. The #define statements are processed before the compiler starts its work. Basically the pre-processor does a search and replace for what you wrote and replaces it, for instance, all instances of INTEGER_EXAMPLE are replaced with the string 2.
It is up to the compiler to decide the type of that 2 based on where it's used:
int x = INTEGER_EXAMPLE; // 2 is an integer
char y = INTEGER_EXAMPLE; // 2 is a char
Preprocessor cannot know the type of the macro definition. Preprocessor will just replace all occurrence of 'CHAR_EXAMPLE' with '2'. I would use cast:
#define CHAR_EXAMPLE ((char)2)

How do I do different things per macro value?

#define TYPE char *
if TYPE is char *
do A
if TYPE is int
do B
Is there an example how to do such things?
C preprocessor MACROS manipulate text, so are essentially typeless, so NO you can't do that.
You could associate another symbol with it:
#define TYPE char *
#define TYPE_IS_CHAR_STAR
#ifdef TYPE_IS_CHAR_STAR
...
#endif
You just need to keep them consistent manually.
Note that that's a dangerous macro; you should use a typedef instead. With the macro:
TYPE x, y;
x is a pointer, but y isn't.
You can get a similar effect by defining another macro along with the type, and using #ifdef etc. with that other macro. For example:
#define TYPE char *
#define TYPE_IS_PCHAR 1
...then later...
#ifdef TYPE_IS_PCHAR
do A
#endif
#ifdef TYPE_IS_INT
do B
#endif
It's not quite the same thing, but it still gets you there.
Not easily. You could do something like:
#define TYPE_IS_CHARPTR
//#define TYPE_IS_INT
#ifdef TYPE_IS_CHARPTR
do A
#endif
#ifdef TYPE_IS_INT
do B
#endif
But you really should be trying to minimise your use of the preprocessor for tricky things (anything other than simple variables).
With enumerated constants and inline functions, there's little need for such uses nowadays.
It would work if you just used basic types (since they're just strings - see Mitch's answer). But as soon as you try to use pointers, it won't work any more - the asterisk throws the preprocessor for a loop:
[holt#Michaela ~]$ gcc test.c
test.c:3:10: error: operator '*' has no right operand
But if you want do do different things based on different types, I'm going to have to recommend switching to C++ and using templates and template specialization. Reluctantly, since template syntax is incredibly ugly, but you should be able to do whatever you want.
Hope that helps!

How to define a define in C?

Is it possible to write a #define that defines a #define?
For example:
#define FID_STRS(x) #x
#define FID_STRE(x) FID_STRS(x)
#define FID_DECL(n, v) static int FIDN_##n = v;static const char *FIDS_##n = FID_STRE(v)
But instead:
#define FID_DECL2(n, v) #define FIDN_##n v \
FIDS_##n FID_STRE(v)
FID_DECL works fine but creates two static variables. Is it possible to make FID_DECL2 work and having define two defines?
No; preprocessing is performed in a single pass. If you want or need more advanced behavior, consider using another tool to preprocess the source, like m4.
Further, the # in the replacement list (at the beginning of #define FIDN... would be parsed as the # (stringize) operator: the operand of this operator must be a named macro parameter, which define is not.
No while defining macros u should take care of one thing
that macro should not call itself (reccursively) either directly
or indirectly.
I know two static variables consuming 8 bytes will be expansive for u.
I have solution over it
#define FID_STRS2(x) #x
#define FID_STRE(x) FID_STRS2(x)
#define FID_DECL(n, v) static int FIDN_##n = v;static const char *FIDS_##n = FID_STRE(v)
Just rename them going reccursive

#undef-ing in Practice?

I'm wondering about the practical use of #undef in C. I'm working through K&R, and am up to the preprocessor. Most of this was material I (more or less) understood, but something on page 90 (second edition) stuck out at me:
Names may be undefined with #undef,
usually to ensure that a routine is
really a function, not a macro:
#undef getchar
int getchar(void) { ... }
Is this a common practice to defend against someone #define-ing a macro with the same name as your function? Or is this really more of a sample that wouldn't occur in reality? (EG, no one in his right, wrong nor insane mind should be rewriting getchar(), so it shouldn't come up.) With your own function names, do you feel the need to do this? Does that change if you're developing a library for others to use?
What it does
If you read Plauger's The Standard C Library (1992), you will see that the <stdio.h> header is allowed to provide getchar() and getc() as function-like macros (with special permission for getc() to evaluate its file pointer argument more than once!). However, even if it provides macros, the implementation is also obliged to provid actual functions that do the same job, primarily so that you can access a function pointer called getchar() or getc() and pass that to other functions.
That is, by doing:
#include <stdio.h>
#undef getchar
extern int some_function(int (*)(void));
int core_function(void)
{
int c = some_function(getchar);
return(c);
}
As written, the core_function() is pretty meaningless, but it illustrates the point. You can do the same thing with the isxxxx() macros in <ctype.h> too, for example.
Normally, you don't want to do that - you don't normally want to remove the macro definition. But, when you need the real function, you can get hold of it. People who provide libraries can emulate the functionality of the standard C library to good effect.
Seldom needed
Also note that one of the reasons you seldom need to use the explicit #undef is because you can invoke the function instead of the macro by writing:
int c = (getchar)();
Because the token after getchar is not an (, it is not an invocation of the function-like macro, so it must be a reference to the function. Similarly, the first example above, would compile and run correctly even without the #undef.
If you implement your own function with a macro override, you can use this to good effect, though it might be slightly confusing unless explained.
/* function.h */
…
extern int function(int c);
extern int other_function(int c, FILE *fp);
#define function(c) other_function(c, stdout);
…
/* function.c */
…
/* Provide function despite macro override */
int (function)(int c)
{
return function(c, stdout);
}
The function definition line doesn't invoke the macro because the token after function is not (. The return line does invoke the macro.
Macros are often used to generate bulk of code. It's often a pretty localized usage and it's safe to #undef any helper macros at the end of the particular header in order to avoid name clashes so only the actual generated code gets imported elsewhere and the macros used to generate the code don't.
/Edit: As an example, I've used this to generate structs for me. The following is an excerpt from an actual project:
#define MYLIB_MAKE_PC_PROVIDER(name) \
struct PcApi##name { \
many members …
};
MYLIB_MAKE_PC_PROVIDER(SA)
MYLIB_MAKE_PC_PROVIDER(SSA)
MYLIB_MAKE_PC_PROVIDER(AF)
#undef MYLIB_MAKE_PC_PROVIDER
Because preprocessor #defines are all in one global namespace, it's easy for namespace conflicts to result, especially when using third-party libraries. For example, if you wanted to create a function named OpenFile, it might not compile correctly, because the header file <windows.h> defines the token OpenFile to map to either OpenFileA or OpenFileW (depending on if UNICODE is defined or not). The correct solution is to #undef OpenFile before defining your function.
Although I think Jonathan Leffler gave you the right answer. Here is a very rare case, where I use an #undef. Normally a macro should be reusable inside many functions; that's why you define it at the top of a file or in a header file. But sometimes you have some repetitive code inside a function that can be shortened with a macro.
int foo(int x, int y)
{
#define OUT_OF_RANGE(v, vlower, vupper) \
if (v < vlower) {v = vlower; goto EXIT;} \
else if (v > vupper) {v = vupper; goto EXIT;}
/* do some calcs */
x += (x + y)/2;
OUT_OF_RANGE(x, 0, 100);
y += (x - y)/2;
OUT_OF_RANGE(y, -10, 50);
/* do some more calcs and range checks*/
...
EXIT:
/* undefine OUT_OF_RANGE, because we don't need it anymore */
#undef OUT_OF_RANGE
...
return x;
}
To show the reader that this macro is only useful inside of the function, it is undefined at the end. I don't want to encourage anyone to use such hackish macros. But if you have to, #undef them at the end.
I only use it when a macro in an #included file is interfering with one of my functions (e.g., it has the same name). Then I #undef the macro so I can use my own function.
Is this a common practice to defend against someone #define-ing a macro with the same name as your function? Or is this really more of a sample that wouldn't occur in reality? (EG, no one in his right, wrong nor insane mind should be rewriting getchar(), so it shouldn't come up.)
A little of both. Good code will not require use of #undef, but there's lots of bad code out there you have to work with. #undef can prove invaluable when somebody pulls a trick like #define bool int.
In addition to fixing problems with macros polluting the global namespace, another use of #undef is the situation where a macro might be required to have a different behavior in different places. This is not a realy common scenario, but a couple that come to mind are:
the assert macro can have it's definition changed in the middle of a compilation unit for the case where you might want to perform debugging on some portion of your code but not others. In addition to assert itself needing to be #undef'ed to do this, the NDEBUG macro needs to be redefined to reconfigure the desired behavior of assert
I've seen a technique used to ensure that globals are defined exactly once by using a macro to declare the variables as extern, but the macro would be redefined to nothing for the single case where the header/declarations are used to define the variables.
Something like (I'm not saying this is necessarily a good technique, just one I've seen in the wild):
/* globals.h */
/* ------------------------------------------------------ */
#undef GLOBAL
#ifdef DEFINE_GLOBALS
#define GLOBAL
#else
#define GLOBAL extern
#endif
GLOBAL int g_x;
GLOBAL char* g_name;
/* ------------------------------------------------------ */
/* globals.c */
/* ------------------------------------------------------ */
#include "some_master_header_that_happens_to_include_globals.h"
/* define the globals here (and only here) using globals.h */
#define DEFINE_GLOBALS
#include "globals.h"
/* ------------------------------------------------------ */
If a macro can be def'ed, there must be a facility to undef.
a memory tracker I use defines its own new/delete macros to track file/line information. this macro breaks the SC++L.
#pragma push_macro( "new" )
#undef new
#include <vector>
#pragma pop_macro( "new" )
Regarding your more specific question: namespaces are often emul;ated in C by prefixing library functions with an identifier.
Blindly undefing macros is going to add confusion, reduce maintainability, and may break things that rely on the original behavior. If you were forced, at least use push/pop to preserve the original behavior everywhere else.

Resources