Calling Functions (newbie)


10 posts
by extravagoose » Wed Jun 13, 2012 4:20 pm
Hi again,

Still going with C and enjoying it!

I've been playing with functions today and have coded up a simple program that gets two numbers from the user and returns them both with the sum, difference and product by calling a function. (pointless I know... but using it to get used to how it works etc).

Anyway, the program seems to compile and run fine :)... but the compiler throws me some warnings which I'm a little confused as to what they mean. Wondering if anyone could provide some clarity here.

My Code:
Code: Select all
#include <stdio.h>

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /* Get the SUM, DIFFERENCE and PRODUCT of the two numbers. */

   for (int i = 0; i <= 3 ; i++)
   {
      calcNumbers(number1, number2, i);
   }
   
   printf("Finished.");
   return 0;
}

void calcNumbers (int num1, int num2, int i)
{
   if (i == 0)
      printf("The SUM of the numbers (%d + %d) = %d\n", num1, num2, num1 + num2);
   
   if (i == 1)
      printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", num1, num2, num1 - num2);
   
   if (i == 2)
      printf("The PRODUCT of the numbers (%d * %d) = %d\n", num1, num2, num1 * num2);
}


The compiler gives me the following:

[steve@Gimli learning]$ gcc -std=c99 03.c -o run_03-test
03.c: In function âmainâ:
03.c:30:3: warning: implicit declaration of function âcalcNumbersâ [-Wimplicit-function-declaration]
03.c: At top level:
03.c:37:6: warning: conflicting types for âcalcNumbersâ [enabled by default]
03.c:30:3: note: previous implicit declaration of âcalcNumbersâ was here

... but the program seems to run ok:
[steve@Gimli learning]$ ./run_03-test
Please enter a number of your choice: 5
Now enter another number of your choice: 5
You entered: 5 and 5

The SUM of the numbers (5 + 5) = 10
The DIFFERENCE of the numbers (5 - 5) = 0
The PRODUCT of the numbers (5 * 5) = 25
Finished.[steve@Gimli learning]$

Sorry for my still total newbie questions... whilst confident in Java... I'm finding C to be a different ballgame...
RPi 1: Hostname: Gimli, 500Gb USB HDD, ArchLinux | ARM.
Main Use: Bit of everything - but mainly web server, Network Storage and C programming.

RPi 2: Hostname tba, awaiting delivery.
User avatar
Posts: 59
Joined: Tue May 29, 2012 2:51 pm
Location: UK
by jecxjo » Wed Jun 13, 2012 4:28 pm
extravagoose wrote:03.c:30:3: warning: implicit declaration of function âcalcNumbersâ [-Wimplicit-function-declaration]


The reason this warning pops up is due to the way the compiler processes the file. Think about how you would read the c file, line by line. First you read #include <stdio.h>. Now we know about all the standard IO functions like printf and scanf.

We read a little further and you call printf("Please enter a number of your choice: ");. We know about the function printf from our #include. No problems so far.

Later we read calcNumbers(number1, number2, i);. We have not heard about this function so what do we do? The compiler will assume that it will eventually hear about this function later on so it prints a warning.

At the end we finally get the definition of calcNumbers and everything is good.

The way to get around this warning is to a) add a function declaration at the begining of the c file or b) move the entire definition of the function before it is used.

Define the function, implementation at the end
Code: Select all
#include <stdio.h>

void calcNumbers (int num1, int num2, int i);

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /* Get the SUM, DIFFERENCE and PRODUCT of the two numbers. */

   for (int i = 0; i <= 3 ; i++)
   {
      calcNumbers(number1, number2, i);
   }
   
   printf("Finished.");
   return 0;
}

void calcNumbers (int num1, int num2, int i)
{
   if (i == 0)
      printf("The SUM of the numbers (%d + %d) = %d\n", num1, num2, num1 + num2);
   
   if (i == 1)
      printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", num1, num2, num1 - num2);
   
   if (i == 2)
      printf("The PRODUCT of the numbers (%d * %d) = %d\n", num1, num2, num1 * num2);
}


