Welcome, Guest. Please Login
 
  HomeHelpSearchLogin FAQ Radified Ghost.Classic Ghost.New Bootable CD Blog  
 
Page Index Toggle Pages: 1
Send Topic Print
Basic C programming: semicolon usage (Read 5272 times)
Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Basic C programming: semicolon usage
Feb 16th, 2010 at 12:47pm
 
Can somebody tell me why there's no semicolon required at the end of the #include line and/or the main function declaration??

Code:
#include <stdio.h>
int
main(int argc, char *argv[])
{
printf("hello, world\n");
}

A semicolon only seems necessary at the end of the printf statement. Trying to understand the rules/logic/patterns.

Also, some sources include the first solo 'int', while others do not.

Some sources include the text found inside the main function parens, while others do not.

Comment?
 
WWW  
IP Logged
 

Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Re: Basic C programming: semicolon usage
Reply #1 - Feb 16th, 2010 at 1:51pm
 
Here's another question .. regarding the formula to convert fahrenheit to celsius:

Code:
int c = (5/9) * (f - 32) 



Why are there SPACES surrounding the minus sign, but not around the divisor?

Or can you add and remove these spaces at will? (personal preference)??
 
WWW  
IP Logged
 
MrMagoo
Übermensch
*****
Offline


Resident Linux Guru

Posts: 1026
Phoenix, AZ (USA)


Back to top
Re: Basic C programming: semicolon usage
Reply #2 - Feb 16th, 2010 at 2:18pm
 
Rad wrote on Feb 16th, 2010 at 12:47pm:
Can somebody tell me why there's no semicolon required at the end of the #include line and/or the main function declaration??

Semicolons are required at the end of every statement.  #include is a directive, or a special instruction to the compiler.

Rad wrote on Feb 16th, 2010 at 12:47pm:
Also, some sources include the first solo 'int', while others do not.

It is not necessary.

Rad wrote on Feb 16th, 2010 at 12:47pm:
Some sources include the text found inside the main function parens, while others do not.

The variables declared in the parens describe the variables a function expects to be passed to it from whatever called it.  In the case of main(), the calling function would be the shell that executed it, so the variables passed to it would be arguments passed to the program by the command line (or however the program was exectued.)

Rad wrote on Feb 16th, 2010 at 1:51pm:
Why are there SPACES surrounding the minus sign, but not around the divisor?

It's been a while since I'm looked at C seriously, but I think this is just a matter of style/personal preference.
 
WWW  
IP Logged
 
Spanky
Radmeister
**
Offline


Rad's non-Admin Test profile
in Seamonkey

Posts: 73
Same as Rad


Back to top
Re: Basic C programming: semicolon usage
Reply #3 - Feb 16th, 2010 at 2:36pm
 
Thanks, bro.
 
WWW  
IP Logged
 
Dan Goodell
Special Guest
*****
Offline



Posts: 552
N California


Back to top
Re: Basic C programming: semicolon usage
Reply #4 - Feb 16th, 2010 at 6:56pm
 
It's been a long time since I've worked with C, but . . .

Unless they're needed to separate words (e.g., "int c" vs. "intc"), spaces are often just to improve readability.  For instance:

    int c = (5/9) * (f - 32) ;

could just as legitimately be written:

    int c=(5/9)*(f-32);

Note that spaces in a string, though, are literal, so "Hello world" is different from "Hello    world".

Think of the main() function like a subroutine.  If you are passing variables when you call the subroutine, you need to describe what you're passing.  (Note we're not talking about global variables here--which, strictly speaking, you wouldn't be "passing".)  In the case of main(), the variables passed to it come from the command line.

However, in the case of your "Hello world" example, the main() function isn't using any passed variables, so the text between the parens is superfluous and isn't necessary.

And, if I remember my C, the solo "int" isn't really solo, it's part of "int main()", and could be written that way.  If you are passing variables from a subroutine back to the calling function, you should be declaring the type of variable you're passing back (int, char, double, etc).  Since the main() function is not passing anything back, the "int" declaration isn't strictly necessary.




 
 
IP Logged
 
Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Re: Basic C programming: semicolon usage
Reply #5 - Feb 16th, 2010 at 7:59pm
 
Thanks for the clarification.

C is like a gateway language.
 
WWW  
IP Logged
 

Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Re: Basic C programming: semicolon usage
Reply #6 - Feb 16th, 2010 at 8:02pm
 
from Nigel:

Quote:
In respect of http://radified.com/cgi-bin/yabb2/YaBB.pl?num=1266346028
Can somebody tell me why there's no semicolon required at the end of the #include line and/or the main function declaration??

There's no semicolon at the end of #include because there are really two languages in C; one operates at the level of text, and is called the C Preprocessor. All the lines in a program that begin with # are instructions for the preprocessor, which runs before the main C compiler proper. C's model is that conceptually, the C compiler is chewing on one big single file of text and the preprocessor does jobs like combining text files together as part of passing them on to the compiler.

