Cranes Varsity Blog

Variable length argument is feature that allows a function to receive any number of arguments. These are situations where we want a function to handle variable number of arguments according to requirements.

  1. Sum of given numbers.
  2. Minimum of given numbers.

Variable number of arguments are represented by three dotes ( . . .  )

int Fun(int num, . . .)

{

…….

…….

}

int main()

{

            Fun(2,10,20);

            Fun(3,5,6,7);

}

In the above function, when we calling the function the first argument will be always an int  ,it will represent no .of arguments that we are passing in function call. In definition the first formal parameter will access the total no .of argument and followed with three dots( . . ).i.e,ellipses.  To use this functionality always we need to include stdarg.h header file which provides the functions and macros to implement the functionality variable no .of arguments and follow the given steps:

  • Define a function with its last parameter as ellipses and the one just before the ellipses is always an int which will represent the number of arguments.
  • Create ava_list type variable in the function definition. This type is defined in stdarg.h header file.
  • Use int parameter and va_start macro to initialize the va_list variable to an argument list. The macro va_start is defined in stdarg.h header file.
  • Use va_arg macro and va_list variable to access each item in argument list.
  • Use a macro va_end to clean up the memory assigned to va_list 

Now let us follow the above steps and write down a simple function which can take the variable number of parameters and return their average.

#include<stdio.h>

#include<stdarg.h>

float fun(int num , …)

{

            int i=0;

            float sum=0;

            //creating a va_list type variable

            va_list valist;

            //initialize valist fom num number of arguments

            va_start (valist , num);

            //access all the arguments assigned to valist

            for(;i<num;i++)

                        sum= sum + va_arg(valist,int);

            //cleanup memory reserved for valist

            va_end(valist);

            return sum/num;

}

int main()

{

            printf(“the average of 2,3,4 is = %f\n”, fun(3,2,3,4));

            printf(“the average of 10,20,30,40 is = %f\n”, fun(4,10,20,30,40));

}

There are two ways to pass arguments to a function -- Pass by Value and Pass by Address. The major difference between Pass by Value and Pass by Address is that in pass by value a copy of actual arguments is passed to respective formal arguments. While, in call by reference the location (address) of actual arguments is passed to formal arguments, hence any change made to formal arguments will also reflect in actual arguments.

Pass by Value:

 A copy of actual arguments is passed to formal arguments of the called function and any change made to the formal arguments in the called function has no effect on the values of actual arguments in the calling function.

 In call by value, actual arguments will remain safe, they cannot be modified accidentally. 

#include<stdio.h>

void swap (int a,int b)

{

          int temp;

          temp=a;

          a=temp;

          b=temp;

          printf("a=%d,b=%d",a,b);

}

int main()

{

          int a=10,b=20;

          swap(a,b);

          printf("a=%d\n,b=%d\n",a,b);

}

output:

          a=20,b=10(in function swap)

          a=10,b=20(in main function)

In the above program, a and b values are updated only in the functon swap not in the main function.

Pass by Address:

In Pass by address, the location (address) of actual arguments is passed to formal arguments of the called function. This means by accessing the addresses of actual arguments we can alter them within from the called function.

alteration to actual arguments is possible within from called function; therefore the code must handle arguments carefully else you get unexpected results.

#include<stdio.h>

void swap (int *a,int *b)

{

          int temp;

          temp=*a;

          *a=temp;

          *b=temp;

          printf("a=%d,b=%d",*a,*b);

}

int main()

{

          int a=10,b=20;

          swap(&a,&b);

          printf("a=%d\n,b=%d\n",a,b);

}

output:

          a=20,b=10(in function swap)

          a=20,b=10(in main function)

In the above program, a and b address are  passed and in the function swap those address are received by the pointers updated  values are reflected to the main function.

A function calling itself again and again to compute a value is known as recursive function or recursion function or recursion. Normally a function is called by the main program or by some other function but in recursion the same function is called by itself repeatedly.

  Syntax :

void recursion()

{

recursion(); /* function calls itself*/

}

int main()

{

recursion();

return 0;

}

Uses of recursion function :

 Recursion functions are written less number of statements.

 Recursion is effective where terms are generated successively to compute value.

 Recursion is useful for branching process. Recursion helps to create short code that would otherwise be impossible.

Recursive function is very useful to solve many mathematical problems like to calculate factorial of a number, generating Fibonacci series, etc.

Number Factorial :

Following is an example, which calculates factorial for a given number using a recursive function:

Program :

#include <stdio.h>

int factorial(int i)

{              

  if(i <= 1)

   {             return 1;

   }

   return i * factorial(i - 1);

}

int  main()

int i;

    printf(“enter a value for finding factorial value:”);

    scanf(“%d”, &i);

    printf(“Factorial of %d is %d\n”, i, factorial(i));

    return 0;

}

Output :

Enter a value for finding factorial value : 5

Factorial of 5 is 120

 

Fibonacci Series :

Following is another example, which generates Fibonacci series for a given number using a recursive function :

  Program :

#include <stdio.h>

int fibonaci(int i)

{

if(i == 0)

   {

      return 0;

   }

   if(i == 1)

   {

      return 1;

   }

   return fibonaci(i-1) + fibonaci(i-2);

}

int  main()