In this case the compiler reads void calcNumbers (int num1, int num2, int i); and now hows how the function is to be called. It assumes later on you will provide the actual code for the function.

Define the entire function first
Code: Select all
#include <stdio.h>

void calcNumbers (int num1, int num2, int i)
{
   if (i == 0)
      printf("The SUM of the numbers (%d + %d) = %d\n", num1, num2, num1 + num2);
   
   if (i == 1)
      printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", num1, num2, num1 - num2);
   
   if (i == 2)
      printf("The PRODUCT of the numbers (%d * %d) = %d\n", num1, num2, num1 * num2);
}

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /* Get the SUM, DIFFERENCE and PRODUCT of the two numbers. */

   for (int i = 0; i <= 3 ; i++)
   {
      calcNumbers(number1, number2, i);
   }
   
   printf("Finished.");
   return 0;
}


Both are valid cases, typically depends on how big your c file is and if it makes sense to have a function like main defined at the top of the file before all the "helper" functions.

In cases where a different C file needs to call a function defined here, you would create a Header file (i.e. myfunctions.h) which would include the function defintions and then you would #include it.

myfunctions.h
Code: Select all
#ifndef MYFUNCTIONS_H
#define MYFUNCTIONS_H

void calcNumbers (int num1, int num2, int i);

#endif


myfunctions.c
Code: Select all
#include <stdio.h>

void calcNumbers (int num1, int num2, int i)
{
   if (i == 0)
      printf("The SUM of the numbers (%d + %d) = %d\n", num1, num2, num1 + num2);
   
   if (i == 1)
      printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", num1, num2, num1 - num2);
   
   if (i == 2)
      printf("The PRODUCT of the numbers (%d * %d) = %d\n", num1, num2, num1 * num2);
}


Code: Select all
#include <stdio.h>
#include "myfunctions.h"

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /* Get the SUM, DIFFERENCE and PRODUCT of the two numbers. */

   for (int i = 0; i <= 3 ; i++)
   {
      calcNumbers(number1, number2, i);
   }
   
   printf("Finished.");
   return 0;
}


This is how you would work with larger projects that have multiple C files.
Last edited by jecxjo on Wed Jun 13, 2012 4:36 pm, edited 4 times in total.
IRC (w/ SSL Support): jecxjo.mdns.org
Blog: http://jecxjo.motd.org/code
ProjectEuler Friend: 79556084281370_44d12dd95e92b1d9453aba2bdc94101b
User avatar
Posts: 157
Joined: Sat May 19, 2012 5:22 pm
Location: Ames, IA (USA)
by wallacebiy » Wed Jun 13, 2012 4:31 pm
Dunno if this is helpful or no , but from a reuse point of view , and maybe streamlining and making the end program more flexible , I'd split the operations into three functions ( a sum , difference and product function ) , and return the result to each , handling the print in the main code . It would make it more extendable too , and allow you to later upgrade the program to allow the user to select which he wants , without having to rewrite all your functions ..


( but then I am very bad at coding )
Posts: 56
Joined: Wed May 16, 2012 2:00 pm
by extravagoose » Wed Jun 13, 2012 7:13 pm
jecxjo, that is super helpful! So, I understand now that the compiler would "prefer" the function code to be defined prior to the main program - hence the warnings in my code.

Am I also reading correctly that when it comes to using functions in this way, its better (and tidier) to bung them into a header file and include it? I can see the appeal there straight away in making the code easier to navigate let alone smaller files. I've yet to touch header files (with exception to stdio.h).

So, If I had the header file "stevesHeader.h" Will the compiler see this header file when I run the command gcc -std=c99 functions.c -o run_functions? or would one need to do something to the header files with the compiler?

wallacebiy, I did think that too and indeed makes sense when thinking of reusing code. When I code a Java application I take that approach (unless I'm using a void). I'm just trying to get to grips with using functions (and now so it seems, header files). However, I will probably change the code to what you suggest and actually try doing some more complex things that would definitely reuse the code.

Very grateful for this though, thanks very much :)

I now have the following program which works a treat thanks you help (my code comments could be better though! :P :)

