Week 1
C Programming
Introduction - Basics of C programming
Contents
• Introduction to C
• Compilation of C programs
• Syntax
• Data types
• Functions
• Program execution
• I/O standard and File
Introduction - Basics of C programming 2
IEEE Spectrum
2022-08-23
Job listings are of course not the only metrics we look at in Spectrum. A complete list of our sources is here, but
in a nutshell we look at nine metrics that we think are good proxies for measuring what languages people are
programming in. Sources include GitHub, Google, Stack Overflow, Twitter, and IEEE Xplore. The raw data is
normalized and weighted according to the different rankings offered—for example, the Spectrum default ranking
is heavily weighted toward the interests of IEEE members,
Great Idea #1: Abstraction
(Levels of Representation/Interpretation)
High Level Language temp = v[k];
v[k] = v[k+1];
Program (e.g., C) v[k+1] = temp;
Compiler lw x3, 0(x10)
Assembly Language lw x4, 4(x10) Anything can be represented
as bits,
sw x4, 0(x10)
Program (e.g., RISC-V) sw x3, 4(x10) i.e., data or instructions
Assembler 1000 1101 1110 0010 0000 0000 0000 0000
Machine Language 1000 1110 0001 0000 0000 0000 0000 0100
Program (RISC-V) 1010 1110 0001 0010 0000 0000 0000 0000
1010 1101 1110 0010 0000 0000 0000 0100
Hardware Architecture Description al 1
+4
wb
Da e
R
]
[ pc
Reg[rs1]
1
A D
al
u
pc+4
(e.g., block diagrams)
ta 0
u p IM inst[11:7] Ad g 1
pc+4
0 D Reg[rs2] L A
M Da
wb
c E inst[19:15] dr
AddrA Da
Bra 0 d 0
D
ta
nc
Co U Da E
dr
ta mem
1 R
M inst[24:20] Ad Da h ta
Architecture Implementation
m
W M
dr A
ta p.
B B
Logic Circuit Description
inst[31:7]
I . imm[31:0]
G
m
em
(Circuit Schematic Diagrams) n
Introduction - Basics of C programming 4
Introduction to C
• Why C?
• We can write programs that allow us to exploit underlying features of
the architecture
• memory management, special instructions, parallelism
• C and derivatives (C++/Obj-C/C#) still one of the most
popular programming languages after >40 years!
• Both high level and low-level language
Introduction - Basics of C programming 5
Compile
vs
Interpret
Introduction - Basics of C programming 6
Compilation: Overview
• C compilers map C programs directly into
architecture-specific machine code (string of 1s and 0s)
• For C, generally a two parts process of compiling .c files to .o files, then
linking the .o files into executables;
• Assembling is also done (but is hidden, i.e., done automatically, by
default)
Introduction - Basics of C programming 7
Getting started
#include <stdio.h>
int main() {
printf("Hello
World!\n");
}
Introduction - Basics of C programming 8
Compilation
#include <stdio.h> Start with a human readable file containing your
#define HELLO "Hello World!\n" source program and possibly some references
int main() { to libraries
printf(HELLO);
}
Call the C compiler to obtain an executable file,
which is a sequence of numbers that can run
on the target hardware
gcc -std=c99 -c hello.c
gcc -o a.out hello.o
./a.out
Introduction - Basics of C programming 9
Compilation
#include <stdio.h> The compiler works in phases that transform
#define HELLO "Hello World!\n" the program into the executable one step at a
int main() { time.
printf(HELLO);
}
gcc -c hello.c
gcc -o a.out hello.o
./a.out
The last step links libraries, e.g. I/O, to
create a stand alone executable binary
Introduction - Basics of C programming 10
C Compilation Simplified Overview
foo.c bar.c C source files
(text)
Compiler Compiler/assembler
Compiler
combined here
foo.o bar.o Machine code object
files
Pre-built
Linker lib.o object file
libraries
a.out Machine code executable
file
Introduction - Basics of C programming 11
Compilation: Advantages
• Reasonable compilation time: enhancements in compilation
procedure (Makefiles) allow only modified files to be
recompiled
Introduction - Basics of C programming 12
Compilation: Disadvantages
• Compiled files, including the executable, are architecture-
specific, depending on processor type (e.g., MIPS vs. x86 vs.
RISC-V) and the operating system (e.g., Windows vs. Linux vs.
MacOS)
• Executable must be rebuilt on each new system
• I.e., “porting your code” to a new architecture
• “Change → Compile → Run [repeat]” iteration cycle can be slow
during development
• but make only rebuilds changed pieces, and can compile in parallel:
make -j
• linker is sequential though → Amdahl’s Law
Introduction - Basics of C programming 13
C Syntax
Introduction - Basics of C programming 14
C Pre-Processor (CPP)
foo.c CPP foo.i Compiler
• C source files first pass through macro processor, CPP, before compiler sees code
• CPP replaces comments with a single space
• CPP commands begin with “#”
• #include "file.h" /* Inserts file.h into output */
• #include <stdio.h> /* Looks for file in standard location, but no actual difference! */
• #define PI (3.14159) /* Define constant */
• #if/#endif /* Conditionally include text */
• Use –save-temps option to gcc to see result of preprocessing
• Full documentation at: http://gcc.gnu.org/onlinedocs/cpp/
Introduction - Basics of C programming 15
Main
int main()
{ return
‣
‣
0;
C programs must have a main() function
main() called first when the program is started by the OS
} ‣ main() returns an integer
‣ without a return statement, undefined value is returned
‣ The correct signature for main() is:
int main(int argc, const char*
argv[]) { }
C Syntax: main
• To get the main function to accept arguments, use
this:
• int main (int argc, char *argv[])
• What does this mean?
• argc will contain the number of strings on the command line
(the executable counts as one, plus one for each argument).
Here argc is 2:
unix% sort myFile
• argv is a pointer to an array containing the arguments as
strings (more on pointers later).
🗹
Introduction - Basics of C programming 18
Getchar/printf
int c = 0;
while((c = getchar()) !=
EOF) printf("%c", c);
‣ getchar() returns 1 character from “standard input” converted to an int
‣ If the stream is at end-of-file or a read error occurs, EOF is returned
‣ printf() outputs a string to the standard output
‣ printf() takes a format string and a variable numbers of
arguments that are converted to characters according to the
requested format
Looping
int c = getchar();
while(c != EOF) {
printf("%c",
c); c
=
getchar();
}
‣ another way to express the same behavior
‣ in C assignments are expressions, the same program
C Data Types
Introduction - Basics of C programming 22
Data Types
Data types are sets of values along with operations that
manipulate them
For example, (signed) integers in C are made up of the set
of values …, -1,0, 1, 2, … along
with operations such as addition, subtraction, multiplication,
division…
Values must be mapped to data types provided by the
hardware and operations compiled to sequences of hardware
instructions
Byte
A byte = 8 bits
‣ Decimal 0 to 255
‣ Hexadecimal 00 to FF
‣ Binary 00000000 to 11111111
In C:
‣ Decimal constant: 12
‣ Octal constant: 014
‣ Hexadecimal constant: 0xC
http://en.wikipedia.org/wiki/Hexadecimal
Words
Hardware has a `Word size` used to hold integers and
addresses
The size of address words defines the maximum amount of
memory that can be manipulated by a program
Two common options:
‣ 32-bit words => can address 4GB of data
‣ 64-bit words => could address up to 1.8 x 1019
Different words sizes (integral number of bytes, multiples and
fractions) are supported
Addresses
•Addresses specify byte location 32-bit 64-bit
Words Words
Bytes Addr.
in computer memory 0000
Addr
‣ address of first byte in word 0001
=
‣ address of following words differ by 4 ??
0000
0002
Addr
0003
(32-bit) and 8 (64-bit) =
0000
?? 0004
Addr
0005
=
??
0004
0006
0007
0008
Addr
0009
=
??
0008 Addr
0010
= 0011
0008
?? 0012
Addr
0013
=
??
0012
0014
0015
© ?@)-6 A+6@)* @)- B@C4
Data Types
The base data type in C
‣ int - used for integer numbers
‣ float - used for floating point numbers
‣ double - used for large floating point numbers
‣ char - used for characters
‣ void - used for functions without parameters or return value
‣ enum - used for enumerations
The composite types are
‣ pointers to other types
‣ functions with arguments types and a return type
‣ arrays of other types
‣ structs with fields of other types
‣ unions of several types
Qualifiers, Modifiers & Storage
Type specifiers
‣ short - decrease storage size
‣ long - increase storage size
‣ signed - request signed representation
‣ unsigned - request unsigned representation
Type qualifiers
‣ volatile - value may change without being written to by the program
‣ #define GPIO_PORT (*(volatile unsigned long*) 0x012345)
‣ const - value not expected to change
Storage class
‣ static - variable that are global to the program (that file only)
‣ extern - variables that are declared in another file
‣ register – variables that are stored in CPU registers (no address, just register
number is assigned)
Sizes
Type Range (32-bits)
Size in
bytes
signed char −128 to +127 1
unsigned char 0 to +255 1
signed short int −32768 to +32767 2
unsigned short int 0 to +65535 2
signed int −2147483648 to +2147483647 4
unsigned int 0 to +4294967295 4
signed long int −2147483648 to +2147483647 4 or 8
unsigned long int 0 to +4294967295 4 or 8
signed long long int −9223372036854775808 to +9223372036854775807 8
unsigned long long 0 to +18446744073709551615 8
int
float 1×10−37 to 1×1037 4
double 1×10−308 to 1×10308 8
long double 1×10−308 to 1×10308 8, 12, or 16
Character representation
ASCII code (American Standard Code for Information
Interchange): defines 128 character codes (from 0 to 127),
In addition to the 128 standard ASCII codes there are other
128 that are known as extended ASCII, and that are platform-
dependent.
Examples:
‣ The code for ‘A’ is 65
‣ The code for ‘a’ is 97
‣ The code for ‘b’ is 98
‣ The code for ‘0’ is 48
‣ The code for ‘1’ is 49
Get size of a type
Some data types are not interpreted the same on different
platforms, they are machine-dependent
‣ sizeof( x ) returns the size in bytes of the object x
Declarations
The declaration of a variable allocates storage for that variable
and can initialize it
int lower = 3, upper = 5;
char c = ‘\\’, line[10],
he[3] = “he”; float eps
= 1.0e-5;
char arrdarr[10]
[10]; unsigned intx
= 42; char*
ardar[10];
char* a;
void* v;
void foo(const
char[]);
Conversions
What is the meaning of an operation with operands of different
types?
char c; int i; … i + c …
The compiler will attempt to convert data types without losing
information; if not possible emit a warning and convert anyway
Conversions happen for operands, function arguments, return
values and right-hand side of assignments.
Consts and Enums in C
• Constant is assigned a typed value once in the declaration; value can't
change during entire execution of program
const float golden_ratio = 1.618;
const int days_in_week = 7;
const double the_law = 2.99792458e8;
• You can have a constant version of any of the standard C variable types
• Enums: a group of related integer constants. E.g.,
enum cardsuit {CLUBS,DIAMONDS,HEARTS,SPADES};
enum color {RED, GREEN, BLUE};
An example program to demonstrate working of enum in C
#include<stdio.h>
enum week{Mon, Tue, Wed, Thur, Fri, Sat, Sun};
int main(){ enum week day; day = Wed; printf("%d",day); return 0;}
Output: 2
Introduction - Basics of C programming 35
Union
• Unions are used to
• Compress bits of variables
• Complete number of bits can be used by one variable at a time
union number {int a; char c;};
int main() {
union number num;
num.a = 10;
num.c = ‘c’;
return 0; “a” will use all 4 bytes, while “c” will use only one byte
}
4 Bytes
Introduction - Basics of C programming 36
Anonymous union
• A union without a name
• It can not be followed by an object
• Not a type, an unnamed object
• Variable names are unique in scope in which union is defined
void fn() {
union {int x, char c};
x=5;// union’s 4 bytes now store 5
// int x=10; uncomment to get error!
}
Introduction - Basics of C programming 37
C Functions
Introduction - Basics of C programming 38
Typed Functions in C
• You have to declare the type of data you plan to return from a function
• Return type can be any C variable type, and is placed to the left of the
function name
• You can also specify the return type as void
• Just think of this as saying that no value will be returned
• Also need to declare types for values passed into a function
• Variables and functions MUST be declared before used
int number_of_people () { return 3; }
float dollars_and_cents () { return 10.33; }
Introduction - Basics of C programming 39
Functions
Declaration defines the interface of a function; i.e., number and
types of parameters, type of return value
‣ A C prototype is an explicit declaration
int strl(char []);
First use of a function without a preceding prototype
declaration implicitly declares the function
‣ If prototype follows the first use => error
Definition gives the implementation of a function
int strl(char
s[]) { int i
= 0;
while(s[i] != ‘\
0’)
++i; //pre-
increment,i++(post-
Return statement
return [(] [expression] [)];
‣ Terminates the execution of a function and returns control to caller
‣ Parenthesis are optional
‣ Converted to declared return type
‣ Return value can be ignored by caller
Return string from a function
char* AB(){
return “ncdc”;
}
int main(){
char* st =AB();
printf(“%s”,st);
}
Introduction - Basics of C programming 42
Parameter passing
Historically programming languages have offered:
‣ passed by value
‣ passed by reference
‣ passed by value-result
By-value semantics:
‣ Copy of param on function entry, initialized to value passed by caller
‣ Updates of param inside callee made only to copy
‣ Caller’s value is not changed (updates to param not visible after return)
To swap or not to swap?
6
int y = 20, x = 10;
swap(x,y);
void swap(int a, int
x y
b) { int t
= a; 10 20
a = b;
b = t;
} a b
10 20
To swap!
int y = 20, x = 10;
swap(&x,&y);
void swap(int* a,
int* b)t = *a; {
int x y
*a = *b;
*b = t; 10 20
}
a b
Recursive functions
A function can call itself
‣ recursive expression of the function
‣ requires a stopping condition
Example: n!
int fact(int n)
{ return ? 1 : n*fact(n-1); //Conditional operator ?:
} (n<=1)
Assembler
Low-level language that maps directly to hardware
‣ Perform arithmetic on registers or memory
‣ Transfer data between memory and registers
‣ Transfer control to procedures/returns or within a procedure
C Syntax : Control Flow (1/2)
• A statement can be a {} of code or just a standalone statement
• if-else
• if (expression) statement
• if (x == 0) y++;
• if (x == 0) {y++;}
• if (x == 0) {y++; j = j + y;}
• if (expression) statement1 else statement2
• There is an ambiguity in a series of if/else if/else if you don't use {}s,
so use {}s to block the code
• In fact, it is a bad C habit to not always have the statement in {}s,
it has resulted in some amusing errors...
• while
• while (expression) statement
• do statement while (expression);
Introduction - Basics of C programming 48
C Syntax : Control Flow (2/2)
• for
• for (initialize; check; update) statement
• initialize
for(;check;) {update}
• C also has goto
• But it can result in spectacularly bad code if you use it, so don't!
Introduction - Basics of C programming 49
Control flow
• Switch statement in C
• One of the matching case if executed
• If break is not provided all cases are checked
• Switch variable can be of int or char type
#include <stdio.h>
int main() { // Switch variable int var = 1;
// Switch statement switch (var) {
case 1: printf("Case 1 is Matched.");
break;
case 2: printf("Case 2 is Matched.");
break;
case 3: printf("Case 3 is Matched.");
break;
default: printf("Default case is Matched.");
break; }
return 0;}
Introduction - Basics of C programming 50
C Program Execution
Introduction - Basics of C programming 51
...it’s all about the stack
The operating system creates a process
by assigning memory and other resources
‣ Stack: keeps track of the point to which each active
Stack
subroutine should return control when it finishes
executing; stores variables that are local to functions
‣ Heap: dynamic memory for variables that are
created with malloc, calloc, realloc and disposed of Heap
with free
‣ Data: initialized variables including global and Data
static variables, un-initialized variables
Code
‣ Code: the program instructions to be executed
Stack and heap
• Heap is implemented as linked list
• Memory fragmentation
• Can result in memory allocation failure
• Stack is implemented as LIFO
Stack frame of a
function call
main Code
Static storage
Params
Another function
stack frame
Locals
Return Address
Static Link
Dynamic Link
Return
Address
Introduction - Basics of C programming 53
The Stack
Logically it’s a last-in-first-out (LIFO) structure
Two operations: push and pop
Grows ‘down’ from high-addresses to low
Holds “stack frames”, i.e. state of
functions as they execute
‣ top-most (lowest) frame corresponds to
the currently executing function
Stores local variables and address of
the function that needs to be executed
next
C program execution
PC (program counter) points to next machine
instruction to execute
Procedure call:
‣ Prepare parameters
‣ Save state (SP (stack pointer) and PC) and allocate on stack
local variables
‣ Jumps to the beginning of procedure being called
Procedure return:
‣ Recover state (SP and PC (this is return address)) from stack and
adjust stack
‣ Execution continues from return address
First Big C Program: Compute Sines table
#include <stdio.h> PI = 3.141593
#include <math.h> Angle
int main(void) Sine
0
{ 0.000000
int angle_degree; 10
0.173648
double angle_radian, pi, value; 20
0.342020
30
printf("Compute a table of the sine function\n\n"); 0.500000
40
pi = 4.0*atan(1.0); /* could also just use pi = M_PI */ 0.642788
printf("Value of PI = %f \n\n", pi); 50
0.766044
printf("Angle\tSine\n"); 60
angle_degree = 0;/* initial angle value */ 0.866025
70
while (angle_degree <= 360) { /* loop til angle_degree > 360 */ 0.939693
angle_radian = pi * angle_degree / 180.0; 80
0.984808
value = sin(angle_radian); 90
printf ("%3d\t%f\n ", angle_degree, value); 1.000000
… etc …
angle_degree += 10; /* increment the loop index */
}
return 0;
}
🗹
Introduction - Basics of C programming 56
C – File I/O
Introduction - Basics of C programming 57
More General I/O
3
Redirection is done by the OS, not by C
But, C does provide a set of libraries for performing
I/O
One such library:
stdio.h: provides operations to read (getchar and
scanf) and write (putchar and printf) to stdin/stdout
stdio.h
4
printf: Provide a format string and arguments to print
formatted text to the display
scanf: printf in reverse; you give it a format string that
specifies the input to read followed by pointers. Ex:
scanf(“%s %d”, buffer, &int_var)
- Reads in a string and an integer
- Stores them in buffer and int_var respectively
getchar and putchar: get a single character from
stdin or display a single character to stdout
stdio.h (cont.)
5
Also provides more general operations for dealing with
files
A file is an abstraction of a non-volatile memory region:
- Its contents remain after program execution
- C exposes this file abstraction as a FILE*
- You can only access files using interfaces provided
by C
System Calls
7
System calls are services for interacting with the OS
C libraries let users invoke system calls through C
functions System calls are slower than almost any other
function Example:
- I/O operations such as open, close, read, write
- Memory allocation using malloc
- (more on this in future lectures)
File Manipulation
8
There are three basic actions when manipulating files:
- Open
- Read/Write
- Close
When writing to a file, nothing is guaranteed to happen
until it is closed
Opening a File Stream
1
3
FILE* fopen(const char* filename, const char* mode)
- mode can be “r” (read), “w” (write), “a” (append).
- Returns NULL on error. ALWAYS check for errors.
int fileno(FILE *stream) returns the fd associated with stream
// This code opens a file pointer in read
mode char *mode = "r";
FILE* ifp = fopen("in.list", mode);
if(ifp==NULL){printf("Failed");exit(1);}
FILE* ofp = fopen("out.list", "w");
if (ofp==NULL) {...}
Closing Files
1
4
You should ALWAYS close files before program
termination For a file pointer: fclose(FILE *fp)
Why? Two reasons:
1) Output is buffered, closing enforces writing to disk
2) Leaving file pointers open may introduce security
risks
And In Conclusion, …
• C chosen to exploit underlying features of HW
• Key C concepts
• Pointers, arrays, implications for mem management
• C compiled and linked to make executables
• Pros (speed) and Cons (slow edit-compile cycle)
• C looks mostly like Java except
• no OOP, ADTs defined through structs
• 0 (and NULL) FALSE, all else TRUE (C99 bool types)
• Use intN_t and uintN_t for portable code!
• Unitialized variables contain garbage
• “Bohrbugs” (repeatable) vs “Heisenbugs” (random)
🗹
Introduction - Basics of C programming
Lab work
• Introduction to gcc
• Debugging in GDB
Introduction - Basics of C programming 66
Thank You