Functions, Arguments, Parameters and Returns

what are function parameters, arguments, and return types. Difference between function parameters and function arguments

Last Reviewed and Updated on February 7, 2020
Posted by Parveen(Hoven),
Aptitude Trainer and Software Developer

My C/C++ Videos on Youtube

Here is the complete playlist for video lectures and tutorials for the absolute beginners. The language has been kept simple so that anybody can easily understand them. I have avoided complex jargon in these videos.

A function can be thought of as a factory that takes inputs and returns a result. The processing occurs inside the function body. In this tutorial we are discussing the inputs and returns. Please refer the previous chapter for a general discussion of functions.

What are Parameters ?

Parameters describe the inputs that a function accepts. Each parameter has a type associated with it. A function can accept no parameters, one parameter, or more than one parameter. If a function accepts more than one parameter, then they must be separated by a comma. In the following definition, the function showSum accepts two int type of parameters, and they have been separated by a comma.

void showSum (int i, int j)
{
    int sum = i + j;
 
    cout << "Sum = " << sum << endl;
}

In the above example, the parameters have the names i and j. These names are used to access them inside the body of the function. But it is not compulsory for a parameter to have a name. In that case it is called an un-named parameter. Here's an example.

void fx(int)
{
    cout << "Hoven Trainings" << endl;
}
 
int main()
{
    fx(9);
 
    return 0;
}

The above function accepts an un-named parameter of type int. We can think of an un-named parameter as a placeholder that we don't intend to access inside our function body. When a function with dummy parameter(s) is called, then it is compuslory to pass values for the dummy parameters. We can pass any values, but the type must match the type of the un-named parameter. If you omit a dummy argument, the compiler will throw an error.

Dummy Parameters

But what is the use of dummy parameters? What are the use scenarios of such functions? The first one is that a dummy parameter can serve as a type of a flag, or a tag whose presence is required for a different type of processing. In the example below the function "divide" has been written in two ways so that the division can be done in two different ways. This objective can be achieved by using an un-named placeholder parameter. If the function is called by passing three arguments, the division is done in a different way.

void divide(float i, float j)
{
    float result = i / j;
 
    cout << "i/j = " << result << endl;
}
 
void divide(float i, float j, bool)
{
    float result = j / i;
 
    cout << "j/i = " << result << endl;
}
 
int main()
{
    divide(9, 8);
 
    divide(9, 8, false);
 
    return 0;
}

I agree that there are better ways of writing code to achieve the above purpose, but I just wanted to convey that C++ allows us to use this handy tool when we need it. But sometimes, the use of an un-named parameter is the only way out. It's not an option in that case - overloading of postfix and prefix operators is one such case. The prefix operator is overloaded by using one argument, and the postfix by adding a dummy second argument. Following is a templated version of the prefix increment operator.[You can postpone this if you are not yet familiar with operator overloading and templates]

template<class T>
T operator++(T& t)
{
    // code here
}

This is the templated version for the postfix increment operator. Notice the use of second dummy parameter - it has to be an int, the compiler is already programmed that way.

template<class T>
T operator++(T& t, int)
{
    
}

There is another use case scenario for using a dummy parameter. Again, if you are not yet familiar with inheritance, you can skip this example too, and come back later. So, if you are overriding a base class virtual function in a derived class, and do not intend to use a parameter in your implementation, then you can use an un-named parameter so that your signature matches with that of the base class virtual.

Another use case of using an un-named parameter is when you have to use a function as a callback in multi-threaded applications and also in many Win32 API. A callback function is your function that is called by another function. This is usually done to hook your function into another function which is doing some work such as downloading from the internet and informing you about the progress by calling your callback function periodically. The signature of the callback is fixed by the API. So when you hook your function as a callback you have to conform to that signature, and use dummy parameters for the values you donot intend to access in your function.

If you specify a parameter name but do not use it, then your compiler could flag a warning message. Such types of warnings can be avoided by using dummy parameters.

The use of dummy parameters can(but not surely) positively impact the speed of your program because the compiler can choose not to pass any values for the dummy parameters(and hence save machine cycles); but this is entirely dependent on a compiler, and the optimization logic that is wired into it. Moreover, other stories like inlining also play a role during compilation.

If you already know templates, then you can take it as an exercise to explain the following code. Or you can write to me at SALES.HOVEN@GMAIL.COM for an answer.

template<class T>
void fx(T, int x)
{
    
}
 
void gx()
{
    cout << "Hello http://hoventrainings.com" << endl;
}
 
int main()
{
    fx(gx, 7);
 
    fx(9, 7);
 
    return 0;
}

Variable Number of Arguments

It is possible to pass a variable number of arguments to a function. The first argument is compulsory, and it's type must be specified. It can be anything, and of any type. Typically, the first argument is the count of arguments being passed to the function. In the code below the function showArgs accepts a variable number of arguments. The first argument is the count of arguments that you will be passing(it doesn't always have to be the count of args, it can be any convenient value, of suitable type, that will help you obtain the count and type of args being passed to the function; it could be an un-named parameter also if you do not need it), the remaining arguments are specified with an ellipsis. The arguments need not be of the same type; you can pass heterogenous types. The header file stdarg.h must be included apart from others.