functions.c
Code: Select all
#include <stdio.h>
#include "steveFunctions.h"

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /*
    * Get the SUM, DIFFERENCE and PRODUCT of the two numbers.
    */
   printf("The SUM of the numbers (%d + %d) = %d\n", number1, number2, addNumbers(number1, number2));
   printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", number1, number2, subtractNumbers(number1, number2));
   printf("The PRODUCT of the numbers (%d * %d) = %d\n", number1, number2, multiplyNumbers(number1, number2));
   
   printf("Finished.\n");
   return 0;
}


steveFunctions.h
Code: Select all
#ifndef STEVEFUNCTIONS_H
#define STEVEFUNCTIONS_H

int addNumbers (int num1, int num2)
{
   return num1 + num2;
}

int subtractNumbers (int num1, int num2)
{
   return num1 - num2;
}

int multiplyNumbers (int num1, int num2)
{
   return num1 * num2;
}

#endif
RPi 1: Hostname: Gimli, 500Gb USB HDD, ArchLinux | ARM.
Main Use: Bit of everything - but mainly web server, Network Storage and C programming.

RPi 2: Hostname tba, awaiting delivery.
User avatar
Posts: 59
Joined: Tue May 29, 2012 2:51 pm
Location: UK
by jecxjo » Wed Jun 13, 2012 7:52 pm
extravagoose wrote:Am I also reading correctly that when it comes to using functions in this way, its better (and tidier) to bung them into a header file and include it? I can see the appeal there straight away in making the code easier to navigate let alone smaller files. I've yet to touch header files (with exception to stdio.h).


Its all a judgement call on how big your project is. If you are writing small programs that are only a few pages there is no need. Once you get into larger projects, or projects where you are part of a group then it make sense. But for learning to program in C/C++ its not a big deal to just have a single, large C file.

extravagoose wrote:So, If I had the header file "stevesHeader.h" Will the compiler see this header file when I run the command gcc -std=c99 functions.c -o run_functions? or would one need to do something to the header files with the compiler?


If you have multiple C files you will have to compile them each and then link them together. The linking automatically happens when you have just a single C file to executable.

Code: Select all
gcc -o functions.o functions.s
gcc -o steveFunctions.o steveFunctions.c
gcc -o run_03-test functions.o steveFunctions.o


Add whatever flags you need for other compiler features.

Also as a side note. Your file steveFunction.h is actually layed out as a source file (extension .c) rather than a header file (extension .h). Think of a header file as the table of contents in a book and the source file as the actual chapters. One tells you of the existence of information, the other contains the information.

steveFunctions.h
Code: Select all
#ifndef STEVEFUNCTIONS_H
#define STEVEFUNCTIONS_H

int addNumbers (int num1, int num2);
int subtractNumbers (int num1, int num2);
int multiplyNumbers (int num1, int num2);

#endif


steveFunctions.c
Code: Select all
int addNumbers (int num1, int num2)
{
   return num1 + num2;
}

int subtractNumbers (int num1, int num2)
{
   return num1 - num2;
}

int multiplyNumbers (int num1, int num2)
{
   return num1 * num2;
}


The the compiler performs its "preprocessing" stage all of the #include lines get replaced with the contents of the file to which they are pointing. So after the preprocessing of functions.c you get

Code: Select all
// stdio.h header file....too much to put here.

int addNumbers (int num1, int num2);
int subtractNumbers (int num1, int num2);
int multiplyNumbers (int num1, int num2);

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /*
    * Get the SUM, DIFFERENCE and PRODUCT of the two numbers.
    */
   printf("The SUM of the numbers (%d + %d) = %d\n", number1, number2, addNumbers(number1, number2));
   printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", number1, number2, subtractNumbers(number1, number2));
   printf("The PRODUCT of the numbers (%d * %d) = %d\n", number1, number2, multiplyNumbers(number1, number2));
   
   printf("Finished.\n");
   return 0;
}