{

    int i,n;

                printf(“how many fibonacci's(range) u want:”);

                scanf(“%d”, &n);

    for (i = 0; i < n; i++)

    {

       printf(“%d\t%n”, fibonaci(i));

    }

    return 0;

}

Output :

 How many fibonacci's (range) u want: 10

0   1   1   2   3   5   8   13   21   34

Data types specify how we enter data into our programs and what type of data we enter. C language has some predefined set of data types to handle various kinds of data that we can use in our program. These datatypes have different storage capacities.

C language supports 2 different type of data types:

  1. Primary data types(primitive):

These are fundamental data types in C namely integer(int), floating point(float), character(char) and void.

  1. Derived data types:

Derived data types are nothing but primary datatypes but a little twisted or grouped together like array, stucture, union and pointer. These are discussed in details later.

Here we will study about primary or primitive datatype

Primary data types:

  • char: The most basic data type in C. It stores a single character and requires a single byte (8bits)of memory in almost all compilers.it can store an renage
  • int: As the name suggests, an int variable is used to store an integer.

The regular integer that we use has a size of 2 bytes (16 bits) on a 16-bit machine. However, most of the modern systems have 32 or 64-bit configurations. The size of an integer in such environment is 4 bytes.

  • float: It is used to store decimal numbers (numbers with floating point value) with single precision. Its size is 4bytes irrrespective of 32 or 64 bit
  • double: It is used to store decimal numbers (numbers with floating point value) with double precision. Its size is 8bytes irrrespective of 32 or 64 bit

Different data types also have different ranges upto which they can store numbers. These ranges may vary from compiler to compiler. Below is list of ranges along with the memory requirement and format specifiers on 32 bit gcc compiler. 

DATA TYPE

TYPE OF DATA

MEMORY SIZE

RANGE

Int

Integer

2 Bytes

-32768 to 32767

Char

Character

1 Byte

-128 to 127

Float

Floating point number

4 Bytes

3.4e-38 to 3.4e+38

Double

Floating point number with higher precetion

8 Bytes

1.7e-308 to 1.7e+308

 

Program to check size of an datatypes:

#include <stdio.h>

int main()

{

          int a = 1;

          char b ='G';

          float f = 7.77;

          double c = 3.14;

          printf("Hello World!\n");

          printf("I am a character. My value is %c and "

          "my size is %lu byte.\n", b,sizeof(char));

          printf("I am an integer. My value is %d and "

          "my size is %lu bytes.\n", a,sizeof(int));

          printf("I am a float with single floating point variable."" My value is %f and     my size is %lu         bytes.\n",f,sizeof(float));

          printf("I am a double floating point variable."" My value is %lf and my size is %lu           bytes.\n",c,sizeof(double));

          printf("Bye! See you soon. :)\n");

          return 0;

}

Output of the program:

Hello World!

I am a character. My value is G and my size is 1 byte.

I am an integer. My value is 1 and my size is 4 bytes.

I am a float with single floating point variable. My       value is       7.770000 and my size is 4           bytes.

I am a double floating point variable. My value is         3.140000 and my size is 8       bytes.

Bye! See you soon. :)

Like embedded hardware, embedded software architecture is highly flexible. Simple embedded software (such as electronic toys, calculators, and so on) may be only a few thousand lines of code and perform simple input and output functions. On the other hand, complex embedded systems (such as smart phones, robots, and so on) need more complex software architecture, similar to desktop computers and servers.

Complex embedded systems provide more powerful functions, need more convenient interfaces for users, and require the support of more powerful hardware. With the improvement of hardware integration and processing capabilities, the hardware bottleneck has gradually loosened and even broken, so embedded system software now tends to be fully functional and diversified.

An embedded software system is composed of four layers, from bottom to top:

  1. Hardware abstraction layer
  2. Operating system layer
  3. System service layer
  4. Application layer

Hardware Abstraction Layer

The hardware abstraction layer (HAL), as a part of the OS, is a software abstraction layer between the embedded system hardware and OS. It includes the boot loader, board support package (BSP), device drivers, and other components. Similar to the BIOS in PCs, the boot loader is a program that runs before the OS kernel executes. It completes the initialization of the hardware, establishes the image of memory space, and consequently enables the hardware and software environment to reach an appropriate state for the final scheduling of the system kernel.

Operating System Layer

An OS is a software system for uniformly managing hardware resources. It abstracts many hardware functions and provides them to applications in the form of services. Scheduling, files synchronization, and networking are the most common services provided by the OS. Operating systems are widely used in most desktop and embedded systems. In embedded systems, the OS has its own unique characteristics: stability, customization, modularity, and real-time processing.

The common embedded OS contains embedded Linux, Windows CE, VxWorks, MeeGo, Tizen, Android, Ubuntu, and some operating systems used in specific fields. Embedded Linux is a general Linux kernel tailored, customized, and modified for mobile and embedded products. In particular, VxWorks is used in the Mars probes by NASA.

System Service Layer

The system service layer is the service interface that the OS provides to the application. Using this interface, applications can access various services provided by the OS. To some extent, it plays the role of a link between the OS and applications. This layer generally includes the file system, graphical user interface (GUI), task manager, and so on. A GUI library provides the application with various GUI programming interfaces, which enables the application to interact with users through application windows, menus, dialog boxes, and other graphic forms instead of a command line.

Application Layer

The application, located at the top level of the software hierarchy, implements the system functionality and business logic. From a functional perspective, all levels of modules in the application aim to perform system functions. From a system perspective, each application is a separate OS process. Typically, applications run in the less-privileged processor mode and use the API system schedule provided by the OS to interact with the OS.

 

mixpanel.track("Video play");