Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cybrscot

macrumors 6502
Original poster
Dec 7, 2010
282
0
Somewhere in Southeast Asia
My current book, "Learn C on the Mac" says that I should include a function prototype for every function, other than main(). But, in my other book "C Progamming, by K.N. King, I've gotten much further along than I have in this book and it never mentioned function prototypes at all, nor did any of the examples use them.

Learn C on the Mac says that they help compilers know what's coming next in the code, but I never had any trouble when writing programs in my other book with my compiler knowing what's coming next or reading my code? Is this really necessary?

Also please notice my comments below, and try to address my questions please


Code:
}		

#include <stdio.h>

void SayHello( void ) ;   //book says "other than main", isn't this f.proto for               
                                  //main??
int main (int argc, const char* argv []) {  //this is main, right?? SayHello()
	SayHello();                                  //is inside main's {}
	
	return 0;
	
}

void SayHello( void ) {      //why here?? printf isn't a function, it's a stmt
	printf("Hello, world!\n");
	
}
 
It's at the very least good practice.

Take the following sample code:

Code:
int main() {
    int a = 1;
    int b = 2;

    int c = functionA(a);
    functionB(a,b);
    functionC(b);
    (do more stuff...)
    return 0;
}

int functionA(int input) {
   return (input*input);
}

void functionB(int input) {
   (do stuff...)
}

void functionC(int input) {
   (do stuff...)
}

If you don't have the function prototypes many compilers will refuse to compile the code. This is because functionA, functionB, and functionC are called in main() before they have been defined. Having the function prototypes at the top tell the compiler what to expect when the code mentions functionA, functionB, and functionC.

If you moved the main() function in the example to the bottom, the code would compile correctly. In this case, functionA, functionB, and functionC would be defined before any code actually called those functions (e.g. the code in main), and you wouldn't get errors. If you've been lucky so far and only called functions after you defined them you wouldn't get errors, even without function headers.

Now imagine functionA called functionB, functionB called functionC, and functionC called functionA. In this situation you would need the function prototypes for things to compile correctly.

In most cases the function prototypes are placed in a header (.h) file and included in the .c file (e.g. #include "myheader.h"). This also makes it easy for someone to see what functions are included in your module and how to invoke them; instead of wading through all your code in the .c file they can open the .h file and see all the short, concise function prototypes.

===================================

As for your comments:

1. The function prototype is for the SayHello function. Each function needs a function prototype, except for the main function.

2. The function SayHello is not defined inside main(), it is called by main. 'SayHello();' basically means 'go to the SayHello function, execute all its code, and then return to where we were and continue executing. Main is defined from the curly bracket { to the curly bracket } (after 'return 0;'). SayHello is defined from the curly bracket { to the bracket }.

3. printf is a function. The function is defined in the standard I/O library, which is why you did #include <stdio.h>.
 
Last edited:
There are some options, either put the function prototype before main or put the entire function before main, or put it in a header file and include it just like stdio.h.

All you would need to do is to leave it out, and observe the compile error. That should be confirmation that it's necessary in the example.

BTW, regarding your comments, printf() is a function, it's defined in stdio.h so just like your sayhello() prototype it's introduced before main.
 
Last edited:
Just in case it hasn't been clear, the compiler doesn't look ahead in your code.

Take AustinZ's example. When the compiler is look at the line int c = functionA(a) is doesn't look further down your code to see how functionA is defined.

Without a prototype before that line, it can't know how many paramaters there are meant to be, what are their types, and what is the type of the return value.

For example, if functionA was actually defined as float functionA(float input), the compiler would need add instructions to convert the int a into a float and to covert the float return value into an int before assigning to c. Without the prototype, it could never know to do this.
 
Just in case it hasn't been clear, the compiler doesn't look ahead in your code.

Exactly. I just posted something about this in cybrscot's "scope" thread.

The function prototype is exactly analogous to a variable declaration.

You would not assume that this code should work for exactly the same reason.

Code:
int a;
a=b;
int b;

Just like you don't need a separate variable declaration, you don't need a separate function prototype. You can just put the code you need before where you use it, just as you can write int a = b + 1; without int a;.

However, if you get into the habit it will make splitting your code into multiple files so much easier.

B
 
3. printf is a function. The function is defined in the standard I/O library, which is why you did #include <stdio.h>.


So just to clarify a bit more, printf is a funtion, AND.....it's also a string literal AND....it's also a statement right?? At least that's my understanding. I think in this book they said that printf is a statement too. I think in the past on these forums someone also said that printf is a string literal.

If this is the case, then some of these things have different names and we refer to them by whichever name seems to fit the circumstances at the moment.
Which is why I get confused from the books, because it seems sometimes they tell you that something is a function, or that a function is made of stmts, etc. So I end up changing what I think something is. Because I'm new at this, I'm not real confident in my knowledge yet. So I'll go along thinking something is a statement, then later I read it's a function, then I think I must have been wrong before in thinking it was a statement. And I say to myself, "oh I was wrong about that", it's really a function. etc. etc. etc.

So some things in programming can be many things at once right?

I hope somebody tells me I'm right about this!!
 
So just to clarify a bit more, printf is a funtion, AND.....it's also a string literal AND....it's also a statement right?? At least that's my understanding. I think in this book they said that printf is a statement too. I think in the past on these forums someone also said that printf is a string literal.


I hope somebody tells me I'm right about this!!

I wouldn't call it a literal as it doesn't really 'hold' a value. However, it IS a function. Further you can consider every line of code you write as a statement.

So:

Code:
int absValue = abs(-42);

Is a statement. In this statement absValue is the literal and abs() is the function (and -42 is the function argument ;) ).
 
