Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.
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.

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

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;
}

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:

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

Code:
int squareAnInt(int intToBeSquared);

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

B
 
Last edited:
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".
 
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
 
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;
}
 
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,
Code:
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.
 
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 habit, which carries its own kind of terseness.

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

Code:
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.
 
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.
 
Last edited:
True. I wish someone would tell me what was wrong with my two-line loop that looked something like this.

Code:
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:
Code:
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.
 
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.

Code:
(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.
 
Last edited:
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.
 
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
 
Last edited:
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).
 
Last edited:
@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.
 
Last edited:
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
 
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" and "varargout"

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

B
 
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."
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.