C Language Notes 12_Variable Parameters-Memory Management-Command Line Parameters

Keywords: C Programming

Variable parameters

Sometimes, you may encounter situations where you want a function to have a variable number of parameters instead of a predefined number of parameters.The C language provides a solution to this situation by allowing you to define a function that accepts a variable number of parameters depending on your specific needs.The following example demonstrates the definition of this function.

int func(int, ... ) 
{
   .
   .
   .
}
 
int main()
{
   func(2, 2, 3);
   func(3, 2, 3, 4);
}

Note that the last parameter of function func() is written as an ellipsis, that is, three dots (...), and the parameter before the ellipsis is int, which represents the total number of variable parameters to pass.To use this functionality, you need to use the stdarg.h header file, which provides functions and macros that implement variable parameter functionality.The steps are as follows:

  • Define a function with an ellipsis as the last parameter. Custom parameters can be set before the ellipsis.
  • Create a va_list type variable in the function definition, which is defined in the stdarg.h header file.
  • Initialize the va_list variable as a list of parameters using the int parameter and the va_start macro.The macro va_start is defined in the stdarg.h header file.
  • Use the va_arg macro and va_list variable to access each item in the parameter list.
  • Use the macro va_end to clean up the memory assigned to the va_list variable.

Now let's follow the steps above to write a function with variable number parameters and return their mean values:

#include <stdio.h>
#include <stdarg.h>
 
double average(int num,...)
{
 
    va_list valist;
    double sum = 0.0;
    int i;
 
    /* Initialize valist for num parameters */
    va_start(valist, num);
 
    /* Access all parameters assigned to valist */
    for (i = 0; i < num; i++)
    {
       sum += va_arg(valist, int);
    }
    /* Clean up memory reserved for valist */
    va_end(valist);
 
    return sum/num;
}
 
int main()
{
   printf("Average of 2, 3, 4, 5 = %f\n", average(4, 2,3,4,5));
   printf("Average of 5, 10, 15 = %f\n", average(3, 5,10,15));
}

When the above code is compiled and executed, it produces the following results.It should be noted that the function average() is called twice, and each time the first parameter represents the total number of variable parameters passed.Ellipsis are used to pass a variable number of parameters.

Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000

memory management

C provides several functions for memory allocation and management.These functions can be found in the <stdlib.h>header file.

Sequence Number Functions and Descriptions
1 void *calloc(int num, int size); dynamically allocates num contiguous spaces of size in memory and initializes each byte to zero.So its result is that num*size bytes of memory are allocated, and each byte has a value of 0.
2 void free(void *address); this function releases the block of memory that address points to, freeing up dynamically allocated memory space.
3 void *malloc(int num); allocates a specified size of memory space in the heap area to hold data.This memory space will not be initialized after the function is executed, and their values are unknown.
4 void *realloc(void *address, int newsize); this function reallocates memory to extend it to newsize.

Note: The void * type represents a pointer of undetermined type.C, C++ specifies that void * types can be cast to any other type of pointer through type conversion.

Dynamic memory allocation

When programming, if you know the size of the array beforehand, it's easier to define it.For example, an array that stores names of people can hold up to 100 characters, so you can define the array as follows:

char name[100];

However, if you don't know in advance the length of text you need to store, for example, if you want to store a detailed description of a topic.Here, we need to define a pointer to a character that does not define the required memory size, and then allocate memory on demand, as follows:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* Dynamic memory allocation */
   description = (char *)malloc( 200 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student in class 10th");
   }
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
}

When the above code is compiled and executed, it produces the following results:

Name = Zara Ali
Description: Zara ali a DPS student in class 10th

The above program can also be written using calloc(), simply replace malloc with calloc, as follows:

calloc(200, sizeof(char));

When allocating memory dynamically, you have full control and can pass values of any size.Arrays with predefined sizes cannot be resized once defined.

Resize and free memory

When a program exits, the operating system automatically releases all memory allocated to the program, but it is recommended that you call the function free() to free memory when you do not need it.

Alternatively, you can increase or decrease the size of allocated memory blocks by calling the function realloc().Let's look at the above example again using the realloc() and free() functions:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
 
int main()
{
   char name[100];
   char *description;
 
   strcpy(name, "Zara Ali");
 
   /* Dynamic memory allocation */
   description = (char *)malloc( 30 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcpy( description, "Zara ali a DPS student.");
   }
   /* Suppose you want to store a larger description */
   description = (char *) realloc( description, 100 * sizeof(char) );
   if( description == NULL )
   {
      fprintf(stderr, "Error - unable to allocate required memory\n");
   }
   else
   {
      strcat( description, "She is in class 10th");
   }
   
   printf("Name = %s\n", name );
   printf("Description: %s\n", description );
 
   /* Release memory using the free() function */
   free(description);
}

When the above code is compiled and executed, it produces the following results:

Name = Zara Ali
Description: Zara ali a DPS student.She is in class 10th

You can try not to reallocate extra memory, and the strcat() function generates an error because there is not enough memory available to store the description.

Command Line Parameters

When executing a program, you can pass values from the command line to the C program.These values are called command-line parameters and are important to programs, especially when you want to control the program from outside, rather than hard-coded within the code.

Command line parameters are handled using the main() function parameter, where argc is the number of parameters passed in and argv[] is an array of pointers to each parameter passed to the program.The following is a simple example of checking if the command line provides parameters and performing the appropriate actions based on them:

#include <stdio.h>

int main( int argc, char *argv[] )  
{
   if( argc == 2 )
   {
      printf("The argument supplied is %s\n", argv[1]);
   }
   else if( argc > 2 )
   {
      printf("Too many arguments supplied.\n");
   }
   else
   {
      printf("One argument expected.\n");
   }
}

Using one parameter, compile and execute the code above, which produces the following results:

$./a.out testing
The argument supplied is testing

Using two parameters, compile and execute the code above, which produces the following results:

$./a.out testing1 testing2
Too many arguments supplied.

Compile and execute the code above without passing any parameters, which produces the following results:

$./a.out
One argument expected

It should be noted that the name of the argv[0] stored program, argv[1] is a pointer to the first command line parameter and *argv[n] is the last parameter.If no parameter is provided, argc will be 1; otherwise, if a parameter is passed, argc will be set to 2.

Multiple command line parameters are separated by spaces, but if the parameter itself has spaces, the parameter should be passed inside a double or single quotation mark''.With a space, you can put them in double or single quotation marks, from this point of view.Let's rewrite the above example and pass a command line parameter inside double quotes to the program:

#include <stdio.h>

int main( int argc, char *argv[] )  
{
   printf("Program name %s\n", argv[0]);
 
   if( argc == 2 )
   {
      printf("The argument supplied is %s\n", argv[1]);
   }
   else if( argc > 2 )
   {
      printf("Too many arguments supplied.\n");
   }
   else
   {
      printf("One argument expected.\n");
   }
}

Using a simple space-delimited parameter enclosed in double quotes, compile and execute the code above, which produces the following results:

$./a.out "testing1 testing2"

Progranm name ./a.out
The argument supplied is testing1 testing2

Reference from: https://www.runoob.com/cprogramming/c-tutorial.html

Posted by dannel77 on Fri, 27 Dec 2019 17:43:15 -0800