This comes from the original UNIX where C developed, which as mentioned before was a 16-bit machine with 64k of data and program space per process. The preprocessor was actually a separate program (named "cpp") from the C compiler proper (which generally got called something like "cc1") and the two were connected by a UNIX pipe so that the text output of cpp was piped into the cc1 part - using a pipe for this allowed the two programs together to accomplish much more than an integrated one. Users typically newer ran the compiler parts themselves; that arrangement was then managed by a "front end" program which occupied the name "cc" and was what most people interacted with, and thus thought of as the C compiler (and that front end could also handle compiling multiple files, and then involve the linker program "ld" to create a final executable binary).

A semicolon only seems necessary at the end of the printf statement. Trying to understand the rules/logic/patterns

The rules for semicolons are a little arcane from the outside; they are required so that the language can tell one statement apart from the one that comes after it, as C considers all whitespace (newlines, spaces, and such like) as insignificant at the level of the grammar. All statements therefore need something to separate them from the next statement, and it's the semicolon which has that job (for statements that themselves that can contain another statement like "if" conditionals and "for" loops, curly braces will often do the same job).

By the way, remember that at the time, UNIX was unusual in having programs being "text files" and those files being nothing more than sequences of bytes ("bytes" being relatively new at the time too!). Older languages cared more about whitespace - things like column position - because they were input on physical *punchcards*, not typed into a terminal. The 80-column line width of terminals was considered ideal, incidentally because most punchcards were physically 80 characters long.

Also, some sources include the first solo 'int', while others do not.

The "solo int" thing reflects the history of the language, and these days it should be considered absolutely required; not having it is a throwback to the very first versions of C, where the only data types were "char", "int", and "long", pointers and arrays. In that early version of the C language, since most things were of type "int", it was made the *default* data type. So, if a declaration did not include an "int", the fact the data was an int was just assumed. This changed dramatically over the years, especially with the evolution of C++ out of C - it's still possible to omit "int" in a few places, but it's never a good idea and it's something you should avoid doing. Be explicit as possible.

Some sources include the text found inside the main function parens, while others do not.

The text inside the parentheses after "main" is largely another historical change; similarly to the case above with default "int", most function parameters were assumed to have a type of int and so there usually wasn't a need to declare their data types at all. Furthermore, although C generally required you to declare correctly declare at least the number of function arguments correctly, the "main" function is special in that it's where your program started, so it's the one function in all of C where *it didn't matter if you got the arguments wrong*; unlike any other function, nothing bad happened. So, people got lazy and often tended to leave everything out altogether.

This largely changed with the standardization of C during the 1980's; the usage with the data type declarations inside the parentheses comes from the ANSI Standard editions of C (the original C language put them elsewhere if they were present at all, which as noted above they weren't). This change allowed the compiler to do a much better job of type-checking the language to ensure that you called functions with the right number and type of arguments - prior to ANSI C, there was basically no checking at all of this, and almost any program would compile but would happily crash when you ran it. ANSI C tried to move as much as much of this kind of pre-checking as possible into the compiler instead of just letting programs crash, and then C++ built on that much much more and as a result some of the really error-prone old C style is not longer considered legal in C++.

So, although in a pure C program you can still sometimes get away with this kind of thing, a good C program should ideally also be a valid C++ program, by keeping to the subset of C which is also supported in C++. For that reason and for better type-checking, good style should *always* include proper data type declarations for function arguments in the parentheses.
 
WWW  
IP Logged
 
Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Re: Basic C programming: semicolon usage
Reply #7 - Feb 16th, 2010 at 8:03pm
 
cont'd

Quote:
Why are there SPACES surrounding the minus sign, but not around the divisor?

There's no specific requirement one way or the other, it's personal preference (styles on this vary, based on ideas about readability, just as styles of placement of curly braces and the amount to indent lines vary from place to place and person to person).

As noted above, the C compiler isn't really interested in spaces or other kinds of whitespace like newlines. This is defined as the *lexical* part of the language, where the incoming program text is separated into units that are called *tokens*, and the grammar of the language is defined in terms of sequences of tokens. Whitespace do nothing in the language other that keeping identifiers from running into each other, and don't form tokens themselves; but separating identifiers can also be done by any other character, most of which (like the division or substraction signs) do form tokens that are part of the language grammar.

Or can you add and remove these spaces at will? (personal preference)??

Whitespace doesn't matter, so it doesn't matter how much you have. You can add more or fewer based on your particular ideas of what makes the end result more readable.

- Nigel
 
WWW  
IP Logged
 
Dan Goodell
Special Guest
*****
Offline



Posts: 552
N California


Back to top
Re: Basic C programming: semicolon usage
Reply #8 - Feb 16th, 2010 at 9:17pm
 
