PDA

View Full Version : C Programming Function Prototypes




cybrscot
Apr 5, 2011, 12:54 AM
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


}

#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");

}



AustinZ
Apr 5, 2011, 01:11 AM
It's at the very least good practice.

Take the following sample 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>.

subsonix
Apr 5, 2011, 02:14 AM
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.

jiminaus
Apr 5, 2011, 03:01 AM
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.

balamw
Apr 5, 2011, 06:17 AM
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.

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

cybrscot
Apr 5, 2011, 07:28 AM
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!!

ChOas
Apr 5, 2011, 07:42 AM
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:


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 ;) ).

balamw
Apr 5, 2011, 07:53 AM
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.
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:
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

lee1210
Apr 5, 2011, 09:11 AM
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.

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

Bill McEnaney
Apr 5, 2011, 09:31 AM
You probably need prototypes when you're going to write mutually recursive functions.

balamw
Apr 5, 2011, 09:39 AM
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

cybrscot
Apr 5, 2011, 10:05 AM
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!!

lee1210
Apr 5, 2011, 10:13 AM
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

Bill McEnaney
Apr 5, 2011, 10:13 AM
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

ulbador
Apr 5, 2011, 10:14 AM
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/

firestarter
Apr 5, 2011, 10:25 AM
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 (http://en.wikipedia.org/wiki/Linker_(computing)).

balamw
Apr 5, 2011, 10:43 AM
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:

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:

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

firewood
Apr 5, 2011, 03:24 PM
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.

cybrscot
Apr 6, 2011, 12:14 AM
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.




#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.

subsonix
Apr 6, 2011, 12:36 AM
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:


int a;
a = 10;


Works, but:


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.

ChOas
Apr 6, 2011, 12:50 AM
I need some help figuring out what is what below...


#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
Apr 6, 2011, 02:14 AM
Thanks for the help!

balamw
Apr 6, 2011, 06:11 AM
cybrscot,

The code you posted is equivalent to:


#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
Apr 6, 2011, 10:06 AM
cybrscot,

The code you posted is equivalent to:


#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

notjustjay
Apr 6, 2011, 10:25 AM
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.

balamw
Apr 6, 2011, 11:23 AM
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.

I do think the example that was posted is particularly inadequate to introducing passing variables by reference when it could very easily have been dealt with as a return value.

#include <stdio.h>

int squareIt(int x) {
return x*x;
}

int main (int argc, const char * argv []) {
int square;
square = squareIt(5);

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

return 0;
}

How would you extend that to create a function that would return both the square and the cube of the argument?

That's one place where passing by reference or complicated data structures can come in.

B

Sydde
Apr 6, 2011, 11:29 AM
[QUOTE=cybrscot;12337809]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./QUOTE]

Why "SquareIt"? This is both trivial and important at the same time. I could write a function named "miffle()" if it struck my fancy, and where ever the compiler finds that name, it would know how to construct the proper object code for the function, and the linker would use that name to figure out how to tie the parts of the program together. Everything would work fine.

But the, if someone else has to deal with my source, or if I have to look at it 18 months later, here is "miffle()", WTH does that mean? If I had named that function "shuffleTheCards()", it would save anyone looking at the source (including forgetful me) a great deal of time later on trying to figure things out.

Sometimes just choosing good descriptive names for a functions and variables is almost as good as writing comments, though doing both is better.

balamw
Apr 6, 2011, 11:37 AM
Sometimes just choosing good descriptive names for a functions and variables is almost as good as writing comments, though doing both is better.

Even more important in Objective-C. This is one of the reasons why I am on the fence about learning C before Obj-C.

C tends to be both terse and dense. Lots of variables named "a" "x" etc..., Objective-C is quite the opposite. verbose and sparse. If you are well versed in C and tend to write terse dense code you'll have a harder time with Obj-C.

EDIT: Evolve your code

Start with what you are familiar with:


#include <stdio.h>

int main (int argc, const char * argv []) {
int square;
square = 5 * 5;

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

return 0;
}