So just to clarify a bit more, printf is a funtion, AND.....it's also a string literal AND....it's also a statement right?? At least that's my understanding. I think in this book they said that printf is a statement too. I think in the past on these forums someone also said that printf is a string literal.

printf is a function.

The function prototype for the function printf is declared in <stdio.h> that is why you include it as AustinZ points out. (EDIT: you should open <stdio.h> for yourself and find the prototype.)

When you call printf from your own code, that is a statement. e.g.
Code:
printf("Hello World!/n");

In that particular case the string "Hello World!/n" is a string literal. It is not a variable holding the string, it literally is the string "Hello World!/n".

Similarly:
Code:
int a = -42;
int absValue_v = abs(a);
int absValue_l = abs(-42);
The argument to abs used to compute absValue_v is a variable named a that contains the value -42. The argument to abs used to compute absValue_l is a literal int whose value is -42.

EDIT: This page http://c.comsci.us/etymology/literals.html defines it as:

Literal constants (often referred to as literals or constants) are explicit invariant values contained with source programs.

Once you type -42 or "Hello World!" that value is explicit (you know what it is) and invariant (it won't change). Other examples are in the link.

B
 
I've arrived embarrassingly late to this particular rodeo, but i thought i'd throw in my 2¢ anyway (I am still regularly baffled by the lack of a "cent" sign in ascii).

A function is a reusable piece of code that may take named arguments and may return a value. Note "may" doesn't mean "must", these pieces are optional. It's been laid out again, but hopefully more explanation doesn't muddy the water:
A prototype describes the return type, name, and the number and type of arguments a function takes:
int myNeatIntReturningFunction(char mySweetCharArgument, int *myExcellentIntPointerArgument, double myDubiousDoubleArgument);
In this case the return type of the function is int, its name is myNeatIntReturningFunction, and it has three arguments, a char, an int *, and a double. You do not have to name your arguments in the prototype, just say what type they are, so:
int myNeatIntReturningFunction(char, int *,double);
would work just as well.

A function implementation starts with a similar looking header, but also contains a block of code between {} that is the "function body", the code that executes when the function is called.
Code:
int myNeatIntReturningFunction(char mySweetCharArgument, int *myExcellentIntPointerArgument, double myDubiousDoubleArgument) {
  int returnValue = 0;
  if(myDubiousDoubleArgument > 87.32) {
    returnValue += 22;
  }

  returnValue -=*myExcellentIntPointerArgument;

  if(mySweetCharArgument >= 'A' && mySweetCharArgument <= 'Z') {
    returnValue = mySweetCharArgument + ('a' - 'A');
  }

  if(returnValue > *myExcellentIntPointerArgument) {
    *myExcellentIntPointerArgument = returnValue;
  }

  return returnValue;
}

Earlier you stated that printf was a "string literal". I'm not sure what you meant, but it certainly isn't that. It's first argument is often a string literal, but could also be a const char * variable. A literal is any of these:
1
5.6f
5.6
'A'
"A"
45L
12U

They are different types of literals, but literal means: exactly this value of a particular data type. This means the value of this expression is known at compile-time. The type of printf is int, so it doesn't even return a string.

When you call a function, you pass it the proper arguments, and you can assign or test its return value. There are times that a function will do something very fixed and specific, like print a banner for example, that requires no input and no return value. This is pretty rare, though, as what really makes functions interesting is they allow you to perform a task on different data and get a result. Often the result will be returned from the function, but (I can't remember if you've covered pointers yet) you can also modify variables that are passed to a function using a pointer.

Again, most of this has been mentioned, but while I'm here... The reason for prototypes is to tell the compiler in advance what a function "looks like". It's going to make assumptions if you don't give it the heads up, and it may give you warnings it should not based on these assumptions, or fail to give you warnings it should. We want to tell the compiler the most we possibly can so it can tell us the most it possibly can about potential problems. Any issue you can catch and fix at compile time is a great boon compared to having to figure it out at runtime. When we tell the compiler about our functions it can check that we're passing the right number and type of arguments, it can tell us about possibly unexpected data-conversion issues with a return type (assigning the result of a function that returns a double to an int, for example), and it's generally happier because it's well-informed.

Functions are absolutely critical to modularity. They allow us to write solid, well-tested code that we're confident performs a task correctly, and then reuse this code all over our program or throughout all of our programs. We depend on system-provided functions to get anything useful done (like your printf example). If you ever find yourself retyping or copying/pasting code from one place to another you should probably be pasting it into a function, genericizing as needed, and using the function instead.

-Lee
 
You probably need prototypes when you're going to write mutually recursive functions.

I think you are right about that.

If function1 calls function2 and function2 calls function1 (defining mutual recursion for those who may not have understood what you meant). You need to tell the compiler what to expect for each function before it's called using prototypes.

So unless you can write your code on a Moebius strip, and your compiler can read it that way you probably need prototypes. :p

B
 
It was mentioned by balamw that I should "open" <stdio.h> and look at the function prototypes included.

I never knew one could "open" <stdio.h>, I just thought it was a piece of code that started off each program, that included the standard library from somewhere deep inside my computer, I had no idea where it was or that you could "look inside" Shows how much I know!! Everyday something new out of left field!! My books have just said it was standard library..... the C Programming by KN King never mentioned func. proto, as of yet, ch 7.

So how do I open it?

Also, my current book, Learn C on the Mac, says explicitly I should include function prototypes for all functions except main (). This is pretty literal, and it never said that printf already has it's func proto included in <stdio.h>. So how was I to know this? Thanks to you guys for telling me that!

This is bringing me to my next dilemma, since even printf is a function, how do I know which functions (other than printf) have their func proto's included in a header, or that I need to write the func proto myself?? ?? Listening to the book, now I'm thinking that it's good practice to use func proto's as they recommend, but after you guys told me that printf was a function, I was wondering why the book didn't show a proto for printf, then I learned from you guys, (not the book) that <stdio.h> already contained the proto for printf!!
 
It was mentioned by balamw that I should "open" <stdio.h> and look at the function prototypes included.

I never knew one could "open" <stdio.h>, I just thought it was a piece of code that started off each program, that included the standard library from somewhere deep inside my computer, I had no idea where it was or that you could "look inside" Shows how much I know!! Everyday something new out of left field!! My books have just said it was standard library..... the C Programming by KN King never mentioned func. proto, as of yet, ch 7.

So how do I open it?

Also, my current book, Learn C on the Mac, says explicitly I should include function prototypes for all functions except main (). This is pretty literal, and it never said that printf already has it's func proto included in <stdio.h>. So how was I to know this? Thanks to you guys for telling me that!

This is bringing me to my next dilemma, since even printf is a function, how do I know which functions (other than printf) have their func proto's included in a header, or that I need to write the func proto myself?? ?? Listening to the book, now I'm thinking that it's good practice to use func proto's as they recommend, but after you guys told me that printf was a function, I was wondering why the book didn't show a proto for printf, then I learned from you guys, (not the book) that <stdio.h> already contained the proto for printf!!

You need to write prototypes for functions YOU write. If you are using a function from a library you only know it's arguments, return type, etc. because it was included in a header. You're not capable of writing the prototype yourself because you don't have the necessary information. When you write a function, always remember that an important step is to put the prototype at the top of your source file or in a header file that you're including.

From terminal, you can type "locate stdio.h". You may end up getting a few matches, but for your purposes any are fine. I'm not sure if you're comfortable with any terminal text editors, but once you've found the location of the file hopefully you can open it in whatever you like.

-Lee
 
If function1 calls function2 and function2 calls function1 (defining mutual recursion for those who may not have understood what you meant). You need to tell the compiler what to expect for each function before it's called using prototypes.
Thanks for explaining what I meant.

So unless you can write your code on a Moebius strip, and your compiler can read it that way you probably need prototypes. :p
What's a moebius strip? If a moebius is going to take off his clothes, I don't want to watch. :eek::p
 
I never knew one could "open" <stdio.h>, I just thought it was a piece of code that started off each program, that included the standard library from somewhere deep inside my computer, I had no idea where it was or that you could "look inside" Shows how much I know!! Everyday something new out of left field!! My books have just said it was standard library..... the C Programming by KN King never mentioned func. proto, as of yet, ch 7.

So how do I open it?

It's in the directory:

/usr/include



This is bringing me to my next dilemma, since even printf is a function, how do I know which functions (other than printf) have their func proto's included in a header, or that I need to write the func proto myself?? ?? Listening to the book, now I'm thinking that it's good practice to use func proto's as they recommend, but after you guys told me that printf was a function, I was wondering why the book didn't show a proto for printf, then I learned from you guys, (not the book) that <stdio.h> already contained the proto for printf!!

Opening the file may not be enough to get a handle on what's in it. It's not really documented. You are better off just plugging stdio.h into google and looking at some of the very well documented reference material that's out there:

http://www.cplusplus.com/reference/clibrary/cstdio/
 
You won't appreciate the value of function prototypes so much when you're writing small self contained programs - their value increases as you build bigger systems with multiple files of source code.

Function prototypes, held in their own .h 'header' files allow you to compile against a function, without the compiler actually parsing that function's code. The result of this is that you can pre-compile all your libraries and separate code modules into 'object' files, and you don't have to keep re-compiling them. This is a BIG WIN if you're writing a large app, or using other people's libraries in your code.

It also enables you to ship libraries as compiled object code + header files, without including the source code too. This is essential for 3rd party libraries who don't necessarily want to share their source code. To use these libraries, you just #include the header file.

The app whose job it is to join all these pieces of individual object code together after compilation is the linker.
 
Last edited:
Opening the file may not be enough to get a handle on what's in it. It's not really documented.

Yeah, perhaps something simpler like stdbool.h from the other thread might be easier to grok. I keep forgetting how complicated I/O (particularly scanf/printf) can really be:

FWIW the prototype for printf in /usr/include/stdio.h on my system is:

Code:
int      printf(const char * __restrict, ...) __DARWIN_LDBL_COMPAT(printf);

When you #include a header file it is basically like copying and pasting the entire document in your .c file at that point from the compiler's perspective. So if the file you #include has #includes of its own, all of that will get processed. So __DARWIN_LDBL_COMPAT is probably defined in one of those #includes.

You can also get something easier to digest from the man pages on your own system. Try "man 3 printf" from Terminal and among other things you'll see:

Code:
int
     printf(const char *restrict format, ...);

What's a moebius strip? If a moebius is going to take off his clothes, I don't want to watch. :eek::p

http://en.wikipedia.org/wiki/Möbius_strip perfectly safe for work.

B
 
Last edited:
My current book, "Learn C on the Mac" says that I should include a function prototype for every function, other than main(). But, in my other book "C Progamming, by K.N. King, I've gotten much further along than I have in this book and it never mentioned function prototypes at all, nor did any of the examples use them.

There are tons of recommended programming practices that aren't really needed, until your programs become much larger and in need of maintenance or reuse, etc.

My preferred suggestion is to forget about them until you encounter your first nasty bug that could have been avoided had you used this software methodology. Then you will know why. Programming is hard enough to learn at all, without having to learn how to program "correctly" at the same time.
 
I need some help figuring out what is what below...

void SquareIt (); is the function prototype right? And it's giving the compiler a preview of the very next line, int main () {, correct?? As my book says to use a f proto before each function.

If I was writing that f.proto, how would I know to write the SquareIt after the void?? Meaning, why chose the word SquareIt?? What does that tell the compiler? That word isn't in the int main () line of code anywhere.




Code:
#include <stdio.h>

	void   SquareIt ( int number, int *squarePtr); //this is a f. proto, yes??
	                                                         
	int main (int argc, const char * argv []) { //the f proto is giving the 
		int   square;                              //compiler a prev of this line??
		
		SquareIt(5, &square); // I understand these are parameters
		
		printf("5 squared is %d.\n", square);
		
		return 0;
		
	}
	
	void	SquareIt(int number, int *squarePtr) { //is this another f. proto?
		*squarePtr = number * number;         //what does this entire piece 
		                                                     //of code do?? It's after the 
	                                                             //program has ended.
}


Do you usually write the f proto after you have written the function? Typically, I have written my programs line by line from the top down, but it seems that one would need to write the function first, than go back and insert a f proto above it.
 
void SquareIt (); is the function prototype right? And it's giving the compiler a preview of the very next line, int main () {, correct?? As my book says to use a f proto before each function.

Yes it's a function prototype. It's telling the compiler that the function SquareIt inside main has an implementation further down. It's known as forward declaration, it's the same principle you use when you declare a variable without defining it, as was mentioned earlier. For example:

Code:
int a;
a = 10;

Works, but:

Code:
a = 10;
int a;

doesn't

Yes SqurareIt is in main, it's just above printf. Without the prototype the compiler won't know what to do with SquareIt, (unless you move the entire function up before main). The name SquareIt is completely arbitrary, it's just an identifier like a variable name. You can make up anything you want as long as you don't give your function a name that already exists.
 
I need some help figuring out what is what below...


Code:
#include <stdio.h>

	void   SquareIt ( int number, int *squarePtr); //this is a f. proto, yes??
	                                                         
// Yup, that is the function prototype. This tells the compiler that a function 
// exists which returns a void and takes a number and a pointer to a number.

// Nothing more.



	int main (int argc, const char * argv []) { //the f proto is giving the 
		int   square;                              //compiler a prev of this line??

// No. This line has nothing to do with the prototype definition above
		
	
	void	SquareIt(int number, int *squarePtr) { //is this another f. proto?

// No. This is the function definition. It is basically the real world function 
// you told the compiler that existed in the function prototype above. 

// As you can see it looks just like the prototype but instead of closing 
// the line with a ; you open a new scope (the function) by typing a {

		*squarePtr = number * number;         //what does this entire piece 
		                                                     //of code do?? It's after the 
	                                                             //program has ended.
}	

// I think you might be thinking about it wrong. Your program isn't executed top-down, 
// line by line. The program can jump between functions and back. See below.

Flow:

1:: SquareIt(5, &square); // I understand these are parameters

2:: printf("5 squared is %d.\n", square);

Just to explain what happens. Your program runs into line 1, it sees the functions SquarIt.

It then jumps in you program to the function squareIt (which you declared below your main) and
executes the code in there. When it's at the end of that function the program goes back to line 2
and executes that.
 
cybrscot,

The code you posted is equivalent to:

Code:
#include <stdio.h>
	                                                         
int main (int argc, const char * argv []) { 
	int   square;                              	
	square = 5 * 5;
		
	printf("5 squared is %d.\n", square);
		
	return 0;
}

They introduced a function to implement the line square = 5*5 that passes the argument (5) by value and square by reference. Then, since the code for the function SquareIt was below main they added a function prototype for SquareIt above main so the compiler would know what was coming.

This is often how code evolves.

You identify a bit of your code that you want to encapsulate for some reason. Either you use it a lot in this code, you want to reuse it in some other code or it is messy and you want to separate it from the main logic flow of your program.

These small scale examples are never ideal as the thing they are equivalent to is often less complex than the version that includes functions and function prototypes.

Note that the function prototype and the function declaration must agree on several things: The function's name, the function's return type, the number of arguments the function takes and the data types of those arguments. They do not have to agree about the argument names, just like when you call the function you don't have to use the same names.

In this case you can read the function prototype as saying: There is a function called SquareIt coming up somewhere. It takes two arguments one int by value and one int by reference and returns nothing. At that point that is all either you or the computer know about this function.

B
 
cybrscot,

The code you posted is equivalent to:

Code:
#include <stdio.h>
	                                                         
int main (int argc, const char * argv []) { 
	int   square;                              	
	square = 5 * 5;
		
	printf("5 squared is %d.\n", square);
		
	return 0;
}



These small scale examples are never ideal as the thing they are equivalent to is often less complex than the version that includes functions and function prototypes.

B

This is exactly what I was thinking after seeing your code. Your code, looks like something I could write already based on my knowledge so far, so I was thinking if it can be done this easily, why bother with the confusion of pointers? Are we just trying to make ourselves look clever? But I get what you mean, it's just an example, albeit one that can be done an easier way, but it's not like they are going to use a huge complicated program to teach a concept to a beginner, or we'd never understand it and have a million more questions. Thanks
 
This is exactly what I was thinking after seeing your code. Your code, looks like something I could write already based on my knowledge so far, so I was thinking if it can be done this easily, why bother with the confusion of pointers? Are we just trying to make ourselves look clever? But I get what you mean, it's just an example, albeit one that can be done an easier way, but it's not like they are going to use a huge complicated program to teach a concept to a beginner, or we'd never understand it and have a million more questions. Thanks

Exactly. There are lots of very good reasons for using pointers, but you won't see them until you start working with bigger, more complex programs. You'll start creating and destroying data on-the-fly (using malloc() for example) and you'll start working with entire data structures instead of simple variables. Once you start getting into object-oriented programming, you'll start using them even more.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.