return-type function-name(argument declarations)
{
declarations and statements //body
}
int
.return
is used.return expression; //expression can be converted to the return type of the function if necessary
double func(char arr[]) //return type is double
{
//body
return sign;
}
//we can declare it in main() which is optional
main()
{
double func(arr[]); //same type here, otherwise meaningless answers
}
double func(char arr[]) //return type is double
{
int sign;
//body
return sign; //sign will be converted to double when returning value
}
Statements following a return
have no significance and are useless.
If a function uses no arguments, use void
. Don’t leave it blank as parameter checking is turned off then and it is still there just for backwards compatibility.
int func(void) {...}
extern
keyword is used to extend the visibility of variables/functions.extern
is not needed in function declaration/definition. Its use is redundant.extern int a;
, a is not assigned any value and using it throws an error in compilation.extern
variable is declared with initialization, it is taken as the definition of the variable as well. Ex - extern int a = 4;
Program in different files:
file1 -
int p = 4; // external variables are defined only once
float q;
file2 -
extern int p; // declared wherever required
extern float q;
Command Line command to link both Files together - gcc file1.c file2.c
// filename: 'file1.c'
int a;
int main(void)
{
a = 2;
}
// filename: file2.c
// When this file is linked with 'file1.c', functions of this file can access 'a'
extern int a;
int myfun()
{
a = 2;
}
.h
.Each file that needs the calc.h
header file has #include "calc.h"
in the beginning as preprocessor directive.
static
.static char buf[BUFSIZE];
static int bufp = 0;
int getch(void) { ... }
void ungetch(int c) { ... }
static
can also be used for functions. the functions declared static
will be invisible to the functions in the other files of the same program.static
can also be used for local variables and are invisible to other functions but they remain (retain value) there even when we enter and leave functions (they are initialized the first time we enter a function, and never leave that value even if we try to change it) unlike automatic variables which are initialized everytime we call the function.int main()
{
int x = 3;
while (x > 0)
{
static int y = 5; // ignored after first iteration/initialization
y++;
printf("The value of y is %d\n", y);
x--;
}
}
OUTPUT: The value of y is 6 The value of y is 7 The value of y is 8
In C, variables are always statically (or lexically) scoped i.e., binding of a variable can be determined by program text and is independent of the run-time function call stack.
For example, output for the below program is 0
, i.e., the value returned by f()
is not dependent on who is calling it. f()
always returns the value of global variable x
.
# include <stdio.h>
int x = 0;
int f()
{
return x;
}
int g()
{
int x = 1;
return f();
}
int main()
{
printf("%d", g());
printf("\n");
getchar();
}
OUTPUT: 0
register
qualifier are an indication to the compiler that they will be used frequently and it should store them in registers which are only a few.register
.register
are harmless, beacause it is then ignored. Further specifications vary across compilers.
register int x;
register char c;
//functions
f(register unsigned m, register long n)
{
resigter int i;
...
}
{ }
, and variables declared and initialized inside a block remain automatic for only that block and there is no name clash with other variables outside the block.int x;
int y;
func(int x)
{
int y;
...
}
In the above code, within the function func
occurances of x
refer to the parameter double x
and all occurances outside func()
refer to the external int x
.
int arr[] = {1, 2, 3, 4}; //size not specified, decide from the initializers = 4
int arr[4] = {1, 2, 3, 4, 5} //error
int arr[4] = {1, 2} //rest will be initialized with 0 weather arr[] is external/automatic, or register
char name[] = "two" //size = 4
/* OR */
char name[] = {'t', 'w', 'o'}
Preprocessor Directives | Function |
---|---|
#include “…” or #include <…> | Header File Inclusion |
#define | Macros (#replacement-text, first ## second) |
#if | Conditional Preprocessing |
#endif | " |
#elif | " |
#else | " |
#ifdef | " |
#ifndef | " |
File Inclusion - #inlcude "filename"
or #include<filename>
.
#include
is in itself a collection of many #define
and an included file may contain further #include
.Macro Substitution - #define name replacement-text
. Here, name
cannot be inside quotes "..."
.
#define forever for(;;) //infinite loop
#define max(a, b) ((a > b) ? (a) : (b))
#undef
undefines macros#undef func
#
preceeding a replacement text to and it will be expanded as a quoted string "..."
.#define dprint(expr) printf(#expr " = %f\n", expr)
//example -
dprint(x/y);
//expanded as -
printf("x/y" " = /f\n", x/y);
//strings will get concatenated as -
printf("x/y = %f\n", x/y);
##
adjacent to arguments, in the expansion white spaces will be removed and arguments will be concatenated. Ex -#define paste(first, second) first ## second
//call
paste(name, 1);
//result is -
name1
defined(name)
function inside an #if
-#endif
block which returns 1 if defined, and 0 otherwise.#if !defined(HDR)
#define HDR
/* contents og hdr.h go here */
#endif
#ifndef
and #ifdef
are specialized forms that test wheather a name is defined.Above cde can be alternatively written as -
#ifndef HDR
#define HDR
/* contents og hdr.h go here */
#endif