In response to your,
"Some sources include the text found inside the main function parens, while others do not"
. . .

Nigel said,
"people got lazy and often tended to leave everything out altogether.
[...]
although in a pure C program you can still sometimes get away with this kind of thing,
[...]
good style should *always* include proper data type declarations for function arguments in the parentheses."



Assuming there are function arguments, I agree that their data types should be declared.  But what if there are no arguments?  If there weren't any arguments, I didn't know using "main()" was being lazy.  If main() is not expected to get any arguments from the command line (as in your "Hello world" example), does Nigel mean we should still include the "(int argc, char *argv[])" anyway?  Or is he merely saying that *if* you have an argument, its data type should be declared?



 
 
IP Logged
 
Rad
Radministrator
*****
Offline


Sufferin' succotash

Posts: 4090
Newport Beach, California


Back to top
Re: Basic C programming: semicolon usage
Reply #9 - Feb 17th, 2010 at 11:47am
 
Quote:
By the way, it occurred to me that I should clarify something I wrote earlier:

> [main() is...] the one function in all of C where *it didn't matter if you got the arguments wrong*

That's an overstatement, since one (somewhat unfortunate) aspect of the first C implementation was that you *could* get away with getting the argument list to a function  wrong, as a side-effect of the way the C compiler translated code for the PDP-11 machine architecture. This had one particular practical benefit, which was that it was possible to write functions like printf(), which take a variable number of arguments, something that a number of earlier languages did not allow.

However, this came with a couple of drawbacks; one I mentioned earlier, which is a general lack of safety if you do make a mistake (and the library functions like printf() and its ilk that this made possible are famously error-prone to use, to the point where many organizations absolutely forbid the use of printf() to avoid security vulnerabilities). Another big practical drawback is that on architectures other than the PDP-11, having to support functions being called with the wrong number of arguments meant much less efficient code is generated (which influenced some practicalities of early microcomputer operating systems; both the original Apple Mac and Lisa, and the early versions of Windows all used non-C-based APIs to their core operating system code because the calling conventions of the Pascal programming language didn't have this inefficiency).

Either way, of course, the rule applies.

As to Dan Goodell's follow-up question, since I'm writing anyway I'll try and draw something instructive out of it:

> does Nigel mean we should still include the "(int argc, char *argv[])" anyway?

My point was simply to clarify the rules of the language, since the small examples Rad has been looking at were using this unique aspect of main() even though by doing so, they make it *less* clear how the language works since it's such an exceptional case in specifically allowing this.

This leads to a couple of larger points of learning computer languages; one is that many instructional programmes (and a great deal of on-line documentation, such as the example snippets included with the Windows API document)  use a great many very tiny example programs, but this approach is fraught with problems. In order to avoid introducing extraneous complexity, these snippets of example code have everything possible removed from them, down to using such shoddy short-cuts as leaving out parameter declarations, not doing standard error-checking, and much of that ilk.

The result is that very very few instructional programmes teach good programming style - the kinds of basic techniques, cliches and habits that are absolutely essential for programming at larger (i.e., realistic) scales, writing programs that are *tens of thousands* times larger than those examples. Indeed, even some of the basic design features of some programming languages fail very, very badly to scale up from very small programs to large ones - at the size of small toy examples, these features may appear quite beneficial, but employing them often leads to absolutely diabolical problems.

A related point to this - and one which makes the use of small snippets coded in poor style - is that much of the learning about programming (even by working programmers) is done by imitation - basically "monkey see, monkey do". A great many bugs in a great many Windows programs are caused by developers just cut-and-pasting the MSDN API documentation into their code and modifying it until it works, without taking the time to really understand what the cut-and-pasted snippet is doing. This dynamic is present almost everywhere in the software industry, and it's a big part of why maintaining large, complex bodies of code over a long period of time is so very hard and costly - code being copied without regard to the quality or fitness of the snippets being duplicated, and relentlessly adding *more* code to already complex systems making them more costly to make significant design changes to.

Because of problems like this, and the fact that only a small minority of developers actually have deep knowledge about the languages they use, one aspect of programming language instruction is giving people higher-quality example code to follow - so that if they do learn by rote and lazily cut-and-paste everything they can, as is human nature, at least some of the damage they cause can be mitigated.

All of that is a long-winded preface to explaining the meaning of a sentence involving a statement about "good style". Even though it's not a part of most instruction, and businesses don't appreciate it (or much else about good engineering, for that matter), an important part of software development is developing the habits of good style and relentlessly applying those habits, not necessarily for your own benefit but for the long-term future; both the software itself, and the other people who come to work on it. Good style habits are the equivalent of flossing, or eating your vegetables, or such like - things that to most people might seem a chore to be avoided, but once developed into a habit are no trouble at all.

- Nigel
 
WWW  
IP Logged
 
Page Index Toggle Pages: 1
Send Topic Print