Looks just like our "Define first, implement later" layout.
IRC (w/ SSL Support): jecxjo.mdns.org
Blog: http://jecxjo.motd.org/code
ProjectEuler Friend: 79556084281370_44d12dd95e92b1d9453aba2bdc94101b
User avatar
Posts: 157
Joined: Sat May 19, 2012 5:22 pm
Location: Ames, IA (USA)
by Narishma » Wed Jun 13, 2012 8:06 pm
You have to declare a function before it's use, so that the compiler knows the function's signature and can check that you are calling it with the correct number and type of parameters, but you can define the function later if you want, or even in another file.

As for multiple files, you usually put only declarations in your .h files, you put definitions in an associated .c file. In your case, for example, you'd have:

steveFunctions.h
Code: Select all
#ifndef STEVEFUNCTIONS_H
#define STEVEFUNCTIONS_H

int addNumbers (int num1, int num2);
int subtractNumbers (int num1, int num2);
int multiplyNumbers (int num1, int num2);

#endif


steveFunctions.c
Code: Select all
#include "steveFunctions.h"

int addNumbers (int num1, int num2)
{
   return num1 + num2;
}

int subtractNumbers (int num1, int num2)
{
   return num1 - num2;
}

int multiplyNumbers (int num1, int num2)
{
   return num1 * num2;
}


functions.c
Code: Select all
#include <stdio.h>
#include "steveFunctions.h"

int main()
{
   int number1;
   int number2;

   /* Prompt user to choose the 1st number */
   printf("Please enter a number of your choice: ");
   
   /* Assign the 1st number to int number1 */
   scanf("%d", &number1);

   /* Prompt user to choose the 2nd number */
   printf("Now enter another number of your choice: ");
   
   /*Assign the 2nd number to int number2 */
   scanf("%d", &number2);

   /* Display the user's two chosen numbers */
   printf("You entered: %d and %d\n\n",number1,number2);

   /*
    * Get the SUM, DIFFERENCE and PRODUCT of the two numbers.
    */
   printf("The SUM of the numbers (%d + %d) = %d\n", number1, number2, addNumbers(number1, number2));
   printf("The DIFFERENCE of the numbers (%d - %d) = %d\n", number1, number2, subtractNumbers(number1, number2));
   printf("The PRODUCT of the numbers (%d * %d) = %d\n", number1, number2, multiplyNumbers(number1, number2));
   
   printf("Finished.\n");
   return 0;
}


And you'd compile it with:
Code: Select all
gcc -std=c99 -Wall -o functions steveFunctions.c functions.c


BTW, there's a subtle bug in the program in your first post. You're calling the function inside the loop 4 times, not 3. In this case it doesn't matter since the function doesn't do anything with values of i other than 0 to 3, but it could result in unexpected things if you modify the function later.
Posts: 151
Joined: Wed Nov 23, 2011 1:29 pm
by extravagoose » Wed Jun 13, 2012 9:37 pm
jecxjo wrote:Its all a judgement call on how big your project is. If you are writing small programs that are only a few pages there is no need. Once you get into larger projects, or projects where you are part of a group then it make sense. But for learning to program in C/C++ its not a big deal to just have a single, large C file.

Ah, I see - so in this case, it would be pretty pointless to use a header file (other than to learn how they work). Although I have to admit, now seeing how they work and getting what goes in them along with their purpose, I rather like them :)

jecxjo wrote:
If you have multiple C files you will have to compile them each and then link them together. The linking automatically happens when you have just a single C file to executable.

Code: Select all
gcc -o functions.o functions.s
gcc -o steveFunctions.o steveFunctions.c
gcc -o run_03-test functions.o steveFunctions.o


Add whatever flags you need for other compiler features.

Also as a side note. Your file steveFunction.h is actually layed out as a source file (extension .c) rather than a header file (extension .h). Think of a header file as the table of contents in a book and the source file as the actual chapters. One tells you of the existence of information, the other contains the information.


Ah, my bad, I thought the file would include the code too (must get my Java hat off... obviously in Java, you could just dump the code into another class, and invoke it accordingly.). Anyway, have rectified that so it declares the functions. Still makes sense though, so thank you for correcting me there! :)



Narishma wrote:BTW, there's a subtle bug in the program in your first post. You're calling the function inside the loop 4 times, not 3. In this case it doesn't matter since the function doesn't do anything with values of i other than 0 to 3, but it could result in unexpected things if you modify the function later.