I want to pull out the bit that does the calculation so that I can re-use it. What does it do? It squares an int, so maybe we can call it "squareAnInt" (don't worry about the capitalization, other choices might be square_an_int or SquareAnInt).

Then we get:



#include <stdio.h>

int squareAnInt(int x){
return x*x;
}

int main (int argc, const char * argv []) {
int square;
square = squareAnInt(5);

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

return 0;
}


If I now want to move the code to another file, or move it below main, I need to replace the function declaration with a function prototype. e.g.


int squareAnInt(int intToBeSquared);


Note that intToBeSquared and x don't need to match.

B

Sydde
Apr 6, 2011, 12:01 PM
we can call it "squareAnInt" (don't worry about the capitalization, other choices might be square_an_int or SquareAnInt).

Except of course to bear in mind that C is case-sensitive: calling "squareAnInt" will not work if the original function is named "SquareAnInt".

balamw
Apr 6, 2011, 12:17 PM
Except of course to bear in mind that C is case-sensitive: calling "squareAnInt" will not work if the original function is named "SquareAnInt".

Yes! Once you pick a name you're stuck with it and names that differ only in case represent different things.

square could be an int variable while Square is a float function and SQUARE
is a constant.

This is another reason for verbose names.

square vs. squareFunction vs squareConstant ...

B

notjustjay
Apr 6, 2011, 01:02 PM
C tends to be both terse and dense. Lots of variables named "a" "x" etc...

That's not a C "thing", that just comes down to the programmer's style and the habits they have learned.

At the company I work for there is a coding standard that we must follow for all C/C++ variables in terms of their capitalization and using prefixes to determine whether they are class or parameter variables, e.g.

void CMyClass::SetDate( int pDay, int pMonth, int pYear)
{
cMonth = pMonth;
cDay = pDay;
cYear = pYear;
}

Sydde
Apr 6, 2011, 01:40 PM
That's not a C "thing", that just comes down to the programmer's style and the habits they have learned.

At the company I work for there is a coding standard that we must follow for all C/C++ variables in terms of their capitalization and using prefixes to determine whether they are class or parameter variables, e.g.

void CMyClass::SetDate( int pDay, int pMonth, int pYear)
{
cMonth = pMonth;
cDay = pDay;
cYear = pYear;
}

Yet, when C or C++ is compared to Objective-C,
CMyClass *cMyObject;
// … assuming it has been instantiated …
// the C++ call

cMyObject::SetDate( thisDay, thisMonth, thisYear );

// vs. that method in Objective-C

[cMyObject setDate:thisDay inMonth:thisMonth inYear:thisYear];
the latter naturally lends itself to much greater verbosity and clarity in the source.

balamw
Apr 6, 2011, 02:55 PM
That's not a C "thing", that just comes down to the programmer's style and the habits they have learned.


I agree to an extent, but Many C programmers learned to read and write very terse code. So it tends to self-perpetuate, because that's what they see in books and many other code examples. Unix is full of terseness: commands like tr, sed, awk ... Most of which are written in C. Look at many of the examples in this thread itself. Lots of single character variable names.

This is hard to get away with in Obj-C as Sydde has already shown.

Of course if you learned C in Win32 you might have a Hungarian notation (http://en.wikipedia.org/wiki/Hungarian_notation)habit, which carries its own kind of terseness.

B

Bill McEnaney
Apr 6, 2011, 05:18 PM
Many C programmers learned to read and write very terse code.
True. I wish someone would tell me what was wrong with my two-line loop that looked something like this.

while (fgets(line, sizeof(line), input) != NULL)
puts(line);

I don't try to impress others by writing terse code. I reason the way functional programmers do. So I prefer function evaluation to explicit assignment. I'm fanatical about writing very readable code, too. I write it easily in Pascal because I'm fluent in that language. I write in C when I need to do that, but I still need to learn a lot about it, especially about C coding style.

subsonix
Apr 6, 2011, 05:29 PM
Remember what you see here are dumb examples with variables without meaning. They are meant to be generic, thus a name that means nothing is a better suit. Also a big reason for the long names in Obj-C comes down to a lack of namespace, thus the NS prefix in cocoa. But the size or how descriptive a name is has very little to do with a language in the end and more to do with culture. Look at CoreFoundation for a C api with long descriptive names for example.

chown33
Apr 6, 2011, 05:42 PM
True. I wish someone would tell me what was wrong with my two-line loop that looked something like this.

while (fgets(line, sizeof(line), input) != NULL)
puts(line);
Wrong in what sense: incomprehensible or malfunctioning?

If you're looking for "Why does it malfunction?", then you have two bugs.

1. fgets() doesn't strip newlines. puts() always writes a newline.

As a consequence, you will get doubled line-endings.

2. fgets() may return data that lacks a newline.

Lines that are longer than sizeof(line) will be echoed with a newline that wasn't in the original. For example, if the data was:
Normal line here.
Another normal line.
Really long line here, maybe a few thousand chars, or perhaps a line with a CR-only line-ending.
Back to normal line length.

and sizeof(line) was 50, then the overlong line will end up with a newline at 50, 100, 150, etc.

You can fix both bugs by using fputs() instead of puts(). The comprehensibility isn't necessarily improved thereby.

You could also fix both bugs by using fread() and fwrite(), instead of trying to interpret the data as lines of text.

Bill McEnaney
Apr 6, 2011, 05:55 PM
Remember what you see here are dumb examples with variables without meaning. They are meant to be generic, thus a name that means nothing is a better suit. Also a big reason for the long names in Obj-C comes down to a lack of namespace, thus the NS prefix in cocoa.
People tell me that reading my Pascal programs is like reading prose. So I don't mind long identifiers when they tell you exactly what they stand for. But my two-liner's critic said that such concise code was hard to maintain.

I would think a program would be hard to maintain when its variable names were non-descriptive. Still, I understand your good point about generality, subsonix.

In Scheme, I'd count integers in a list with this function.

(define (count-integers-in some-list)
(length (filter integer? some-list)))

It's concise function that without explicit assignments, and it has no side effects.

jamesarm97
Apr 6, 2011, 06:02 PM
I just had a problem today I spent some time tracking down and it was a missing prototype that caused it.

main() was calling a function something like so:

int i;

i = 1;
SRD_Send(i);

SRD_Send is defined like:

void SRD_Send(byte ch) {
sprintf(buff, "%dSRD", ch);
}

I kept getting "48SR" on the receiving end (RS485, simplified, big communications program). It should have been receiving "1SRD". As soon as I added the prototype void SRD_Send(byte); everything started working properly. I guess main was assuming a different prototype.

balamw
Apr 6, 2011, 06:07 PM
I kept getting "48SR" on the receiving end

Somewhat randomly I would have guessed 49 being that '1' is ASCII 49.

Remember what you see here are dumb examples with variables without meaning. They are meant to be generic, thus a name that means nothing is a better suit.

Yeah, but that attitude also ends up in the beginning C books and people carry it through to their actual projects. I see less of it in the Obj-C books.

I was just looking at some CoreFoundation code someone else had written and it was chockablock with single character variable names resulting from multi-line function calls. :p

B

subsonix
Apr 6, 2011, 06:27 PM
Yeah perhaps, but if we talk about identifiers then it applies both to function names and variables. The names in CoreFoundation is more similar with what you would see in other Apple frame works compared with some older C api's.

Personally I don't mind short names if their context is local in small helper functions, where the context makes the meaning clear. To me it's more important that the function names are descriptive than the variable names, at least for variables that lives for a very short time.

@Bill, I find Scheme intriguing but I haven't been able to wrap my head around it yet. (haven't spent too much time on it though).

Bill McEnaney
Apr 6, 2011, 10:33 PM
@Bill, I find Scheme intriguing but I haven't been able to wrap my head around it yet. (haven't spent too much time on it though).
That weird language. But Apple invented Dylan, an object-oriented Lisp-like language with far fewer fingernail clippings. ;), i.e., parentheses. Python adopted some features for functional programming, and I love that language's list comprehensions. Still, Common Lisp lets you do something that I haven't found in any other programming language. In Common Lisp, you can write functions that take optional arguments. If you don't need the function to use them, you don't pass them to it.