#include<stdarg.h>
#include<iostream>

using namespace std;
 
void showArgs(int numArgs, ...)
{
    // lst is list marker. it's type should be
    // va_lst. It is required for accessing
    // the arguments passed
    va_list lst;
 
    // begin the process of accessing arguments
    va_start(lst, numArgs);
 
    for(int x = 0; x < numArgs; x++)
    {
        // successive calls to va_arg read
        // the arguments successively
        // the second parameter should be the type
        // of the argument passed
        cout << va_arg(lst, int) << endl;
    }
 
    // this macro MUST be called
    // to end the processing
    va_end(lst);
 
    return;
}
 
int main()
{
    showArgs(4, 8, 7, 44, -1);
 
    return 0;
}
 

In the above example, the showArgs function is being used to display the arguments passed to it. The first argument is the count of variable arguments, and the remaining are all of the type int.

Passing a Large Amount of Data to a Function

Another more convenient and much used method of passing data to a function is to use a struct that contains various data members. You can add as many data members as you like, which would otherwise have been passed as arguments to your function. So, first you create an instance object of your struct and fill the various members. After that pass the struct as a const reference. This is a practical and very convenient approach of passing data to a function. The following example illustrates the whole concept.

#include <iostream>
 
using namespace std;
 
// define your struct
struct SData
{
    int i;
 
    char c;
 
    // a struct can contain an
    // array also
    int arr[10];
 
    float f;
};
 
// pass your struct as an arg
void fx(const SData& sd)
{
    cout << "i = " << sd.i << endl;
 
    cout << "c = " << sd.c << endl;
 
    // display the array elements
    for(int i = 0; i < sizeof(sd.arr)/sizeof(int); i++)
    {
        cout << "element - " << i ;
        
        cout << " = " << sd.arr[i] ;
        
        cout << endl;
    }
 
    cout << "f = " << sd.f << endl;
 
}
 
int main()
{
    // pack your data into the struct
    SData sd = {7, 'A', {78, 65, -1}, 9.8f};
    
    fx(sd);
 
    return 0;
}

This is a long struct that is used by windows to create fonts. This struct packs a lot of data together, and that data is then passed into various functions and dialogs by the windows. Extracted from MSDN

typedef struct tagLOGFONT {
 LONG lfHeight;
 LONG lfWidth;
 LONG lfEscapement;
 LONG lfOrientation;
 LONG lfWeight;
 BYTE lfItalic;
 BYTE lfUnderline;
 BYTE lfStrikeOut;
 BYTE lfCharSet;
 BYTE lfOutPrecision;
 BYTE lfClipPrecision;
 BYTE lfQuality;
 BYTE lfPitchAndFamily;
 TCHAR lfFaceName[LF_FACESIZE];
} LOGFONT, *PLOGFONT;

Default Arguments

Default arguments, as the name indicates, are those arguments that receive default values, and the caller has the option of not passing any value for those arguments. The default values are specified in the manner shown below. The default value of the last parameter is 'A'. If the caller chooses to skip the last argument, then it is treated as if the default value 'A' was passed. But if the caller passes a value, then the passed value supersedes the default value.

void fx(int i, int k, char c = 'A')
{
    cout << "i = " << i << endl;
 
    cout << "k = " << k << endl;
 
    cout << "c = " << c << endl;
}
 
int main()
{
    // prints 8, -7 and A
    fx(8, -7);
 
    // prints 8, -7 and C
    fx(8, -7, 'C');
 
    return 0;
}

The default parameters must all be stacked at the end of the parameter list. For example if a function accepts ten parameters, and you default out the seven-th one, then you must also provide the default values for the eight-th, nine-th and the ten-th parameters.

Returns from a Function

A function can return a value after processing the inputs. This value may be the end result of a calculation, or it may also be an indicator of success or failure of an operation. The return keyword is used to return the value from a function. There are some important restrictions on the return type -

  1. If a function doesn't return anything then the return type should be void.
  2. The returned value from a function must be of the same type(or convertible to) as the return type.
  3. A function take an array as a parameter, but cannot return an array. But it can return a pointer to an array.
  4. A function cannot also return a function, but it can return a pointer to a function or a lambda expression.[Lambda expressions are beyond the scope of this tutorial]

The return type of a function can be specified on the right side also. This is done when the return type of a function has to be determined as based on the template parameters. For example, in the code below the return type of the function will be an int if the arguments are of the type "int", and float if they are of the float type, and so on. The return type depends on the template parameter T. In such cases we specify the return with auto keyword, and on the right side use an arrow with the decltype keyword. The decltype keyword is used for expressing the fact that the type has to be deduced or inferred from the type of the identifier written in braces(), like we have t below.

template<class T>
auto Square(T t) -> decltype(t)
{
 return t * t; 
}
 
int main()
{
    cout << Square(9) << endl;
 
    cout << Square(9.8f) << endl;
 
    return 0;
}