:oops: indeed, my logic was flawed... thanks for spotting that!

Thanks again for the help guys... I'm sure i'll be posting more when I get confused again :lol: On the positive side though, I do feel I'm learning this stuff, so hopefully is all worth it :)
RPi 1: Hostname: Gimli, 500Gb USB HDD, ArchLinux | ARM.
Main Use: Bit of everything - but mainly web server, Network Storage and C programming.

RPi 2: Hostname tba, awaiting delivery.
User avatar
Posts: 59
Joined: Tue May 29, 2012 2:51 pm
Location: UK
by jecxjo » Thu Jun 14, 2012 3:13 am
extravagoose wrote:Ah, my bad, I thought the file would include the code too (must get my Java hat off... obviously in Java, you could just dump the code into another class, and invoke it accordingly.).


If you start looking into C++ you will be able to create "inline functions" where the implementation is found in the header file, but there is only specific, very rare cases when you'll do that.

Thanks again for the help guys... I'm sure i'll be posting more when I get confused again :lol: On the positive side though, I do feel I'm learning this stuff, so hopefully is all worth it :)


With all the delays, people complaining about lack of horse power and all...I'm glad to see the Pi has gotten more people talking about development which is awesome.
IRC (w/ SSL Support): jecxjo.mdns.org
Blog: http://jecxjo.motd.org/code
ProjectEuler Friend: 79556084281370_44d12dd95e92b1d9453aba2bdc94101b
User avatar
Posts: 157
Joined: Sat May 19, 2012 5:22 pm
Location: Ames, IA (USA)
by extravagoose » Thu Jun 14, 2012 9:45 am
jecxjo wrote:If you start looking into C++ you will be able to create "inline functions" where the implementation is found in the header file, but there is only specific, very rare cases when you'll do that.


Funny that, a friend has said to me its probably worth investigating C++ which I think I will do at somepoint :)

jecxjo wrote:With all the delays, people complaining about lack of horse power and all...I'm glad to see the Pi has gotten more people talking about development which is awesome.


I don't really understand what there is to complain about... I mean, its a < £30 computer... sure, I've waiting since the beginning of March and finally received my Pi at the end of May... but boy has it been worth the wait!

As for the dev side of things... It surprises me really because although I can code in Java to say a good intermediate level, I never really had fun or enjoyed it. The Pi has kind of changed that in the fact I've had to start from the bottom up. I need to also get to grips with C ahead of a university module in Autumn. My goal is to become confident with programming in C, but more so get to the point where I can start coding things that make use of the GPIO on the Pi.
RPi 1: Hostname: Gimli, 500Gb USB HDD, ArchLinux | ARM.
Main Use: Bit of everything - but mainly web server, Network Storage and C programming.

RPi 2: Hostname tba, awaiting delivery.
User avatar
Posts: 59
Joined: Tue May 29, 2012 2:51 pm
Location: UK
by jecxjo » Thu Jun 14, 2012 1:20 pm
extravagoose wrote:As for the dev side of things... It surprises me really because although I can code in Java to say a good intermediate level, I never really had fun or enjoyed it. The Pi has kind of changed that in the fact I've had to start from the bottom up. I need to also get to grips with C ahead of a university module in Autumn. My goal is to become confident with programming in C, but more so get to the point where I can start coding things that make use of the GPIO on the Pi.


I work exclusively in low level systems, getting hardware and software to work together and developing and modifying operating systems. When I interview possible new employees I'm saddened that everyone coming out of college lately have backgrounds exclusive to GUI development and higher level applications. It seems like tinkering with small systems...talking to I/O to make things move...real hacking on hardware is not encouraged in school. I'm glad the Pi came along and gained so much popularity.
IRC (w/ SSL Support): jecxjo.mdns.org
Blog: http://jecxjo.motd.org/code
ProjectEuler Friend: 79556084281370_44d12dd95e92b1d9453aba2bdc94101b
User avatar
Posts: 157
Joined: Sat May 19, 2012 5:22 pm
Location: Ames, IA (USA)