Maybe I should have explained how my Scheme function works. First, the filter function creates a potentially empty list of the integers it finds in some-list. Then the "length" function counts the elements of the potentially empty. In Scheme, there's no "return" statement, partly because a Scheme function's value is usually of the last expression in that function.

lee1210
Apr 7, 2011, 12:00 AM
That weird language. But Apple invented Dylan, an object-oriented Lisp-like language with far fewer fingernail clippings. ;), i.e., parentheses. Python adopted some features for functional programming, and I love that language's list comprehensions. Still, Common Lisp lets you do something that I haven't found in any other programming language. In Common Lisp, you can write functions that take optional arguments. If you don't need the function to use them, you don't pass them to it.

Maybe I should have explained how my Scheme function works. First, the filter function creates a potentially empty list of the integers it finds in some-list. Then the "length" function counts the elements of the potentially empty. In Scheme, there's no "return" statement, partly because a Scheme function's value is usually of the last expression in that function.

I know a number of languages that support optional arguments. Fortran 90, perl, JavaScript... These are only the ones I use every day. C supports this in a funnier way, using variable argument lists.

-Lee

Bill McEnaney
Apr 7, 2011, 02:54 AM
I know a number of languages that support optional arguments. Fortran 90, perl, JavaScript... These are only the ones I use every day. [QUOTE=lee1210;12345509]C supports this in a funnier way, using variable argument lists.
I don't understand the phrase "variable argument lists," Lee. Do you mean that an argument list can be the value of a variable?

jiminaus
Apr 7, 2011, 03:16 AM
I don't understand the phrase "variable argument lists," Lee. Do you mean that an argument list can be the value of a variable?

Variadic functions, that is functions that take a variable number of arguments. Think printf and the like.

balamw
Apr 7, 2011, 05:52 AM
I know a number of languages that support optional arguments. Fortran 90, perl, JavaScript... These are only the ones I use every day. C supports this in a funnier way, using variable argument lists.


MATLAB is fun in that it also supports multiple (optional) return values.

You can define a function that returns [average, max, min, sum, mode, N] and choose to use only the ones you need and it also supports being dynamic about it with "varargin (http://www.mathworks.com/help/techdoc/ref/varargin.html)" and "varargout (http://www.mathworks.com/help/techdoc/ref/varargout.html)"

Kind of an odd way of overloading functions, but quite effective.

B

Bill McEnaney
Apr 7, 2011, 10:44 AM
Variadic functions, that is functions that take a variable number of arguments. Think printf and the like.
I should have thought Lee meant that. After all, I brought up functions that take optional arguments. The phrase "variable functions" confused me, though, because it was ambiguous. I would have written "a function with a change number of arguments" or "a function with a changeable arity," because "arity" means "number of arguments."