Comma splices
Intro to C
CSE 2421
1
C is procedural, not object-oriented
C is fully compiled (to machine code), not to byte-code
C allows direct manipulation of memory (via pointers)
C does not have garbage collection; the software writer has to do explicit memory management when it is required, and failure to do so can result in significant problems (e.g., memory leaks, where the memory used by the program may grow potentially without bound)
Many of the basic language constructs in C act similarly to the way they work in Java; nonetheless, there are sometimes important differences which need to be understood
C has many nuanced, yet important details
The Joy of C
2
C does not support the notion of Classes or Objects
C does not itself support Encapsulation, as all memory is technically accessible and modifiable by any instruction of an executable
C does not itself support class Inheritance.
C is not an object oriented language, it is procedural.
C does NOT…
3
In this class, we will learn ANSI C, which was originally standardized in 1989 by the American National Standards Institute. This version of C is sometimes referred to as “C89” (also sometimes referred to as “Standard C”). The ISO, or International Standards Organization, also adopted an equivalent version of C in 1990, which is often referred to as C90. Therefore, C89 and C90 are, in effect, equivalent.
There are later versions of C, for example, C99, which differ from ANSI C; for example, they may support features that ANSI C does not support (such as just-in-time declaration, for example).
ANSI C
4
In computer science, we distinguish events that can occur when a program is being compiled or built, called compile time, from events which can occur when the program is actually being executed, or running, called run time.
Certain kinds of errors can be identified (or occur) only at compile time, and while others only at run time.
Errors which occur at compile/build time: syntax errors [these make a program invalid, i.e., in the case of C, not a valid C program], or possibly linkage errors – more on this in a few weeks. In this case, the compiler may or may not generate an executable depending upon the severity of the error.
Compile/build time events are often referred to as static, and run time events as dynamic.
Errors which occur at run time are semantic errors [these do not make a program invalid, because only a valid program can actually be built and then executed]. An example of such an error would be division by zero or some other logic error. The compiler can not discover such an error, but when the program runs, an exception will sometimes be generated (e.g. segmentation fault), and the operating system will terminate the program.
Compile time versus run time
5
5
Four General Categories of Statements in Computer Languages
Declarations (optional in some languages like Python)
Data Movement
Memory to function variables
Function variables to function variables
Function variables to memory
Arithmetic/Logical Operations
Compare something
Calculate something
Control-Flow
Procedure/function calls
Looping
Conditionals
The Bigger Picture
6
6
/* Version 1 */
#include
void main (int argc, char **argv) {
printf(“Hello, ”);
printf(“World!\n”);
}
First C program: Hello World*
/* Version 2 */
#include
int main (void) {
printf(“Hello, World!\n”);
return (0);
}
/* Version 3 */
#include
#include
int main () {
printf(“Hello, World!\n”);
return (EXIT_SUCCESS);
}
7
Notice the lines at the top which begin with the # character. These are known as preprocessor directives, and are used by a translation program called the preprocessor, which is the first program called when you build C source code (in our case, with gcc).
Required Reading: Pointers on C, Chapter 14, The Preprocesssor
Hello programs – Preprocessor
8
Input is from sourcecode.c and output goes to sourcecode.i
Strips all comments from sourcecode.c
Using any #include file preprocessor directives in to the source code file, copy the entire contents of the file in to sourcecode.i
Replace any MACROs.
Preprocessor Tasks
9
test.i contains 1112 lines of text for test.c
Last few lines:
10
Preprocessor output file: test.i
One of the first things the preprocessor does is find, in the area on disk where library files are kept, the file with the name stdio.h or stdlib.h, and copy the contents of that file into the source file. The text in the preprocessor directive (for example “#include
The header file may contain various things, but one thing it usually contains is one or more function prototypes (function declarations – see below), which tell the compiler information about a function (return type and parameters) that it needs to be able to do error checking while compiling the source code.
The header file does not contain the code for any of the functions…only the prototype.
Preprocessor (continued)
11
The file accessed when #include
The preprocessor also removes comments from the source file.
Comments must be enclosed between /* and */
[Note: no single line comments with // are permitted in ANSI C].
Also, the preprocessor for ANSI C is not written to find nested comments, so they are disallowed.
When you write comments in code on exams/homework/etc, correct format is required.
Preprocessor (continued)
12
Another thing the preprocessor does is to replace macros, which are fragments of code, defined in the source file, or in a header file, with the code they are defined to represent
Keep in mind that code in a source file is just text, so macros are just chunks of text.
These macros, or code fragments, are defined with the define preprocessor directive, as follows:
#define string1 string2
string1 cannot contain any white space characters (spaces, tabs, new lines), but string2 can.
An example of this is in Version 3 of the Hello program, where you see EXIT_SUCCESS in the return statement at the end of the function. This macro is defined in the stdlib.h file, and that is why it has been included, using a preprocessor directive, in this version of the program.
Hello programs – EXIT_SUCCESS macro
13
In C, as in Java, statements must generally end with a semi-colon.
Remember, though, that preprocessor directives are NOT statements, and are not terminated with a semi-colon!
C is also case sensitive, so if we have two variables, named num and Num in a C program, the compiler will treat them as two distinct variables.
Hello programs – statements
14
C programs consist of zero or more:
preprocessor directives,
declarations and
definitions
of:
One or more functions (which may contain variable declarations or definitions), and
Zero or more variables declared or defined outside of any function
More on C programs – declarations and definitions
15
Notice that all three versions of the Hello program have a main() function. Every C program must have exactly one main function, and program execution always begins in this function. main() does not necessarily have to be the first function defined in the program file.
Also, notice that, although Java also has a main method, it is in a class, but C has no classes!
In C, technically, we have no methods, only functions. Please pay attention to this distinction.
(remember the correct programming model and terminology for the language being discussed)!
More on C programs – main and other functions
16
A number of statements grouped into a single logical unit are called a function
REMEMEBER: It is required to have a single function ‘main’ in every C program
A function prototype is a function declaration or definition which includes:
Information about the number of arguments
Information about the types of arguments
What type of value the function returns
NO CODE!
Example: float add_floats(float a, float b);
note that there is a ‘;’ at the end rather than {}
Although you are allowed not to specify any information about a function’s arguments in a declaration, it is purely because of backwards compatibility with Old C and should be avoided (poor coding style).
Functions
17
In general, C passes arguments to functions by value
For example, int mult_values (int a, int b);
This insures that the values passed to the function can not be changed in the calling function by the called function.
But, what if that’s what we would like to have happen?
That’s when pointers get involved and we use what is called “pass by reference”.
We’ll look at this when we look at pointers.
Functions
18
Declaration (type information only, no value(s)):
Variable
it tells the compiler the type of a variable, but not its value
can only be declared once in a given block in a C program;
Function
it tells the compiler the return type, and the number and types of its parameters (parameter names are optional), the is called a prototype.
can be declared multiple times in a C program, as long as all of the declarations are consistent (that is, identical with respect to types/# parameters).
Definition (type information and value):
Variable
it tells the compiler the type of the variable and the initial value.
Function
it tells the compiler the return type, parameter types, and the code that should be executed (i.e., the statements) when the function is called.
A given variable or function can only be defined once in a C program.
Note that a definition is also a declaration, since it contains type information.
Declarations and definitions
19
In C:
A variable must be declared (but not necessarily defined) before it can be referenced in a non-declarative statement.
A function must be declared (but not necessarily defined) before it can be referenced in a non-declarative statement (that is, before it can be called or invoked) .
Declarations and definitions (more)
20
Functions consist of one or more blocks (blocks can legally be empty).
A block in ANSI C has this form:
{ /* left curly brace */
Zero or more variable declarations
Zero or more non-declarative statements
} /* right curly brace */
IMPORTANT: In ANSI C, all declarations in the block must precede the first non-declarative statement (i.e., no just-in-time declaration in ANSI C).
Yes, I know just-in-time declarations are more efficient.
Nested blocks are valid in C, but nested functions are not valid (that is, the compiler will generate errors, and will not produce an executable, if your source code contains one or more nested functions).
If you tried to “nest” functions, then you would be defining one function within a block in another function.
Other languages (e.g. ALGOL, MATLAB, C# (after 7.0), Scala) do support this
In C, all functions have file scope. This means that any function declared in a file can be called from anywhere in the same file, after the point at which the function is declared.
In C, variables can have either file scope or block scope depending upon where they are declared. Block scope means that the variable is only accessible by the variable name within the block where it was declared.
The caveat “by the variable name” is important. We will revisit this when we cover pointers.
main and other functions (more)
21
#include
#include
int function_level=0;
int functionA(int a, float b);
int functionB(int a, float b);
main(){
.
.
function_level = ‘M’;
variable2 = functionA(variable1, float_val1);
variable3 = functionB(variable1, float_val1);
}
float functionC(int a, float b);
float new_float;
int functionA(int a, float b){
/* code within not germane*/
}
int functionB(int a, float b){
.
.
function_level=‘B’;
new_float=functionC(a,b);
}
int functionC(int a, float b){
/* code within not germane */
}
File Scope Example
Function prototypes for functionA() and functionB(). They can be used anywhere within this file from this point down.
Function prototype for functionC(). It can be used anywhere within this file from this point down. (i.e. main() can’t call functionC(), but functionA() or functionB() or functionC() could call it.
The variable function_level can be used anywhere within this file from this point down.
The variable new_float can be used anywhere within this file from this point down. (i.e. main() can’t reference new_float, but functionA() or functionB() or functionC() can.
22
22
#include
#include
int main() {
int total = 0; /* variable declaration and definition */
int i; /* variable declaration */
int values[4] = {12, 14, 18, 20}; /* array variable
declaration and definition */
for (i = 0; i < 4; i++) { /* nested block */
total = total + values[i];
}
printf(“The total is: %i\n”, total);
return (EXIT_SUCCESS);
}
Another example C program
23
/docProps/thumbnail.jpeg