PowerPoint Presentation
Introduction to C
Introduction
C is not a “very high level” language, nor a “big” one, and is not specialized to any particular area of application. But its absence of restrictions and its generality make it more convenient and effective for many tasks than supposedly more powerful languages.
Kernighan and Ritchie
With C we can write programs that allow us to exploit underlying features of the architecture
2
C Concepts
These concepts distinguish C from other programming languages that you may know:
Compiler Creates useable programs from C source code
Typed variables Must declare the kind of data the variable will contain
Typed functions Must declare the kind of data returned from the function
Header files (.h) Allows you to declare functions and variables in separate files
Structs Groups of related values
Enums Lists of predefined values
Pointers Aliases to other variables
3
Terminology
Compiler: The program that converts source code into object code (assembly/machine code)
You will be using GCC to compile your source before you can run it.
Debugger: The program that allows you to inspect a program while it is running.
You will be using GDB.
A good alternative is to use print statements everywhere!
Header: File of function and variable declarations
If you want to use functions defined in other files, you must include a corresponding header (.h) file.
Generic C Program Layout
#include
#include “local_files”
#define macro_name macro_expr
/* declare functions */
/* declare global variables and structs */
int main(int argc, char *argv[]) {
/* the innards */
}
/* define other functions */
Dumps other files here (.h and .o)__
← Macro substitutions
Handled by Preprocessor
Remember rules of scope!
(internal vs. external)
Programs start at main()
main() must return int
5
Sample C Code
#include
#define REPEAT 5
int main(int argc, char *argv[]) {
int i;
int n = 5;
for (i = 0; i < REPEAT; i = i + 1) {
printf("hello, world\n");
}
return 0;
}
6
C Syntax: main
To get arguments to the main function, use:
int main(int argc, char *argv[])
What does this mean?
argc contains the number of strings on the command line (the executable path counts as one, plus one for each argument).
argv is an array containing pointers to the arguments as strings (more on pointers later)
7
main Example
$ ./foo hello 87
Here argc = 3 and the array argv contains pointers to the following strings:
argv[0] = "./foo"
argv[1] = "hello"
argv[2] = "87"
We will cover pointers and strings later
8
C Syntax: Variable Declarations
All variable declarations must appear before they are used (e.g. at the beginning of a block of code)
A variable may be initialized in its declaration;
if not, it holds garbage!
Variables of the same type may be declared on the same line
Examples of declarations:
Correct: int x;
int a, b=10, c;
Incorrect: short x=1, float y=1.0;
z = ‘c’;
Imperfect analogy: new locker or desk – there may be leftover garbage that prevents you from using it properly.
9
C Syntax: True or False
No explicit Boolean type in C (unlike Java)
What evaluates to FALSE in C?
0 (integer)
NULL (a special kind of pointer: more on this later)
What evaluates to TRUE in C?
Anything that isn’t false is true
Same idea as in Scheme: only #f is false, anything else is true!
10
C Syntax: Control Flow
Should be similar to what you’ve seen before
if-else
if (expression) statement
if (expression) statement1
else statement2
while
while (expression)
statement
do
statement
while (expression);
11
C Syntax: Control Flow
Should be similar to what you’ve seen before
for
for (initialize; check; update) statement
switch
switch (expression) {
case const1: statements
case const2: statements
default: statements
}
break
12
switch and break
Case statement (switch) requires proper placement of break to work properly
“Fall through” effect: will execute all cases until a break is found
In certain cases, can take advantage of this!
switch(ch){
case ‘+’: … /* does + and - */
case ‘-’: … break;
case ‘*’: … break;
default: …
}
13
Name of array (Note that all elements of this array have the same name, c)
Position number of the element within array c
c[6]
-45
6
0
72
1543
-89
0
62
-3
1
6453
78
c[0]
c[1]
c[2]
c[3]
c[11]
c[10]
c[9]
c[8]
c[7]
c[5]
c[4]
Arrays
Array
Group of consecutive memory locations
Same name and type
To refer to an element, specify
Array name
Position number
Format:
arrayname[ position number ]
First element at position 0
n element array named c:
c[ 0 ], c[ 1 ]...c[ n – 1 ]
Arrays
initialization
declaration
Common Array Mistakes
C has no array-bound checks. You won’t even get a warning! At best you’ll get a segfault when you try to run it.
Do not use sizeof(array), it will return the size of one single element, not the underlying memory size.
SEGFAULT
Strings in C…
Just null terminated char arrays!
For example: “CS3410” is equivalent to:
char str[] = {‘C’,‘S’,‘3’,‘4’,‘1’,‘0’,‘\0’};
Things to note:
strlen(s) does not include the terminal character. Be careful when using memory operations which does include the character!
Pointers
A pointer is a bit-pattern (generally a number) that represents a memory location.
To access the data in the memory that the pointer points to, you dereference the pointer.
The type of a pointer tells the compiler what kind of object to expect when it is dereferenced.
A “double*” is a pointer representing the memory location of a double.
A pointer does not actually create the data it points to. For the pointer to contain data, some other function must create the data it will point to.
This is typically a call to malloc.
Pointers
Pointers: A visual representation
Stack
char* d1
Memory
char* d2
char* d1;
d1 = “CS3410”;
char* d2;
d2 = d1+1;
//d2[0]==‘S’;
d2[6]=?
Address Value
0x07 ‘\0’
0x06 ‘0’
0x05 ‘1’
0x04 ‘4’
0x03 ‘3’
0x02 ‘S’
0x01 ‘C’
Pointers: A visual representation
Stack
int* d1
Memory
int* d2
int* d1;
d1 = {3,4,1,0,9,8,7};
int* d2;
d2 = d1+1;
//d2[0]==4;
d2[6]=?
Address Value
0x18 7
0x14 8
0x10 9
0x0c 0
0x08 1
0x04 4
0x00 3
Pointers to stack variables
Stack
float* d1
local = 42.42
float* d1;
float local = 42.42;
d1 = &local;
*d1 = 25;
local = 25
Agenda
Miscellaneous C Syntax
Arrays
Administrivia
Strings
More Pointers
Pointer Arithmetic
Pointer Misc
23
Pointer Arithmetic
pointer ± number
e.g. pointer + 1 adds 1 something to the address
Compare what happens: (assume a at address 100)
Pointer arithmetic should be used cautiously
Adds 1*sizeof(char)
Adds 1*sizeof(int)
char *p; char a;
int *p; int a;
p = &a;
printf(“%u %u\n”,p,p+1);
100 101
100 104
Pointer Arithmetic
A pointer is just a memory address, so we can
add to/subtract from it to move through an array
p+1 correctly increments p by sizeof(*p)
i.e. moves pointer to the next array element
What about an array of structs?
Struct declaration tells C the size to use, so handled like basic types
What is valid pointer arithmetic?
Add an integer to a pointer
Subtract 2 pointers (in the same array)
Compare pointers (<, <=, ==, !=, >, >=)
Compare pointer to NULL (indicates that the pointer points to nothing)
Everything else is illegal since it makes no sense:
Adding two pointers
Multiplying pointers
Subtract pointer from integer
Pointer Arithmetic
Subtracting pointer is same as multiplying it by -1 and then adding it
int main(void){
int A[] = {5,10};
int *p = A;
printf(“%u %d %d %d\n”, p, *p, A[0], A[1]);
p = p + 1;
printf(“%u %d %d %d\n”, p, *p, A[0], A[1]);
*p = *p + 1;
printf(“%u %d %d %d\n”, p, *p, A[0], A[1]);
}
Question: The first printf outputs 100 5 5 10. What will the next two printf output?
101 10 5 10 then 101 11 5 11
(A)
104 10 5 10 then 104 11 5 11
(B)
100 6 6 10 then 101 6 6 10
(C)
100 6 6 10 then 104 6 6 10
(D)
A[1]
5
10
A[0]
p
27
(REVIEW) Operator Precedence
Prefix (++p) takes effect immediately
Postfix/Suffix (p++) takes effect last
int main () {
int x = 1;
int y = ++x; // y = 2, x = 2
x–;
int z = x++; // z = 1, x = 2
return 0;
}
For precedence/order of execution, see Table 2-1 on p. 53 of K&R
When multiple prefixal operators are present, they are applied from right to left
*–p decrements p, returns val at that addr
— binds to p before * and takes effect first
++*p increments *p and returns that val
* binds first (get val), then increment immediately
Increment and Dereference
Animate them one at a time, brief selection, include the precedence operators
Agenda
C Operators
Arrays
Administrivia
Strings
More Pointers
Pointer Arithmetic
Pointer Misc
30
Pointers and Allocation
When you declare a pointer (e.g. int *ptr;), it doesn’t actually point to anything yet
It points somewhere (garbage; don’t know where)
Dereferencing will usually cause an error
Option 1: Point to something that already exists
int *ptr,var; var = 5; ptr = &var1;
var has space implicitly allocated for it (declaration)
Option 2: Allocate room in memory for new thing to point to (next lecture)
Pointers and Structures
Variable declarations:
struct Point {
int x;
int y;
struct Point *p;
};
struct Point pt1;
struct Point pt2;
struct Point *ptaddr;
Valid operations:
/* dot notation */
int h = pt1.x;
pt2.y = pt1.y;
/* arrow notation */
int h = ptaddr->x;
int h = (*ptaddr).x;
/* This works too */
pt1 = pt2;
Cannot contain an instance of itself, but can point to one
Copies contents
Pointers to Pointers
Pointer to a pointer, declared as **h
Example:
void IncrementPtr(int **h) {
*h = *h + 1;
}
int A[3] = {50, 60, 70};
int *q = A;
IncrementPtr(&q);
printf(“*q = %d\n”, *q);
*q: 60
50
60
70
A
q
q