Storage Classes in C Programming Language
C Programming Language
troboC |
1. auto
This storage class denotes that an identifier has automatic storage duration. This means once the scope in which the identifier was defined ends, the object denoted by the identifier is no longer valid.Since all objects, not living in global scope or being declared static, have automatic storage duration by default when defined, this keyword is mostly of historical interest and should not be used:
int foo(void)
{
/* An integer with automatic storage duration. */
auto int i = 3;
/* Same */
int j = 5;
return 0;
} /* The values of i and j are no longer able to be used. */
2. register
Hints to the compiler that access to an object should be as fast as possible. The register storage class is more appropriate for variables that are defined inside a block and are accessed with high frequency. For example,/* prints the sum of the first 5 integers*/
/* code assumed to be part of a function body*/
{
register int k, sum;
for(k = 1, sum = 0; k < 6; sum += k, k++);
printf("\t%d\n",sum);
}
In C11, The _Alignof
operator is also allowed to be used with register arrays.3. extern
Used to declare an object or function that is defined elsewhere (and that has external linkage). In general, it is used to declare an object or function to be used in a module that is not the one in which the corresponding object or function is defined:/* file1.c */
int foo = 2; /* Has external linkage since it is declared at file scope. */
/* file2.c */
#include
int main(void)
{
/* `extern` keyword refers to external definition of `foo`. */
extern int foo;
printf("%d\n", foo);
return 0;
}
Things get slightly more interesting with the introduction of the inline keyword in C99:Hints to the compiler that the function
bar
might be inlined and suppresses the generation of an external symbol, unless stated otherwise./* Should usually be place in a header file such that all users see the definition */
inline void bar(int drink)
{
printf("You ordered drink no.%d\n", drink);
}
To be found in just one .c file. Creates an external function definition of bar
for use by other files. The compiler is allowed to choose between the inline version and the external definition when bar
is called. Without this line, bar
would only be an inline function, and other files would not be able to call it.extern void bar(int);
4. static
The static storage class serves different purposes, depending on the location of the declaration in the file:To confine the identifier to that translation unit only (scope=file).
/* No other translation unit can use this variable. */
static int i;
/* Same; static is attached to the function type of f, not the return type int. */
static int f(int n);
To save data for use with the next call of a function (scope=block): void foo() {
static int a = 0; /* has static storage duration and its lifetime is the
* entire execution of the program; initialized to 0 on
* first function call */
int b = 0; /* b has block scope and has automatic storage duration and
* only "exists" within function */
a += 10;
b += 10;
printf("static int a = %d, int b = %d\n", a, b);
}
int main(void) {
int i;
for (i = 0; i < 5; i++) {
foo();
}
return 0;
}
/*
This code prints:
static int a = 10, int b = 10
static int a = 20, int b = 10
static int a = 30, int b = 10
static int a = 40, int b = 10
static int a = 50, int b = 10
*/
5. ___Thread_local
turbo C |
Denotes thread storage duration. A variable declared with
_Thread_local
storage specifier denotes that the object is local to that thread and
its lifetime is the entire execution of the thread in which it's
created. It can also appear along with static or extern.#include
#include
#define SIZE 5
int thread_func(void *id)
{
/* thread local variable i. */
static _Thread_local int i;
/* Prints the ID passed from main() and the address of the i.
* Running this program will print different addresses for i, showing
* that they are all distinct objects. */
printf("From thread:[%d], Address of i (thread local): %p\n", *(int*)id, (void*)&i);
return 0;
}
int main(void)
{
thrd_t id[SIZE];
int arr[SIZE] = {1, 2, 3, 4, 5};
/* create 5 threads. */
for(int i = 0; i < SIZE; i++) {
thrd_create(&id[i], thread_func, &arr[i]);
}
/* wait for threads to complete. */
for(int i = 0; i < SIZE; i++) {
thrd_join(id[i], NULL);
}
}
6. typedef
Defines a new type based on an existing type. Its syntax mirrors that of a variable declaration./* Byte can be used wherever `unsigned char` is needed */
typedef unsigned char Byte;
/* Integer is the type used to declare an array consisting of a single int */
typedef int Integer[1];
/* NodeRef is a type used for pointers to a structure type with the tag "node" */
typedef struct node *NodeRef;
/* SigHandler is the function pointer type that gets passed to the signal function. */
typedef void (*SigHandler)(int);
While not technically a storage class, a compiler will treat it as
one since none of the other storage classes are allowed if the typedef
keyword is used.The typedefs are important and should not be substituted with
#define macro
.typedef int newType;
newType *ptr; // ptr is pointer to variable of type 'newType' aka int
However,#define int newType
newType *ptr; // Even though macros are exact replacements to words,
this doesn't result to a pointer to variable of type 'newType' aka int
Preprocessor Directives - C Programming
The C preprocessor is a macro processor that is used automatically by the C compiler to transform your program before actual compilation (Proprocessor direcives are executed before compilation.). It is called a macro processor because it allows you to define macros, which are brief abbreviations for longer constructs. A macro is a segment of code which is replaced by the value of macro. Macro is defined by
#define
directive.Preprocessing directives are lines in your program that start with
#
. The #
is followed by an identifier that is the directive name. For example, #define
is the directive that defines a macro. Whitespace is also allowed before and after the #
.The
#
and the directive name cannot come from a macro expansion. For example, if foo
is defined as a macro expanding to define
, that does not make #foo
a valid preprocessing directive.All preprocessor directives starts with hash # symbol.
List of preprocessor directives :
#include
#define
#undef
#ifdef
#ifndef
#if
#else
#elif
#endif
#error
#pragma
1. #include
The #include preprocessor directive is used to paste code of given file into current file. It is used include system-defined and user-defined header files. If included file is not found, compiler renders error. It has three variants:
#include
This variant is used for system header files. It searches for a file
named file in a list of directories specified by you, then in a standard
list of system directories.
#include "file"
This variant is used for header files of your own program. It
searches for a file named file first in the current directory, then in
the same directories used for system header files. The current directory
is the directory of the current input file.
#include anything else
This variant is called a computed #include
. Any #include
directive whose argument does not fit the above two forms is a computed include.2. Macro's (#define)
Let's start with macro, as we discuss, a macro is a segment of code which is replaced by the value of macro. Macro is defined by#define
directive.Syntax
#define token value
There are two types of macros:- Object-like Macros
- Function-like Macros
1. Object-like Macros
The object-like macro is an identifier that is replaced by value. It is widely used to represent numeric constants. For example:#define PI 3.1415
Here, PI is the macro name which will be replaced by the value 3.14. Let's see an example of Object-like Macros :#include
#define PI 3.1415
main()
{
printf("%f",PI);
}
Output:3.14000
2. Function-like Macros
The function-like macro looks like function call. For example:#define MIN(a,b) ((a)<(b)?(a):(b))
Here, MIN is the macro name. Let's see an example of Function-like Macros :#include
#define MIN(a,b) ((a)<(b)?(a):(b))
void main() {
printf("Minimum between 10 and 20 is: %d\n", MIN(10,20));
}
Output:Minimum between 10 and 20 is: 10
Preprocessor Formatting
A preprocessing directive cannot be more than one line in normal circumstances. It may be split cosmetically with Backslash-Newline. Comments containing Newlines can also divide the directive into multiple lines.for example, you can split a line cosmetically with Backslash-Newline anywhere:
/*
*/ # /*
*/ defi\
ne FO\
O 10\
20
is equivalent into #define FOO 1020
.3. #undef
To undefine a macro means to cancel its definition. This is done with the#undef
directive.Syntax:
#undef token
define and undefine example#include
#define PI 3.1415
#undef PI
main() {
printf("%f",PI);
}
Output:Compile Time Error: 'PI' undeclared
4. #ifdef
The#ifdef
preprocessor directive checks if macro is defined by #define
. If yes, it executes the code.Syntax:
#ifdef MACRO
//code
#endif
5. #ifndef
The#ifndef
preprocessor directive checks if macro is not defined by #define
. If yes, it executes the code.Syntax:
#ifndef MACRO
//code
#endif
6. #if
The#if
preprocessor directive evaluates the expression or condition. If condition is true, it executes the code.Syntax:
#if expression
//code
#endif
7. #else
The#else
preprocessor directive evaluates the expression or condition if condition of #if
is false. It can be used with #if
, #elif
, #ifdef
and #ifndef
directives.Syntax:
#if expression
//if code
#else
//else code
#endif
Syntax with #elif#if expression
//if code
#elif expression
//elif code
#else
//else code
#endif
Example#include
#include
#define NUMBER 1
void main() {
#if NUMBER==0
printf("Value of Number is: %d",NUMBER);
#else
print("Value of Number is non-zero");
#endif
getch();
}
OutputValue of Number is non-zero
8. #error
The#error
preprocessor directive indicates error. The compiler gives fatal error if #error
directive is found and skips further compilation process.C #error example
#include
#ifndef __MATH_H
#error First include then compile
#else
void main(){
float a;
a=sqrt(7);
printf("%f",a);
}
#endif
9. #pragma
The#pragma
preprocessor directive is used to provide additional information to the compiler. The #pragma
directive is used by the compiler to offer machine or operating-system
feature. Different compilers can provide different usage of #pragma
directive.Syntax:
#pragma token
Example#include
#include
void func() ;
#pragma startup func
#pragma exit func
void main(){
printf("\nI am in main");
getch();
}
void func(){
printf("\nI am in func");
getch();
}
OutputI am in func
I am in main
I am in fun
Comments