Below is a simpler example of using the auto keyword with decltype. In the code below the type of i is obviously an int, but when you have an overloaded operator that returns an object of some other type, then this keyword comes very handy. But as per C++14 the auto keyword alone is sufficient, we donot need decltype on the right side.

auto fx(int i) -> decltype(i)
{
    return i;
}

Alternatives for Returning Data from a Function

One alternative is to return a struct from a function. This struct can pack as much data as you wish. Here is an example that shows how you can get an int and a char out of a function.

#include <iostream>
 
using namespace std;
 
// define your struct
struct SData
{
    int i;
 
    char c;
};
 
// return your struct
SData fx()
{
    SData sd;
 
    cout << "Enter a number: ";
 
    cin >> sd.i;
 
    cout << "Enter a char: ";
 
    cin >> sd.c;
 
    // return the entire struct as a copy
    return sd;
}
 
int main()
{
    SData sd = fx();
    
    cout << "sd.i = " << sd.i << endl;
 
    cout << "sd.c = " << sd.c << endl;
 
    return 0;
}

An obvious problem with the above approach is that the data is passed as a copy from the function - it has a memory overhead. This problem can be solved by passing a struct as an arg either as a reference or as a pointer. The struct would then act as an output parameter. In the following example a struct is being used both as an input and output parameter.

// define your struct
struct SData
{
    int i;
 
    int j;
 
    int result;
};
 
// pass your struct
void fx(SData& sd)
{
    cout << "Enter p for product, s for sum:";
 
    char k;
 
    cin >> k;
 
    switch(k)
    {
    case 'p':
    case 'P':
        {
            sd.result = sd.i * sd.j;
        }
        break;
 
    case 's':
    case 'S':
        {
            sd.result = sd.i + sd.j;
        }
        break;
 
    default:
        cout << "Unsupported operation" << endl;
    }
 
    return;
}
 
int main()
{
    const int NULLDATA = INT_MAX;
 
    // fill the input members of the struct
    // leave the result as NULLDATA
    // any value such as INT_MAX can be used
    // as NULLDATA
    SData sd = {8, 9, NULLDATA};
 
    fx(sd);
 
    cout << "Result = " << sd.result << endl;
 
    return 0;
}

Miscellaneous Points

  1. Parameter vs Arguments: Parameter refers to the identifier names as they appear in the function definition. The arguments refers to the concrete values or data being passed into the function. In the code below, i and j are the parameters and 8 and 9 are the arguments.
    int sum(int i, int j)
    {
        return i + j;
    }
     
    int main()
    {
        sum(8, 9);
     
        return 0;
    }
  2. void as a parameter: void can appear as the sole placeholder to a function to indicate that the function doesn't take any parameters.
    int fx(void)
    {
        return 5;
    }

    You can express the same thing by simply using the round brackets as shown below. Both the methods are same in C++. But the former is the preferred method in traditional C.

    int fx()
    {
        return 5;
    }

Classroom Training

Classroom training in C/C++ is available at our training institute. Click here for details. You can also register yourself here.

Video Tutorial

We have created a video tutorial that can be downloaded and watched offline on your windows based computer. It is in the form of an exe file. No installation is required, it runs by double clicking the file. Since the exe file is hosted on the Google Drive, it should be very safe because Google itself checks for any virus or malware. The video can be watched offline, no internet is required.

Pricing

This single video will cost you USD $5. When you download the video, you will be able to watch the first few minutes for free, as a sample. The video app will prompt you for payment through PayPal and other payment options. If you want ALL VIDEOS, NOT JUST THIS ONE then go here: Complete Set of C/C++ Video Tutorials The entire set is priced at USD $50.

Screenshots

This is a screenshot of the software that should give you a good idea of the available functionality. Click on the image to see a larger view.screenshot of the video being played in the software

Installation

This software doesn't require any installation. Just download and double-click to run it. It doesn't require administrative priviliges to run. It runs in limited access mode, so should be very safe.

supports windows xp and later Supported Operating Systems

These videos can be run on 32-bit as well as 64-bit versions of the Microsoft Windows Operating Systems. Windows XP and all later OS are supported. If you want to run it on Windows XP and Windows Vista, then you must also have the .NET Framework Version 3.5 installed on your machines. Those users who have Windows 7 and later donot have to worry because these operating systems already have the .NET Framework installed on them.

Download Links

IMPORTANT NOTE: This download contains ONLY ONE video. The video is about the topic of this tutorial.

Want ALL Videos? If you want ALL VIDEOS, NOT JUST THIS ONE then go here: Complete Set of C/C++ Video Tutorials. TIP: If you plan to buy these videos, then it would be more economical to buy the entire set.

DISCLAIMER: Even though every care has been taken in making this software bug-free, but still please take a proper backup of your PC data before you use it. We shall not be responsible for any damages or consequential damages arising out of the use of this software. Please use it solely at your own risk.

Please download the software here.
download the video Functions, Arguments, Parameters and Returns



Creative Commons License
This Blog Post/Article "Functions, Arguments, Parameters and Returns" by Parveen (Hoven) is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.
Updated on 2020-02-07. Published on: 2015-10-05