Instant Download Beej S Guide To C Programming Brian Beej Jorgensen Hall PDF All Chapter

Download as pdf or txt
Download as pdf or txt
You are on page 1of 64

Full download test bank at ebookmeta.

com

Beej s Guide to C Programming Brian Beej Jorgensen


Hall

For dowload this book click LINK or Button below

https://ebookmeta.com/product/beej-s-guide-to-c-
programming-brian-beej-jorgensen-hall-4/

OR CLICK BUTTON

DOWLOAD EBOOK

Download More ebooks from https://ebookmeta.com


More products digital (pdf, epub, mobi) instant
download maybe you interests ...

Beej s Guide to C Programming Brian Beej Jorgensen Hall

https://ebookmeta.com/product/beej-s-guide-to-c-programming-
brian-beej-jorgensen-hall-5/

Beej s Guide to C Programming Brian Beej Jorgensen Hall

https://ebookmeta.com/product/beej-s-guide-to-c-programming-
brian-beej-jorgensen-hall-6/

Beej s Guide to C Programming Brian Beej Jorgensen Hall

https://ebookmeta.com/product/beej-s-guide-to-c-programming-
brian-beej-jorgensen-hall/

Beej s Guide to C Programming Brian Beej Jorgensen Hall

https://ebookmeta.com/product/beej-s-guide-to-c-programming-
brian-beej-jorgensen-hall-4/
Beej s Guide to C Programming Brian Beej Jorgensen Hall

https://ebookmeta.com/product/beej-s-guide-to-c-programming-
brian-beej-jorgensen-hall-3/

Effective Perl Programming 2nd Edition Joseph N Hall


Joshua Mcadams Brian D Foy

https://ebookmeta.com/product/effective-perl-programming-2nd-
edition-joseph-n-hall-joshua-mcadams-brian-d-foy/

Software Testing A Craftsman s Approach 5th Edition


Paul C. Jorgensen

https://ebookmeta.com/product/software-testing-a-craftsman-s-
approach-5th-edition-paul-c-jorgensen/

C Programming Language The Beginner s Guide 2020th


Edition Unknown

https://ebookmeta.com/product/c-programming-language-the-
beginner-s-guide-2020th-edition-unknown/

Let Us C Authentic guide to C programming language 19th


Edition Yashavant Kanetkar

https://ebookmeta.com/product/let-us-c-authentic-guide-to-c-
programming-language-19th-edition-yashavant-kanetkar/
Beej’s Guide to C Programming

Brian “Beej Jorgensen” Hall

v0.9.13, Copyright © March 29, 2023


Contents

1 Foreword 1
1.1 Audience . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.2 How to Read This Book . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.3 Platform and Compiler . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.4 Official Homepage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.5 Email Policy . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.6 Mirroring . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.7 Note for Translators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.8 Copyright and Distribution . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.9 Dedication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3

2 Hello, World! 5
2.1 What to Expect from C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
2.2 Hello, World! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
2.3 Compilation Details . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
2.4 Building with gcc . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.5 Building with clang . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.6 Building from IDEs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8
2.7 C Versions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9

3 Variables and Statements 11


3.1 Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1.1 Variable Names . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3.1.2 Variable Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
3.1.3 Boolean Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3.2 Operators and Expressions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.1 Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.2 Ternary Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
3.2.3 Pre-and-Post Increment-and-Decrement . . . . . . . . . . . . . . . . . . . . . 15
3.2.4 The Comma Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2.5 Conditional Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2.6 Boolean Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 16
3.2.7 The sizeof Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3 Flow Control . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
3.3.1 The if-else statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 18
3.3.2 The while statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
3.3.3 The do-while statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
3.3.4 The for statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
3.3.5 The switch Statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22

4 Functions 25
4.1 Passing by Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
4.2 Function Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 27
4.3 Empty Parameter Lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28

5 Pointers—Cower In Fear! 29
5.1 Memory and Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
5.2 Pointer Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31

ii
CONTENTS iii

5.3 Dereferencing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.4 Passing Pointers as Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
5.5 The NULL Pointer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.6 A Note on Declaring Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
5.7 sizeof and Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35

6 Arrays 37
6.1 Easy Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
6.2 Getting the Length of an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.3 Array Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
6.4 Out of Bounds! . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.5 Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
6.6 Arrays and Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.6.1 Getting a Pointer to an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
6.6.2 Passing Single Dimensional Arrays to Functions . . . . . . . . . . . . . . . . . 42
6.6.3 Changing Arrays in Functions . . . . . . . . . . . . . . . . . . . . . . . . . . 43
6.6.4 Passing Multidimensional Arrays to Functions . . . . . . . . . . . . . . . . . . 44

7 Strings 45
7.1 String Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.2 String Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.3 String Variables as Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
7.4 String Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 46
7.5 Getting String Length . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
7.6 String Termination . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 47
7.7 Copying a String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48

8 Structs 51
8.1 Declaring a Struct . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
8.2 Struct Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.3 Passing Structs to Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
8.4 The Arrow Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 53
8.5 Copying and Returning structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
8.6 Comparing structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54

9 File Input/Output 55
9.1 The FILE* Data Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
9.2 Reading Text Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
9.3 End of File: EOF . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
9.3.1 Reading a Line at a Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
9.4 Formatted Input . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
9.5 Writing Text Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
9.6 Binary File I/O . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
9.6.1 struct and Number Caveats . . . . . . . . . . . . . . . . . . . . . . . . . . . 60

10 typedef: Making New Types 63


10.1 typedef in Theory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.1.1 Scoping . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.2 typedef in Practice . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.2.1 typedef and structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
10.2.2 typedef and Other Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
10.2.3 typedef and Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
10.2.4 typedef and Capitalization . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
10.3 Arrays and typedef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66

11 Pointers II: Arithmetic 67


11.1 Pointer Arithmetic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
11.1.1 Adding to Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
11.1.2 Changing Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 68
iv CONTENTS

11.1.3 Subtracting Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69


11.2 Array/Pointer Equivalence . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
11.2.1 Array/Pointer Equivalence in Function Calls . . . . . . . . . . . . . . . . . . . 70
11.3 void Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71

12 Manual Memory Allocation 75


12.1 Allocating and Deallocating, malloc() and free() . . . . . . . . . . . . . . . . . . 75
12.2 Error Checking . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
12.3 Allocating Space for an Array . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
12.4 An Alternative: calloc() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
12.5 Changing Allocated Size with realloc() . . . . . . . . . . . . . . . . . . . . . . . 78
12.5.1 Reading in Lines of Arbitrary Length . . . . . . . . . . . . . . . . . . . . . . 79
12.5.2 realloc() with NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
12.6 Aligned Allocations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 81

13 Scope 83
13.1 Block Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.1.1 Where To Define Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
13.1.2 Variable Hiding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
13.2 File Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
13.3 for-loop Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
13.4 A Note on Function Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

14 Types II: Way More Types! 87


14.1 Signed and Unsigned Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
14.2 Character Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
14.3 More Integer Types: short, long, long long . . . . . . . . . . . . . . . . . . . . . 89
14.4 More Float: double and long double . . . . . . . . . . . . . . . . . . . . . . . . 91
14.4.1 How Many Decimal Digits? . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
14.4.2 Converting to Decimal and Back . . . . . . . . . . . . . . . . . . . . . . . . . 93
14.5 Constant Numeric Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
14.5.1 Hexadecimal and Octal . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
14.5.2 Integer Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
14.5.3 Floating Point Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96

15 Types III: Conversions 99


15.1 String Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
15.1.1 Numeric Value to String . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
15.1.2 String to Numeric Value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
15.2 char Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102
15.3 Numeric Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.3.1 Boolean . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.3.2 Integer to Integer Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.3.3 Integer and Floating Point Conversions . . . . . . . . . . . . . . . . . . . . . 103
15.4 Implicit Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
15.4.1 The Integer Promotions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
15.4.2 The Usual Arithmetic Conversions . . . . . . . . . . . . . . . . . . . . . . . . 104
15.4.3 void* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
15.5 Explicit Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
15.5.1 Casting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105

16 Types IV: Qualifiers and Specifiers 107


16.1 Type Qualifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
16.1.1 const . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
16.1.2 restrict . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 109
16.1.3 volatile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
16.1.4 _Atomic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
16.2 Storage-Class Specifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
16.2.1 auto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 110
CONTENTS v

16.2.2 static . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111


16.2.3 extern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
16.2.4 register . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 112
16.2.5 _Thread_local . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113

17 Multifile Projects 115


17.1 Includes and Function Prototypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
17.2 Dealing with Repeated Includes . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117
17.3 static and extern . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118
17.4 Compiling with Object Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118

18 The Outside Environment 119


18.1 Command Line Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 119
18.1.1 The Last argv is NULL . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
18.1.2 The Alternate: char **argv . . . . . . . . . . . . . . . . . . . . . . . . . . 121
18.1.3 Fun Facts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
18.2 Exit Status . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122
18.2.1 Other Exit Status Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
18.3 Environment Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
18.3.1 Setting Environment Variables . . . . . . . . . . . . . . . . . . . . . . . . . . 125
18.3.2 Unix-like Alternative Environment Variables . . . . . . . . . . . . . . . . . . . 125

19 The C Preprocessor 127


19.1 #include . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
19.2 Simple Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
19.3 Conditional Compilation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 128
19.3.1 If Defined, #ifdef and #endif . . . . . . . . . . . . . . . . . . . . . . . . . 128
19.3.2 If Not Defined, #ifndef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 129
19.3.3 #else . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130
19.3.4 General Conditional: #if, #elif . . . . . . . . . . . . . . . . . . . . . . . . 130
19.3.5 Losing a Macro: #undef . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
19.4 Built-in Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
19.4.1 Mandatory Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 132
19.4.2 Optional Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133
19.5 Macros with Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
19.5.1 Macros with One Argument . . . . . . . . . . . . . . . . . . . . . . . . . . . 134
19.5.2 Macros with More than One Argument . . . . . . . . . . . . . . . . . . . . . . 135
19.5.3 Macros with Variable Arguments . . . . . . . . . . . . . . . . . . . . . . . . . 136
19.5.4 Stringification . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
19.5.5 Concatenation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
19.6 Multiline Macros . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
19.7 Example: An Assert Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
19.8 The #error Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
19.9 The #pragma Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
19.9.1 Non-Standard Pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 139
19.9.2 Standard Pragmas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
19.9.3 _Pragma Operator . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
19.10 The #line Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
19.11 The Null Directive . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 141

20 structs II: More Fun with structs 143


20.1 Initializers of Nested structs and Arrays . . . . . . . . . . . . . . . . . . . . . . . 143
20.2 Anonymous structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
20.3 Self-Referential structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 145
20.4 Flexible Array Members . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
20.5 Padding Bytes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
20.6 offsetof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
20.7 Fake OOP . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149
20.8 Bit-Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
vi CONTENTS

20.8.1 Non-Adjacent Bit-Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151


20.8.2 Signed or Unsigned ints . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
20.8.3 Unnamed Bit-Fields . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 151
20.8.4 Zero-Width Unnamed Bit-Fields . . . . . . . . . . . . . . . . . . . . . . . . . 152
20.9 Unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
20.9.1 Unions and Type Punning . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
20.9.2 Pointers to unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
20.9.3 Common Initial Sequences in Unions . . . . . . . . . . . . . . . . . . . . . . 154
20.10 Unions and Unnamed Structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
20.11 Passing and Returning structs and unions . . . . . . . . . . . . . . . . . . . . . . 157

21 Characters and Strings II 159


21.1 Escape Sequences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
21.1.1 Frequently-used Escapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 159
21.1.2 Rarely-used Escapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
21.1.3 Numeric Escapes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161

22 Enumerated Types: enum 163


22.1 Behavior of enum . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
22.1.1 Numbering . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163
22.1.2 Trailing Commas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
22.1.3 Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
22.1.4 Style . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
22.2 Your enum is a Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164

23 Pointers III: Pointers to Pointers and More 167


23.1 Pointers to Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 167
23.1.1 Pointer Pointers and const . . . . . . . . . . . . . . . . . . . . . . . . . . . . 169
23.2 Multibyte Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
23.3 The NULL Pointer and Zero . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
23.4 Pointers as Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
23.5 Casting Pointers to other Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . 172
23.6 Pointer Differences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174
23.7 Pointers to Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 174

24 Bitwise Operations 177


24.1 Bitwise AND, OR, XOR, and NOT . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
24.2 Bitwise Shift . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177

25 Variadic Functions 179


25.1 Ellipses in Function Signatures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 179
25.2 Getting the Extra Arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180
25.3 va_list Functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
25.4 Library Functions That Use va_lists . . . . . . . . . . . . . . . . . . . . . . . . . 181

26 Locale and Internationalization 183


26.1 Setting the Localization, Quick and Dirty . . . . . . . . . . . . . . . . . . . . . . . . 183
26.2 Getting the Monetary Locale Settings . . . . . . . . . . . . . . . . . . . . . . . . . . 184
26.2.1 Monetary Digit Grouping . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
26.2.2 Separators and Sign Position . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
26.2.3 Example Values . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
26.3 Localization Specifics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186

27 Unicode, Wide Characters, and All That 189


27.1 What is Unicode? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
27.2 Code Points . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189
27.3 Encoding . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
27.4 Source and Execution Character Sets . . . . . . . . . . . . . . . . . . . . . . . . . . 191
27.5 Unicode in C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 191
CONTENTS vii

27.6 A Quick Note on UTF-8 Before We Swerve into the Weeds . . . . . . . . . . . . . . 192
27.7 Different Character Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
27.7.1 Multibyte Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 193
27.7.2 Wide Characters . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
27.8 Using Wide Characters and wchar_t . . . . . . . . . . . . . . . . . . . . . . . . . . 194
27.8.1 Multibyte to wchar_t Conversions . . . . . . . . . . . . . . . . . . . . . . . . 195
27.9 Wide Character Functionality . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
27.9.1 wint_t . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
27.9.2 I/O Stream Orientation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
27.9.3 I/O Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
27.9.4 Type Conversion Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 197
27.9.5 String and Memory Copying Functions . . . . . . . . . . . . . . . . . . . . . 197
27.9.6 String and Memory Comparing Functions . . . . . . . . . . . . . . . . . . . . 197
27.9.7 String Searching Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . 198
27.9.8 Length/Miscellaneous Functions . . . . . . . . . . . . . . . . . . . . . . . . . 198
27.9.9 Character Classification Functions . . . . . . . . . . . . . . . . . . . . . . . . 198
27.10 Parse State, Restartable Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . 199
27.11 Unicode Encodings and C . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
27.11.1 UTF-8 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 200
27.11.2 UTF-16, UTF-32, char16_t, and char32_t . . . . . . . . . . . . . . . . . . . 201
27.11.3 Multibyte Conversions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202
27.11.4 Third-Party Libraries . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202

28 Exiting a Program 203


28.1 Normal Exits . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
28.1.1 Returning From main() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
28.1.2 exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203
28.1.3 Setting Up Exit Handlers with atexit() . . . . . . . . . . . . . . . . . . . . 204
28.2 Quicker Exits with quick_exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
28.3 Nuke it from Orbit: _Exit() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
28.4 Exiting Sometimes: assert() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205
28.5 Abnormal Exit: abort() . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205

29 Signal Handling 207


29.1 What Are Signals? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
29.2 Handling Signals with signal() . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
29.3 Writing Signal Handlers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 208
29.4 What Can We Actually Do? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210
29.5 Friends Don’t Let Friends signal() . . . . . . . . . . . . . . . . . . . . . . . . . . 211

30 Variable-Length Arrays (VLAs) 213


30.1 The Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
30.2 sizeof and VLAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214
30.3 Multidimensional VLAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
30.4 Passing One-Dimensional VLAs to Functions . . . . . . . . . . . . . . . . . . . . . 215
30.5 Passing Multi-Dimensional VLAs to Functions . . . . . . . . . . . . . . . . . . . . . 216
30.5.1 Partial Multidimensional VLAs . . . . . . . . . . . . . . . . . . . . . . . . . 216
30.6 Compatibility with Regular Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
30.7 typedef and VLAs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217
30.8 Jumping Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218
30.9 General Issues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 218

31 goto 219
31.1 A Simple Example . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219
31.2 Labeled continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220
31.3 Bailing Out . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
31.4 Labeled break . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221
31.5 Multi-level Cleanup . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
31.6 Tail Call Optimization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
viii CONTENTS

31.7 Restarting Interrupted System Calls . . . . . . . . . . . . . . . . . . . . . . . . . . 224


31.8 goto and Thread Preemption . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
31.9 goto and Variable Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225
31.10 goto and Variable-Length Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . 226

32 Types Part V: Compound Literals and Generic Selections 227


32.1 Compound Literals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227
32.1.1 Passing Unnamed Objects to Functions . . . . . . . . . . . . . . . . . . . . . 227
32.1.2 Unnamed structs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 228
32.1.3 Pointers to Unnamed Objects . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
32.1.4 Unnamed Objects and Scope . . . . . . . . . . . . . . . . . . . . . . . . . . . 229
32.1.5 Silly Unnamed Object Example . . . . . . . . . . . . . . . . . . . . . . . . . 230
32.2 Generic Selections . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230

33 Arrays Part II 233


33.1 Type Qualifiers for Arrays in Parameter Lists . . . . . . . . . . . . . . . . . . . . . . 233
33.2 static for Arrays in Parameter Lists . . . . . . . . . . . . . . . . . . . . . . . . . . 233
33.3 Equivalent Initializers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234

34 Long Jumps with setjmp, longjmp 237


34.1 Using setjmp and longjmp . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 237
34.2 Pitfalls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 238
34.2.1 The Values of Local Variables . . . . . . . . . . . . . . . . . . . . . . . . . . 238
34.2.2 How Much State is Saved? . . . . . . . . . . . . . . . . . . . . . . . . . . . . 239
34.2.3 You Can’t Name Anything setjmp . . . . . . . . . . . . . . . . . . . . . . . . 239
34.2.4 You Can’t setjmp() in a Larger Expression . . . . . . . . . . . . . . . . . . . 239
34.2.5 When Can’t You longjmp()? . . . . . . . . . . . . . . . . . . . . . . . . . . 240
34.2.6 You Can’t Pass 0 to longjmp() . . . . . . . . . . . . . . . . . . . . . . . . . 240
34.2.7 longjmp() and Variable Length Arrays . . . . . . . . . . . . . . . . . . . . . 240

35 Incomplete Types 241


35.1 Use Case: Self-Referential Structures . . . . . . . . . . . . . . . . . . . . . . . . . . 241
35.2 Incomplete Type Error Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
35.3 Other Incomplete Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
35.4 Use Case: Arrays in Header Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . 242
35.5 Completing Incomplete Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243

36 Complex Numbers 245


36.1 Complex Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 245
36.2 Assigning Complex Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 246
36.3 Constructing, Deconstructing, and Printing . . . . . . . . . . . . . . . . . . . . . . . 246
36.4 Complex Arithmetic and Comparisons . . . . . . . . . . . . . . . . . . . . . . . . . 247
36.5 Complex Math . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
36.5.1 Trigonometry Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 248
36.5.2 Exponential and Logarithmic Functions . . . . . . . . . . . . . . . . . . . . . 249
36.5.3 Power and Absolute Value Functions . . . . . . . . . . . . . . . . . . . . . . . 249
36.5.4 Manipulation Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 249

37 Fixed Width Integer Types 251


37.1 The Bit-Sized Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
37.2 Maximum Integer Size Type . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
37.3 Using Fixed Size Constants . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
37.4 Limits of Fixed Size Integers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 252
37.5 Format Specifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 253

38 Date and Time Functionality 255


38.1 Quick Terminology and Information . . . . . . . . . . . . . . . . . . . . . . . . . . 255
38.2 Date Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 255
38.3 Initialization and Conversion Between Types . . . . . . . . . . . . . . . . . . . . . . 256
CONTENTS ix

38.3.1 Converting time_t to struct tm . . . . . . . . . . . . . . . . . . . . . . . . 256


38.3.2 Converting struct tm to time_t . . . . . . . . . . . . . . . . . . . . . . . . 257
38.4 Formatted Date Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 258
38.5 More Resolution with timespec_get() . . . . . . . . . . . . . . . . . . . . . . . . 259
38.6 Differences Between Times . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

39 Multithreading 261
39.1 Background . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
39.2 Things You Can Do . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
39.3 Data Races and the Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . 262
39.4 Creating and Waiting for Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . 262
39.5 Detaching Threads . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 266
39.6 Thread Local Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 267
39.6.1 _Thread_local Storage-Class . . . . . . . . . . . . . . . . . . . . . . . . . 268
39.6.2 Another Option: Thread-Specific Storage . . . . . . . . . . . . . . . . . . . . 269
39.7 Mutexes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 270
39.7.1 Different Mutex Types . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 273
39.8 Condition Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 274
39.8.1 Timed Condition Wait . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 277
39.8.2 Broadcast: Wake Up All Waiting Threads . . . . . . . . . . . . . . . . . . . . 278
39.9 Running a Function One Time . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 278

40 Atomics 279
40.1 Testing for Atomic Support . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
40.2 Atomic Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 279
40.3 Synchronization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 281
40.4 Acquire and Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 283
40.5 Sequential Consistency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 284
40.6 Atomic Assignments and Operators . . . . . . . . . . . . . . . . . . . . . . . . . . . 285
40.7 Library Functions that Automatically Synchronize . . . . . . . . . . . . . . . . . . . 285
40.8 Atomic Type Specifier, Qualifier . . . . . . . . . . . . . . . . . . . . . . . . . . . . 286
40.9 Lock-Free Atomic Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 287
40.9.1 Signal Handlers and Lock-Free Atomics . . . . . . . . . . . . . . . . . . . . . 288
40.10 Atomic Flags . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 288
40.11 Atomic structs and unions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
40.12 Atomic Pointers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 289
40.13 Memory Order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 290
40.13.1 Sequential Consistency . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.13.2 Acquire . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.13.3 Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.13.4 Consume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.13.5 Acquire/Release . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.13.6 Relaxed . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 291
40.14 Fences . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292
40.15 References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 292

41 Function Specifiers, Alignment Specifiers/Operators 295


41.1 Function Specifiers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
41.1.1 inline for Speed—Maybe . . . . . . . . . . . . . . . . . . . . . . . . . . . 295
41.1.2 noreturn and _Noreturn . . . . . . . . . . . . . . . . . . . . . . . . . . . . 297
41.2 Alignment Specifiers and Operators . . . . . . . . . . . . . . . . . . . . . . . . . . 298
41.2.1 alignas and _Alignas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 298
41.2.2 alignof and _Alignof . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 299
x CONTENTS
Chapter 1

Foreword

C is not a big language, and it is not well served by a big book.


–Brian W. Kernighan, Dennis M. Ritchie
No point in wasting words here, folks, let’s jump straight into the C code:
E((ck?main((z?(stat(M,&t)?P+=a+'{'?0:3:
execv(M,k),a=G,i=P,y=G&255,
sprintf(Q,y/'@'-3?A(*L(V(%d+%d)+%d,0)

And they lived happily ever after. The End.


What’s this? You say something’s still not clear about this whole C programming language thing?
Well, to be quite honest, I’m not even sure what the above code does. It’s a snippet from one of the entries
in the 2001 International Obfuscated C Code Contest1 , a wonderful competition wherein the entrants
attempt to write the most unreadable C code possible, with often surprising results.
The bad news is that if you’re a beginner in this whole thing, all C code you see probably looks obfuscated!
The good news is, it’s not going to be that way for long.
What we’ll try to do over the course of this guide is lead you from complete and utter sheer lost confusion
on to the sort of enlightened bliss that can only be obtained through pure C programming. Right on.
In the old days, C was a simpler language. A good number of the features contained in this book and a lot
of the features in the Library Reference volume didn’t exist when K&R wrote the famous second edition
of their book in 1988. Nevertheless, the language remains small at its core, and I hope I’ve presented it
here in a way that starts with that simple core and builds outward.
And that’s my excuse for writing such a hilariously large book for such a small, concise language.

1.1 Audience
This guide assumes that you’ve already got some programming knowledge under your belt from another
language, such as Python2 , JavaScript3 , Java4 , Rust5 , Go6 , Swift7 , etc. (Objective-C8 devs will have a
particularly easy time of it!)
We’re going to assume you know what variables are, what loops do, how functions work, and so on.
1
https://www.ioccc.org/
2
https://en.wikipedia.org/wiki/Python_(programming_language)
3
https://en.wikipedia.org/wiki/JavaScript
4
https://en.wikipedia.org/wiki/Java_(programming_language)
5
https://en.wikipedia.org/wiki/Rust_(programming_language)
6
https://en.wikipedia.org/wiki/Go_(programming_language)
7
https://en.wikipedia.org/wiki/Swift_(programming_language)
8
https://en.wikipedia.org/wiki/Objective-C

1
2 Chapter 1. Foreword

If that’s not you for whatever reason the best I can hope to provide is some honest entertainment for your
reading pleasure. The only thing I can reasonably promise is that this guide won’t end on a cliffhanger…
or will it?

1.2 How to Read This Book


The guide is in two volumes, and this is the first: the tutorial volume!
The second volume is the library reference9 , and it’s far more reference than tutorial.
If you’re new, go through the tutorial part in order, generally. The higher you get in chapters, the less
important it is to go in order.
And no matter your skill level, the reference part is there with complete examples of the standard library
function calls to help refresh your memory whenever needed. Good for reading over a bowl of cereal or
other time.
Finally, glancing at the index (if you’re reading the print version), the reference section entries are itali-
cized.

1.3 Platform and Compiler


I’ll try to stick to Plain Ol’-Fashioned ISO-standard C10 . Well, for the most part. Here and there I might
go crazy and start talking about POSIX11 or something, but we’ll see.
Unix users (e.g. Linux, BSD, etc.) try running cc or gcc from the command line–you might already have
a compiler installed. If you don’t, search your distribution for installing gcc or clang.
Windows users should check out Visual Studio Community12 . Or, if you’re looking for a more Unix-like
experience (recommended!), install WSL13 and gcc.
Mac users will want to install XCode14 , and in particular the command line tools.
There are a lot of compilers out there, and virtually all of them will work for this book. And a C++ compiler
will compile a lot of (but not all!) C code. Best use a proper C compiler if you can.

1.4 Official Homepage


This official location of this document is https://beej.us/guide/bgc/15 . Maybe this’ll change in the future,
but it’s more likely that all the other guides are migrated off Chico State computers.

1.5 Email Policy


I’m generally available to help out with email questions so feel free to write in, but I can’t guarantee a
response. I lead a pretty busy life and there are times when I just can’t answer a question you have. When
that’s the case, I usually just delete the message. It’s nothing personal; I just won’t ever have the time to
give the detailed answer you require.
As a rule, the more complex the question, the less likely I am to respond. If you can narrow down your
question before mailing it and be sure to include any pertinent information (like platform, compiler, error
messages you’re getting, and anything else you think might help me troubleshoot), you’re much more
likely to get a response.
9
https://beej.us/guide/bgclr/
10
https://en.wikipedia.org/wiki/ANSI_C
11
https://en.wikipedia.org/wiki/POSIX
12
https://visualstudio.microsoft.com/vs/community/
13
https://docs.microsoft.com/en-us/windows/wsl/install-win10
14
https://developer.apple.com/xcode/
15
https://beej.us/guide/bgc/
1.6. Mirroring 3

If you don’t get a response, hack on it some more, try to find the answer, and if it’s still elusive, then write
me again with the information you’ve found and hopefully it will be enough for me to help out.
Now that I’ve badgered you about how to write and not write me, I’d just like to let you know that I fully
appreciate all the praise the guide has received over the years. It’s a real morale boost, and it gladdens me
to hear that it is being used for good! :-) Thank you!

1.6 Mirroring
You are more than welcome to mirror this site, whether publicly or privately. If you publicly mirror the
site and want me to link to it from the main page, drop me a line at [email protected].

1.7 Note for Translators


If you want to translate the guide into another language, write me at [email protected] and I’ll link to your
translation from the main page. Feel free to add your name and contact info to the translation.
Please note the license restrictions in the Copyright and Distribution section, below.

1.8 Copyright and Distribution


Beej’s Guide to C is Copyright © 2021 Brian “Beej Jorgensen” Hall.
With specific exceptions for source code and translations, below, this work is licensed under the Cre-
ative Commons Attribution-Noncommercial-No Derivative Works 3.0 License. To view a copy of this
license, visit https://creativecommons.org/licenses/by-nc-nd/3.0/ or send a letter to Creative
Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA.
One specific exception to the “No Derivative Works” portion of the license is as follows: this guide may
be freely translated into any language, provided the translation is accurate, and the guide is reprinted in
its entirety. The same license restrictions apply to the translation as to the original guide. The translation
may also include the name and contact information for the translator.
The C source code presented in this document is hereby granted to the public domain, and is completely
free of any license restriction.
Educators are freely encouraged to recommend or supply copies of this guide to their students.
Contact [email protected] for more information.

1.9 Dedication
The hardest things about writing these guides are:
• Learning the material in enough detail to be able to explain it
• Figuring out the best way to explain it clearly, a seemingly-endless iterative process
• Putting myself out there as a so-called authority, when really I’m just a regular human trying to
make sense of it all, just like everyone else
• Keeping at it when so many other things draw my attention
A lot of people have helped me through this process, and I want to acknowledge those who have made
this book possible.
• Everyone on the Internet who decided to help share their knowledge in one form or another. The
free sharing of instructive information is what makes the Internet the great place that it is.
• The volunteers at cppreference.com16 who provide the bridge that leads from the spec to the real
world.
16
https://en.cppreference.com/
4 Chapter 1. Foreword

• The helpful and knowledgeable folks on comp.lang.c17 and r/C_Programming18 who got me through
the tougher parts of the language.
• Everyone who submitted corrections and pull-requests on everything from misleading instructions
to typos.
Thank you! ♥

17
https://groups.google.com/g/comp.lang.c
18
https://www.reddit.com/r/C_Programming/
Chapter 2

Hello, World!

2.1 What to Expect from C


“Where do these stairs go?”
“They go up.”
—Ray Stantz and Peter Venkman, Ghostbusters
C is a low-level language.
It didn’t use to be. Back in the day when people carved punch cards out of granite, C was an incredible
way to be free of the drudgery of lower-level languages like assembly1 .
But now in these modern times, current-generation languages offer all kinds of features that didn’t exist
in 1972 when C was invented. This means C is a pretty basic language with not a lot of features. It can
do anything, but it can make you work for it.
So why would we even use it today?
• As a learning tool: not only is C a venerable piece of computing history, but it is connected to the
bare metal2 in a way that present-day languages are not. When you learn C, you learn about how
software interfaces with computer memory at a low level. There are no seatbelts. You’ll write
software that crashes, I assure you. And that’s all part of the fun!
• As a useful tool: C still is used for certain applications, such as building operating systems3 or in
embedded systems4 . (Though the Rust5 programming language is eyeing both these fields!)
If you’re familiar with another language, a lot of things about C are easy. C inspired many other languages,
and you’ll see bits of it in Go, Rust, Swift, Python, JavaScript, Java, and all kinds of other languages.
Those parts will be familiar.
The one thing about C that hangs people up is pointers. Virtually everything else is familiar, but pointers
are the weird one. The concept behind pointers is likely one you already know, but C forces you to be
explicit about it, using operators you’ve likely never seen before.
It’s especially insidious because once you grok6 pointers, they’re suddenly easy. But up until that moment,
they’re slippery eels.
Everything else in C is just memorizing another way (or sometimes the same way!) of doing something
you’ve done already. Pointers are the weird bit. And, arguably, even pointers are variations on a theme
you’re probably familiar with.
1
https://en.wikipedia.org/wiki/Assembly_language
2
https://en.wikipedia.org/wiki/Bare_machine
3
https://en.wikipedia.org/wiki/Operating_system
4
https://en.wikipedia.org/wiki/Embedded_system
5
https://en.wikipedia.org/wiki/Rust_(programming_language)
6
https://en.wikipedia.org/wiki/Grok

5
6 Chapter 2. Hello, World!

So get ready for a rollicking adventure as close to the core of the computer as you can get without assembly,
in the most influential computer language of all time7 . Hang on!

2.2 Hello, World!


This is the canonical example of a C program. Everyone uses it. (Note that the numbers to the left are for
reader reference only, and are not part of the source code.)
1 /* Hello world program */
2

3 #include <stdio.h>
4

5 int main(void)
6 {
7 printf("Hello, World!\n"); // Actually do the work here
8 }

We’re going to don our long-sleeved heavy-duty rubber gloves, grab a scalpel, and rip into this thing to
see what makes it tick. So, scrub up, because here we go. Cutting very gently…
Let’s get the easy thing out of the way: anything between the digraphs /* and */ is a comment and will
be completely ignored by the compiler. Same goes for anything on a line after a //. This allows you
to leave messages to yourself and others, so that when you come back and read your code in the distant
future, you’ll know what the heck it was you were trying to do. Believe me, you will forget; it happens.
Now, what is this #include? GROSS! Well, it tells the C Preprocessor to pull the contents of another file
and insert it into the code right there.
Wait—what’s a C Preprocessor? Good question. There are two stages8 to compilation: the preprocessor
and the compiler. Anything that starts with pound sign, or “octothorpe”, (#) is something the preprocessor
operates on before the compiler even gets started. Common preprocessor directives, as they’re called, are
#include and #define. More on that later.

Before we go on, why would I even begin to bother pointing out that a pound sign is called an octothorpe?
The answer is simple: I think the word octothorpe is so excellently funny, I have to gratuitously spread its
name around whenever I get the opportunity. Octothorpe. Octothorpe, octothorpe, octothorpe.
So anyway. After the C preprocessor has finished preprocessing everything, the results are ready for
the compiler to take them and produce assembly code9 , machine code10 , or whatever it’s about to do.
Machine code is the “language” the CPU understands, and it can understand it very rapidly. This is one
of the reasons C programs tend to be quick.
Don’t worry about the technical details of compilation for now; just know that your source runs through
the preprocessor, then the output of that runs through the compiler, then that produces an executable for
you to run.
What about the rest of the line? What’s <stdio.h>? That is what is known as a header file. It’s the
dot-h at the end that gives it away. In fact it’s the “Standard I/O” (stdio) header file that you will grow
to know and love. It gives us access to a bunch of I/O functionality11 . For our demo program, we’re
outputting the string “Hello, World!”, so we in particular need access to the printf() function to do
this. The <stdio.h> file gives us this access. Basically, if we tried to use printf() without #include
<stdio.h>, the compiler would have complained to us about it.

How did I know I needed to #include <stdio.h> for printf()? Answer: it’s in the documentation.
If you’re on a Unix system, man 3 printf and it’ll tell you right at the top of the man page what header
files are required. Or see the reference section in this book. :-)
7
I know someone will fight me on that, but it’s gotta be at least in the top three, right?
8
Well, technically there are more than two, but hey, let’s pretend there are two—ignorance is bliss, right?
9
https://en.wikipedia.org/wiki/Assembly_language
10
https://en.wikipedia.org/wiki/Machine_code
11
Technically, it contains preprocessor directives and function prototypes (more on that later) for common input and output needs.
2.3. Compilation Details 7

Holy moly. That was all to cover the first line! But, let’s face it, it has been completely dissected. No
mystery shall remain!
So take a breather…look back over the sample code. Only a couple easy lines to go.
Welcome back from your break! I know you didn’t really take a break; I was just humoring you.
The next line is main(). This is the definition of the function main(); everything between the squirrelly
braces ({ and }) is part of the function definition.
(How do you call a different function, anyway? The answer lies in the printf() line, but we’ll get to
that in a minute.)
Now, the main function is a special one in many ways, but one way stands above the rest: it is the function
that will be called automatically when your program starts executing. Nothing of yours gets called before
main(). In the case of our example, this works fine since all we want to do is print a line and exit.

Oh, that’s another thing: once the program executes past the end of main(), down there at the closing
squirrelly brace, the program will exit, and you’ll be back at your command prompt.
So now we know that that program has brought in a header file, stdio.h, and declared a main() function
that will execute when the program is started. What are the goodies in main()?
I am so happy you asked. Really! We only have the one goodie: a call to the function printf(). You
can tell this is a function call and not a function definition in a number of ways, but one indicator is the
lack of squirrelly braces after it. And you end the function call with a semicolon so the compiler knows
it’s the end of the expression. You’ll be putting semicolons after almost everything, as you’ll see.
You’re passing one argument to the function printf(): a string to be printed when you call it. Oh, yeah—
we’re calling a function! We rock! Wait, wait—don’t get cocky. What’s that crazy \n at the end of the
string? Well, most characters in the string will print out just like they are stored. But there are certain
characters that you can’t print on screen well that are embedded as two-character backslash codes. One of
the most popular is \n (read “backslash-N” or simply “newline”) that corresponds to the newline character.
This is the character that causes further printing to continue at the beginning of the next line instead of the
current. It’s like hitting return at the end of the line.
So copy that code into a file called hello.c and build it. On a Unix-like platform (e.g. Linux, BSD, Mac,
or WSL), from the command line you’ll build with a command like so:
gcc -o hello hello.c

(This means “compile hello.c, and output an executable called hello”.)


After that’s done, you should have a file called hello that you can run with this command:
./hello

(The leading ./ tells the shell to “run from the current directory”.)
And see what happens:
Hello, World!

It’s done and tested! Ship it!

2.3 Compilation Details


Let’s talk a bit more about how to build C programs, and what happens behind the scenes there.
Like other languages, C has source code. But, depending on what language you’re coming from, you
might never have had to compile your source code into an executable.
Compilation is the process of taking your C source code and turning it into a program that your operating
system can execute.
JavaScript and Python devs aren’t used to a separate compilation step at all–though behind the scenes
it’s happening! Python compiles your source code into something called bytecode that the Python virtual
8 Chapter 2. Hello, World!

machine can execute. Java devs are used to compilation, but that produces bytecode for the Java Virtual
Machine.
When compiling C, machine code is generated. This is the 1s and 0s that can be executed directly and
speedily by the CPU.
Languages that typically aren’t compiled are called interpreted languages. But as we men-
tioned with Java and Python, they also have a compilation step. And there’s no rule saying
that C can’t be interpreted. (There are C interpreters out there!) In short, it’s a bunch of gray
areas. Compilation in general is just taking source code and turning it into another, more
easily-executed form.
The C compiler is the program that does the compilation.
As we’ve already said, gcc is a compiler that’s installed on a lot of Unix-like operating systems12 . And
it’s commonly run from the command line in a terminal, but not always. You can run it from your IDE,
as well.
So how do we do command line builds?

2.4 Building with gcc


If you have a source file called hello.c in the current directory, you can build that into a program called
hello with this command typed in a terminal:
gcc -o hello hello.c

The -o means “output to this file”13 . And there’s hello.c at the end, the name of the file we want to
compile.
If your source is broken up into multiple files, you can compile them all together (almost as if they were
one file, but the rules are actually more complex than that) by putting all the .c files on the command line:
gcc -o awesomegame ui.c characters.c npc.c items.c

and they’ll all get built together into a big executable.


That’s enough to get started—later we’ll talk details about multiple source files, object files, and all kinds
of fun stuff.

2.5 Building with clang


On Macs, the stock compiler isn’t gcc—it’s clang. But a wrapper is also installed so you can run gcc
and have it still work.
You can also install the gcc compiler proper through Homebrew14 or some other means.

2.6 Building from IDEs


If you’re using an Integrated Development Environment (IDE), you probably don’t have to build from the
command line.
With Visual Studio, CTRL-F7 will build, and CTRL-F5 will run.
With VS Code, you can hit F5 to run via the debugger. (You’ll have to install the C/C++ Extension.)
With XCode, you can build with COMMAND-B and run with COMMAND-R. To get the command line tools,
Google for “XCode command line tools” and you’ll find instructions for installing them.
For getting started, I encourage you to also try to build from the command line—it’s history!
12
https://en.wikipedia.org/wiki/Unix
13
If you don’t give it an output filename, it will export to a file called a.out by default—this filename has its roots deep in Unix
history.
14
https://formulae.brew.sh/formula/gcc
2.7. C Versions 9

2.7 C Versions
C has come a long way over the years, and it had many named version numbers to describe which dialect
of the language you’re using.
These generally refer to the year of the specification.
The most famous are C89, C99, C11, and C2x. We’ll focus on the latter in this book.
But here’s a more complete table:

Version Description
K&R C 1978, the original. Named after Brian Kernighan and Dennis Ritchie.
Ritchie designed and coded the language, and Kernighan co-authored the
book on it. You rarely see original K&R code today. If you do, it’ll look
odd, like Middle English looks odd to modern English readers.
C89, ANSI C, C90 In 1989, the American National Standards Institute (ANSI) produced a C
language specification that set the tone for C that persists to this day. A
year later, the reins were handed to the International Organization for
Standardization (ISO) that produced the identical C90.
C95 A rarely-mentioned addition to C89 that included wide character support.
C99 The first big overhaul with lots of language additions. The thing most
people remember is the addition of //-style comments. This is the most
popular version of C in use as of this writing.
C11 This major version update includes Unicode support and multi-threading.
Be advised that if you start using these language features, you might be
sacrificing portability with places that are stuck in C99 land. But, honestly,
1999 is getting to be a while back now.
C17, C18 Bugfix update to C11. C17 seems to be the official name, but the
publication was delayed until 2018. As far as I can tell, these two are
interchangeable, with C17 being preferred.
C2x What’s coming next! Expected to eventually become C23.

You can force GCC to use one of these standards with the -std= command line argument. If you want it
to be picky about the standard, add -pedantic.
For example:
gcc -std=c11 -pedantic foo.c

For this book, I compile programs for C2x with all warnings set:
gcc -Wall -Wextra -std=c2x -pedantic foo.c
10 Chapter 2. Hello, World!
Chapter 3

Variables and Statements

“It takes all kinds to make a world, does it not, Padre?”


“So it does, my son, so it does.”
—Pirate Captain Thomas Bartholomew Red to the Padre, Pirates
There sure can be lotsa stuff in a C program.
Yup.
And for various reasons, it’ll be easier for all of us if we classify some of the types of things you can find
in a program, so we can be clear what we’re talking about.

3.1 Variables
It’s said that “variables hold values”. But another way to think about it is that a variable is a human-
readable name that refers to some data in memory.
We’re going to take a second here and take a peek down the rabbit hole that is pointers. Don’t worry about
it.
You can think of memory as a big array of bytes1 . Data is stored in this “array”2 . If a number is larger than
a single byte, it is stored in multiple bytes. Because memory is like an array, each byte of memory can be
referred to by its index. This index into memory is also called an address, or a location, or a pointer.
When you have a variable in C, the value of that variable is in memory somewhere, at some address. Of
course. After all, where else would it be? But it’s a pain to refer to a value by its numeric address, so we
make a name for it instead, and that’s what the variable is.
The reason I’m bringing all this up is twofold:
1. It’s going to make it easier to understand pointer variables later—they’re variables that hold the
address of other variables!
2. Also, it’s going to make it easier to understand pointers later.
So a variable is a name for some data that’s stored in memory at some address.

3.1.1 Variable Names


You can use any characters in the range 0-9, A-Z, a-z, and underscore for variable names, with the follow-
ing rules:
• You can’t start a variable with a digit 0-9.
• You can’t start a variable name with two underscores.
1
A “byte” is typically an 8-bit binary number. Think of it as an integer that can only hold the values from 0 to 255, inclusive.
Technically, C allows bytes to be any number of bits and if you want to unambiguously refer to an 8-bit number, you should use the
term octet. But programmers are going assume you mean 8-bits when you say “byte” unless you specify otherwise.
2
I’m seriously oversimplifying how modern memory works, here. But the mental model works, so please forgive me.

11
12 Chapter 3. Variables and Statements

• You can’t start a variable name with an underscore followed by a capital A-Z.
For Unicode, just try it. There are some rules in the spec in §D.2 that talk about which Unicode codepoint
ranges are allowed in which parts of identifiers, but that’s too much to write about here and is probably
something you’ll never have to think about anyway.

3.1.2 Variable Types


Depending on which languages you already have in your toolkit, you might or might not be familiar with
the idea of types. But C’s kinda picky about them, so we should do a refresher.
Some example types, some of the most basic:

Type Example C Type


Integer 3490 int
Floating point 3.14159 float3
Character (single) 'c' char
String "Hello, world!" char *4

C makes an effort to convert automatically between most numeric types when you ask it to. But other
than that, all conversions are manual, notably between string and numeric.
Almost all of the types in C are variants on these types.
Before you can use a variable, you have to declare that variable and tell C what type the variable holds.
Once declared, the type of variable cannot be changed later at runtime. What you set it to is what it is
until it falls out of scope and is reabsorbed into the universe.
Let’s take our previous “Hello, world” code and add a couple variables to it:
1 #include <stdio.h>
2

3 int main(void)
4 {
5 int i; // Holds signed integers, e.g. -3, -2, 0, 1, 10
6 float f; // Holds signed floating point numbers, e.g. -3.1416
7

8 printf("Hello, World!\n"); // Ah, blessed familiarity


9 }

There! We’ve declared a couple of variables. We haven’t used them yet, and they’re both uninitialized.
One holds an integer number, and the other holds a floating point number (a real number, basically, if you
have a math background).
Uninitialized variables have indeterminate value5 . They have to be initialized or else you must assume
they contain some nonsense number.
This is one of the places C can “get you”. Much of the time, in my experience, the indeter-
minate value is zero… but it can vary from run to run! Never assume the value will be zero,
even if you see it is. Always explicitly initialize variables to some value before you use them6 .
What’s this? You want to store some numbers in those variables? Insanity!
Let’s go ahead and do that:

3
I’m lying here a little. Technically 3.14159 is of type double, but we’re not there yet and I want you to associate float with
“Floating Point”, and C will happily coerce that type into a float. In short, don’t worry about it until later.
4
Read this as “pointer to a char” or “char pointer”. “Char” for character. Though I can’t find a study, it seems anecdotally most
people pronounce this as “char”, a minority say “car”, and a handful say “care”. We’ll talk more about pointers later.
5
Colloquially, we say they have “random” values, but they aren’t truly—or even pseudo-truly—random numbers.
6
This isn’t strictly 100% true. When we get to learning about static storage duration, you’ll find the some variables are initialized
to zero automatically. But the safe thing to do is always initialize them.
3.1. Variables 13

1 int main(void)
2 {
3 int i;
4

5 i = 2; // Assign the value 2 into the variable i


6

7 printf("Hello, World!\n");
8 }

Killer. We’ve stored a value. Let’s print it.


We’re going to do that by passing two amazing arguments to the printf() function. The first argument
is a string that describes what to print and how to print it (called the format string), and the second is the
value to print, namely whatever is in the variable i.
printf() hunts through the format string for a variety of special sequences which start with a percent
sign (%) that tell it what to print. For example, if it finds a %d, it looks to the next parameter that was
passed, and prints it out as an integer. If it finds a %f, it prints the value out as a float. If it finds a %s, it
prints a string.
As such, we can print out the value of various types like so:
1 #include <stdio.h>
2

3 int main(void)
4 {
5 int i = 2;
6 float f = 3.14;
7 char *s = "Hello, world!"; // char * ("char pointer") is the string type
8

9 printf("%s i = %d and f = %f!\n", s, i, f);


10 }

And the output will be:


Hello, world! i = 2 and f = 3.14!

In this way, printf() might be similar to various types of format strings or parameterized strings in other
languages you’re familiar with.

3.1.3 Boolean Types


C has Boolean types, true or false?
1!

Historically, C didn’t have a Boolean type, and some might argue it still doesn’t.
In C, 0 means “false”, and non-zero means “true”.
So 1 is true. And -37 is true. And 0 is false.
You can just declare Boolean types as ints:
int x = 1;

if (x) {
printf("x is true!\n");
}

If you #include <stdbool.h>, you also get access to some symbolic names that might make things
look more familiar, namely a bool type and true and false values:
1 #include <stdio.h>
2 #include <stdbool.h>
14 Chapter 3. Variables and Statements

4 int main(void) {
5 bool x = true;
6

7 if (x) {
8 printf("x is true!\n");
9 }
10 }

But these are identical to using integer values for true and false. They’re just a facade to make things look
nice.

3.2 Operators and Expressions


C operators should be familiar to you from other languages. Let’s blast through some of them here.
(There are a bunch more details than this, but we’re going to do enough in this section to get started.)

3.2.1 Arithmetic
Hopefully these are familiar:
i = i + 3; // Addition (+) and assignment (=) operators, add 3 to i
i = i - 8; // Subtraction, subtract 8 from i
i = i * 9; // Multiplication
i = i / 2; // Division
i = i % 5; // Modulo (division remainder)

There are shorthand variants for all of the above. Each of those lines could more tersely be written as:
i += 3; // Same as "i = i + 3", add 3 to i
i -= 8; // Same as "i = i - 8"
i *= 9; // Same as "i = i * 9"
i /= 2; // Same as "i = i / 2"
i %= 5; // Same as "i = i % 5"

There is no exponentiation. You’ll have to use one of the pow() function variants from math.h.
Let’s get into some of the weirder stuff you might not have in your other languages!

3.2.2 Ternary Operator


C also includes the ternary operator. This is an expression whose value depends on the result of a condi-
tional embedded in it.
// If x > 10, add 17 to y. Otherwise add 37 to y.

y += x > 10? 17: 37;

What a mess! You’ll get used to it the more you read it. To help out a bit, I’ll rewrite the above expression
using if statements:
// This expression:

y += x > 10? 17: 37;

// is equivalent to this non-expression:

if (x > 10)
y += 17;
else
y += 37;
3.2. Operators and Expressions 15

Compare those two until you see each of the components of the ternary operator.

Or, another example that prints if a number stored in x is odd or even:


printf("The number %d is %s.\n", x, x % 2 == 0? "even": "odd")

The %s format specifier in printf() means print a string. If the expression x % 2 evaluates to 0, the
value of the entire ternary expression evaluates to the string "even". Otherwise it evaluates to the string
"odd". Pretty cool!

It’s important to note that the ternary operator isn’t flow control like the if statement is. It’s just an
expression that evaluates to a value.

3.2.3 Pre-and-Post Increment-and-Decrement


Now, let’s mess with another thing that you might not have seen.

These are the legendary post-increment and post-decrement operators:


i++; // Add one to i (post-increment)
i--; // Subtract one from i (post-decrement)

Very commonly, these are just used as shorter versions of:


i += 1; // Add one to i
i -= 1; // Subtract one from i

but they’re more subtly different than that, the clever scoundrels.

Let’s take a look at this variant, pre-increment and pre-decrement:


++i; // Add one to i (pre-increment)
--i; // Subtract one from i (pre-decrement)

With pre-increment and pre-decrement, the value of the variable is incremented or decremented before
the expression is evaluated. Then the expression is evaluated with the new value.

With post-increment and post-decrement, the value of the expression is first computed with the value as-is,
and then the value is incremented or decremented after the value of the expression has been determined.

You can actually embed them in expressions, like this:


i = 10;
j = 5 + i++; // Compute 5 + i, _then_ increment i

printf("%d, %d\n", i, j); // Prints 11, 15

Let’s compare this to the pre-increment operator:


i = 10;
j = 5 + ++i; // Increment i, _then_ compute 5 + i

printf("%d, %d\n", i, j); // Prints 11, 16

This technique is used frequently with array and pointer access and manipulation. It gives you a way to
use the value in a variable, and also increment or decrement that value before or after it is used.

But by far the most common place you’ll see this is in a for loop:
for (i = 0; i < 10; i++)
printf("i is %d\n", i);

But more on that later.


16 Chapter 3. Variables and Statements

3.2.4 The Comma Operator


This is an uncommonly-used way to separate expressions that will run left to right:
x = 10, y = 20; // First assign 10 to x, then 20 to y

Seems a bit silly, since you could just replace the comma with a semicolon, right?
x = 10; y = 20; // First assign 10 to x, then 20 to y

But that’s a little different. The latter is two separate expressions, while the former is a single expression!
With the comma operator, the value of the comma expression is the value of the rightmost expression:
x = (1, 2, 3);

printf("x is %d\n", x); // Prints 3, because 3 is rightmost in the comma list

But even that’s pretty contrived. One common place the comma operator is used is in for loops to do
multiple things in each section of the statement:
for (i = 0, j = 10; i < 100; i++, j++)
printf("%d, %d\n", i, j);

We’ll revisit that later.

3.2.5 Conditional Operators


For Boolean values, we have a raft of standard operators:
a == b; // True if a is equivalent to b
a != b; // True if a is not equivalent to b
a < b; // True if a is less than b
a > b; // True if a is greater than b
a <= b; // True if a is less than or equal to b
a >= b; // True if a is greater than or equal to b

Don’t mix up assignment = with comparison ==! Use two equals to compare, one to assign.
We can use the comparison expressions with if statements:
if (a <= 10)
printf("Success!\n");

3.2.6 Boolean Operators


We can chain together or alter conditional expressions with Boolean operators for and, or, and not.

Operator Boolean meaning


&& and
|| or
! not

An example of Boolean “and”:


// Do something if x less than 10 and y greater than 20:

if (x < 10 && y > 20)


printf("Doing something!\n");

An example of Boolean “not”:


if (!(x < 12))
printf("x is not less than 12\n");
3.3. Flow Control 17

! has higher precedence than the other Boolean operators, so we have to use parentheses in that case.

Of course, that’s just the same as:


if (x >= 12)
printf("x is not less than 12\n");

but I needed the example!

3.2.7 The sizeof Operator


This operator tells you the size (in bytes) that a particular variable or data type uses in memory.
More particularly, it tells you the size (in bytes) that the type of a particular expression (which might be
just a single variable) uses in memory.
This can be different on different systems, except for char and its variants (which are always 1 byte).
And this might not seem very useful now, but we’ll be making references to it here and there, so it’s worth
covering.
Since this computes the number of bytes needed to store a type, you might think it would return an int.
Or… since the size can’t be negative, maybe an unsigned?
But it turns out C has a special type to represent the return value from sizeof. It’s size_t, pronounced
“size tee”7 . All we know is that it’s an unsigned integer type that can hold the size in bytes of anything
you can give to sizeof.
size_t shows up a lot of different places where counts of things are passed or returned. Think of it as a
value that represents a count.
You can take the sizeof a variable or expression:
int a = 999;

// %zu is the format specifier for type size_t

printf("%zu\n", sizeof a); // Prints 4 on my system


printf("%zu\n", sizeof(2 + 7)); // Prints 4 on my system
printf("%zu\n", sizeof 3.14); // Prints 8 on my system

// If you need to print out negative size_t values, use %zd

Remember: it’s the size in bytes of the type of the expression, not the size of the expression itself. That’s
why the size of 2+7 is the same as the size of a—they’re both type int. We’ll revisit this number 4 in the
very next block of code…
…Where we’ll see you can take the sizeof a type (note the parentheses are required around a type name,
unlike an expression):
printf("%zu\n", sizeof(int)); // Prints 4 on my system
printf("%zu\n", sizeof(char)); // Prints 1 on all systems

It’s important to note that sizeof is a compile-time operation8 . The result of the expression is determined
entirely at compile-time, not at runtime.
We’ll make use of this later on.

3.3 Flow Control


Booleans are all good, but of course we’re nowhere if we can’t control program flow. Let’s take a look at
a number of constructs: if, for, while, and do-while.
7
The _t is short for type.
8
Except for with variable length arrays—but that’s a story for another time.
18 Chapter 3. Variables and Statements

First, a general forward-looking note about statements and blocks of statements brought to you by your
local friendly C developer:

After something like an if or while statement, you can either put a single statement to be executed, or a
block of statements to all be executed in sequence.

Let’s start with a single statement:


if (x == 10) printf("x is 10\n");

This is also sometimes written on a separate line. (Whitespace is largely irrelevant in C—it’s not like
Python.)
if (x == 10)
printf("x is 10\n");

But what if you want multiple things to happen due to the conditional? You can use squirrelly braces to
mark a block or compound statement.
if (x == 10) {
printf("x is 10\n");
printf("And also this happens when x is 10\n");
}

It’s a really common style to always use squirrelly braces even if they aren’t necessary:
if (x == 10) {
printf("x is 10\n");
}

Some devs feel the code is easier to read and avoids errors like this where things visually look like they’re
in the if block, but actually they aren’t.
// BAD ERROR EXAMPLE

if (x == 10)
printf("This happens if x is 10\n");
printf("This happens ALWAYS\n"); // Surprise!! Unconditional!

while and for and the other looping constructs work the same way as the examples above. If you want
to do multiple things in a loop or after an if, wrap them up in squirrelly braces.

In other words, the if is going to run the one thing after the if. And that one thing can be a single
statement or a block of statements.

3.3.1 The if-else statement


We’ve already been using if for multiple examples, since it’s likely you’ve seen it in a language before,
but here’s another:
int i = 10;

if (i > 10) {
printf("Yes, i is greater than 10.\n");
printf("And this will also print if i is greater than 10.\n");
}

if (i <= 10) printf("i is less than or equal to 10.\n");

In the example code, the message will print if i is greater than 10, otherwise execution continues to the next
line. Notice the squirrley braces after the if statement; if the condition is true, either the first statement
or expression right after the if will be executed, or else the collection of code in the squirlley braces after
the if will be executed. This sort of code block behavior is common to all statements.
3.3. Flow Control 19

Of course, because C is fun this way, you can also do something if the condition is false with an else
clause on your if:
int i = 99;

if (i == 10)
printf("i is 10!\n");
else {
printf("i is decidedly not 10.\n");
printf("Which irritates me a little, frankly.\n");
}

And you can even cascade these to test a variety of conditions, like this:
int i = 99;

if (i == 10)
printf("i is 10!\n");

else if (i == 20)
printf("i is 20!\n");

else if (i == 99) {
printf("i is 99! My favorite\n");
printf("I can't tell you how happy I am.\n");
printf("Really.\n");
}

else
printf("i is some crazy number I've never heard of.\n");

Though if you’re going that route, be sure to check out the switch statement for a potentially better
solution. The catch is switch only works with equality comparisons with constant numbers. The above
if-else cascade could check inequality, ranges, variables, or anything else you can craft in a conditional
expression.

3.3.2 The while statement


while is your average run-of-the-mill looping construct. Do a thing while a condition expression is true.

Let’s do one!
// Print the following output:
//
// i is now 0!
// i is now 1!
// [ more of the same between 2 and 7 ]
// i is now 8!
// i is now 9!

i = 0;

while (i < 10) {


printf("i is now %d!\n", i);
i++;
}

printf("All done!\n");

That gets you a basic loop. C also has a for loop which would have been cleaner for that example.
A not-uncommon use of while is for infinite loops where you repeat while true:
20 Chapter 3. Variables and Statements

while (1) {
printf("1 is always true, so this repeats forever.\n");
}

3.3.3 The do-while statement


So now that we’ve gotten the while statement under control, let’s take a look at its closely related cousin,
do-while.

They are basically the same, except if the loop condition is false on the first pass, do-while will execute
once, but while won’t execute at all. In other words, the test to see whether or not to execute the block
happens at the end of the block with do-while. It happens at the beginning of the block with while.
Let’s see by example:
// Using a while statement:

i = 10;

// this is not executed because i is not less than 10:


while(i < 10) {
printf("while: i is %d\n", i);
i++;
}

// Using a do-while statement:

i = 10;

// this is executed once, because the loop condition is not checked until
// after the body of the loop runs:

do {
printf("do-while: i is %d\n", i);
i++;
} while (i < 10);

printf("All done!\n");

Notice that in both cases, the loop condition is false right away. So in the while, the loop fails, and
the following block of code is never executed. With the do-while, however, the condition is checked
after the block of code executes, so it always executes at least once. In this case, it prints the message,
increments i, then fails the condition, and continues to the “All done!” output.
The moral of the story is this: if you want the loop to execute at least once, no matter what the loop
condition, use do-while.
All these examples might have been better done with a for loop. Let’s do something less deterministic—
repeat until a certain random number comes up!
1 #include <stdio.h> // For printf
2 #include <stdlib.h> // For rand
3

4 int main(void)
5 {
6 int r;
7

8 do {
9 r = rand() % 100; // Get a random number between 0 and 99
10 printf("%d\n", r);
3.3. Flow Control 21

11 } while (r != 37); // Repeat until 37 comes up


12 }

Side note: did you run that more than once? If you did, did you notice the same sequence of numbers
came up again. And again. And again? This is because rand() is a pseudorandom number generator that
must be seeded with a different number in order to generate a different sequence. Look up the srand()9
function for more details.

3.3.4 The for statement


Welcome to one of the most popular loops in the world! The for loop!
This is a great loop if you know the number of times you want to loop in advance.
You could do the same thing using just a while loop, but the for loop can help keep the code cleaner.
Here are two pieces of equivalent code—note how the for loop is just a more compact representation:
// Print numbers between 0 and 9, inclusive...

// Using a while statement:

i = 0;
while (i < 10) {
printf("i is %d\n", i);
i++;
}

// Do the exact same thing with a for-loop:

for (i = 0; i < 10; i++) {


printf("i is %d\n", i);
}

That’s right, folks—they do exactly the same thing. But you can see how the for statement is a little more
compact and easy on the eyes. (JavaScript users will fully appreciate its C origins at this point.)
It’s split into three parts, separated by semicolons. The first is the initialization, the second is the loop
condition, and the third is what should happen at the end of the block if the loop condition is true. All
three of these parts are optional.
for (initialize things; loop if this is true; do this after each loop)

Note that the loop will not execute even a single time if the loop condition starts off false.
for-loop fun fact!

You can use the comma operator to do multiple things in each clause of the for loop!
for (i = 0, j = 999; i < 10; i++, j--) {
printf("%d, %d\n", i, j);
}

An empty for will run forever:


for(;;) { // "forever"
printf("I will print this again and again and again\n" );
printf("for all eternity until the heat-death of the universe.\n");

printf("Or until you hit CTRL-C.\n");


}

9
https://beej.us/guide/bgclr/html/split/stdlib.html#man-srand
22 Chapter 3. Variables and Statements

3.3.5 The switch Statement


Depending on what languages you’re coming from, you might or might not be familiar with switch, or
C’s version might even be more restrictive than you’re used to. This is a statement that allows you to take
a variety of actions depending on the value of an integer expression.
Basically, it evaluates an expression to an integer value, jumps to the case that corresponds to that value.
Execution resumes from that point. If a break statement is encountered, then execution jumps out of the
switch.

Let’s do an example where the user enters a number of goats and we print out a gut-feel of how many
goats that is.
1 #include <stdio.h>
2

3 int main(void)
4 {
5 int goat_count;
6

7 printf("Enter a goat count: ");


8 scanf("%d", &goat_count); // Read an integer from the keyboard
9

10 switch (goat_count) {
11 case 0:
12 printf("You have no goats.\n");
13 break;
14

15 case 1:
16 printf("You have a singular goat.\n");
17 break;
18

19 case 2:
20 printf("You have a brace of goats.\n");
21 break;
22

23 default:
24 printf("You have a bona fide plethora of goats!\n");
25 break;
26 }
27 }

In that example, if the user enters, say, 2, the switch will jump to the case 2 and execute from there.
When (if) it hits a break, it jumps out of the switch.
Also, you might see that default label there at the bottom. This is what happens when no cases match.
Every case, including default, is optional. And they can occur in any order, but it’s really typical for
default, if any, to be listed last.

So the whole thing acts like an if-else cascade:


if (goat_count == 0)
printf("You have no goats.\n");
else if (goat_count == 1)
printf("You have a singular goat.\n");
else if (goat_count == 2)
printf("You have a brace of goats.\n");
else
printf("You have a bona fide plethora of goats!\n");

With some key differences:


• switch is often faster to jump to the correct code (though the spec makes no such guarantee).
3.3. Flow Control 23

• if-else can do things like relational conditionals like < and >= and floating point and other types,
while switch cannot.
There’s one more neat thing about switch that you sometimes see that is quite interesting: fall through.
Remember how break causes us to jump out of the switch?
Well, what happens if we don’t break?
Turns out we just keep on going into the next case! Demo!
switch (x) {
case 1:
printf("1\n");
// Fall through!
case 2:
printf("2\n");
break;
case 3:
printf("3\n");
break;
}

If x == 1, this switch will first hit case 1, it’ll print the 1, but then it just continues on to the next line
of code… which prints 2!
And then, at last, we hit a break so we jump out of the switch.
if x == 2, then we just hit the case 2, print 2, and break as normal.
Not having a break is called fall through.
ProTip: ALWAYS put a comment in the code where you intend to fall through, like I did above. It will
save other programmers from wondering if you meant to do that.
In fact, this is one of the common places to introduce bugs in C programs: forgetting to put a break in
your case. You gotta do it if you don’t want to just roll into the next case10 .
Earlier I said that switch works with integer types—keep it that way. Don’t use floating point or string
types in there. One loophole-ish thing here is that you can use character types because those are secretly
integers themselves. So this is perfectly acceptable:
char c = 'b';

switch (c) {
case 'a':
printf("It's 'a'!\n");
break;

case 'b':
printf("It's 'b'!\n");
break;

case 'c':
printf("It's 'c'!\n");
break;
}

Finally, you can use enums in switch since they are also integer types. But more on that in the enum
chapter.

10
This was considered such a hazard that the designers of the Go Programming Language made break the default; you have to
explicitly use Go’s fallthrough statement if you want to fall into the next case.
24 Chapter 3. Variables and Statements
Chapter 4

Functions

“Sir, not in an environment such as this. That’s why I’ve also been programmed for over thirty
secondary functions that—”
—C3PO, before being rudely interrupted, reporting a now-unimpressive number of additional
functions, Star Wars script
Very much like other languages you’re used to, C has the concept of functions.
Functions can accept a variety of arguments and return a value. One important thing, though: the argu-
ments and return value types are predeclared—because that’s how C likes it!
Let’s take a look at a function. This is a function that takes an int as an argument, and returns an int.
1 #include <stdio.h>
2

3 int plus_one(int n) // The "definition"


4 {
5 return n + 1;
6 }
7

The int before the plus_one indicates the return type.


The int n indicates that this function takes one int argument, stored in parameter n. A parameter is a
special type of local variable into which the arguments are copied.
I’m going to drive home the point that the arguments are copied into the parameters, here. Lots of things
in C are easier to understand if you know that the parameter is a copy of the argument, not the argument
itself. More on that in a minute.
Continuing the program down into main(), we can see the call to the function, where we assign the return
value into local variable j:
8 int main(void)
9 {
10 int i = 10, j;
11

12 j = plus_one(i); // The "call"


13

14 printf("i + 1 is %d\n", j);


15 }

Before I forget, notice that I defined the function before I used it. If I hadn’t done that, the
compiler wouldn’t know about it yet when it compiles main() and it would have given an
unknown function call error. There is a more proper way to do the above code with function
prototypes, but we’ll talk about that later.

25
26 Chapter 4. Functions

Also notice that main() is a function!


It returns an int.
But what’s this void thing? This is a keyword that’s used to indicate that the function accepts no argu-
ments.
You can also return void to indicate that you don’t return a value:
1 #include <stdio.h>
2

3 // This function takes no arguments and returns no value:


4

5 void hello(void)
6 {
7 printf("Hello, world!\n");
8 }
9

10 int main(void)
11 {
12 hello(); // Prints "Hello, world!"
13 }

4.1 Passing by Value


I’d mentioned earlier that when you pass an argument to a function, a copy of that argument gets made
and stored in the corresponding parameter.
If the argument is a variable, a copy of the value of that variable gets made and stored in the parameter.
More generally, the entire argument expression is evaluated and its value determined. That value is copied
to the parameter.
In any case, the value in the parameter is its own thing. It is independent of whatever values or variables
you used as arguments when you made the function call.
So let’s look at an example here. Study it and see if you can determine the output before running it:
1 #include <stdio.h>
2

3 void increment(int a)
4 {
5 a++;
6 }
7

8 int main(void)
9 {
10 int i = 10;
11

12 increment(i);
13

14 printf("i == %d\n", i); // What does this print?


15 }

At first glance, it looks like i is 10, and we pass it to the function increment(). There the value gets
incremented, so when we print it, it must be 11, right?
“Get used to disappointment.”
—Dread Pirate Roberts, The Princess Bride
But it’s not 11—it prints 10! How?
4.2. Function Prototypes 27

It’s all about the fact that the expressions you pass to functions get copied onto their corresponding pa-
rameters. The parameter is a copy, not the original.
So i is 10 out in main(). And we pass it to increment(). The corresponding parameter is called a in
that function.
And the copy happens, as if by assignment. Loosely, a = i. So at that point, a is 10. And out in main(),
i is also 10.

Then we increment a to 11. But we’re not touching i at all! It remains 10.
Finally, the function is complete. All its local variables are discarded (bye, a!) and we return to main(),
where i is still 10.
And we print it, getting 10, and we’re done.
This is why in the previous example with the plus_one() function, we returned the locally modified
value so that we could see it again in main().
Seems a little bit restrictive, huh? Like you can only get one piece of data back from a function, is what
you’re thinking. There is, however, another way to get data back; C folks call it passing by reference and
that’s a story we’ll tell another time.
But no fancy-schmancy name will distract you from the fact that EVERYTHING you pass to a function
WITHOUT EXCEPTION is copied into its corresponding parameter, and the function operates on that
local copy, NO MATTER WHAT. Remember that, even when we’re talking about this so-called passing
by reference.

4.2 Function Prototypes


So if you recall back in the ice age a few sections ago, I mentioned that you had to define the function
before you used it, otherwise the compiler wouldn’t know about it ahead of time, and would bomb out
with an error.
This isn’t quite strictly true. You can notify the compiler in advance that you’ll be using a function of a
certain type that has a certain parameter list. That way the function can be defined anywhere (even in a
different file), as long as the function prototype has been declared before you call that function.
Fortunately, the function prototype is really quite easy. It’s merely a copy of the first line of the function
definition with a semicolon tacked on the end for good measure. For example, this code calls a function
that is defined later, because a prototype has been declared first:
1 #include <stdio.h>
2

3 int foo(void); // This is the prototype!


4

5 int main(void)
6 {
7 int i;
8

9 // We can call foo() here before it's definition because the


10 // prototype has already been declared, above!
11

12 i = foo();
13

14 printf("%d\n", i); // 3490


15 }
16

17 int foo(void) // This is the definition, just like the prototype!


18 {
19 return 3490;
20 }
28 Chapter 4. Functions

If you don’t declare your function before you use it (either with a prototype or its definition), you’re
performing something called an implicit declaration. This was allowed in the first C standard (C89), and
that standard has rules about it, but is no longer allowed today. And there is no legitimate reason to rely
on it in new code.
You might notice something about the sample code we’ve been using… That is, we’ve been using the
good old printf() function without defining it or declaring a prototype! How do we get away with this
lawlessness? We don’t, actually. There is a prototype; it’s in that header file stdio.h that we included
with #include, remember? So we’re still legit, officer!

4.3 Empty Parameter Lists


You might see these from time to time in older code, but you shouldn’t ever code one up in new code.
Always use void to indicate that a function takes no parameters. There’s never1 a reason to do this in
modern code.
If you’re good at just remembering to put void in for empty parameter lists in functions and prototypes,
you can skip the rest of this section.
There are two contexts for this:
• Omitting all parameters where the function is defined
• Omitting all parameters in a prototype
Let’s look at a potential function definition first:
void foo() // Should really have a `void` in there
{
printf("Hello, world!\n");
}

While the spec spells out that the behavior in this instance is as-if you’d indicated void (C11 §6.7.6.3¶14),
the void type is there for a reason. Use it.
But in the case of a function prototype, there is a significant difference between using void and not:
void foo();
void foo(void); // Not the same!

Leaving void out of the prototype indicates to the compiler that there is no additional information about
the parameters to the function. It effectively turns off all that type checking.
With a prototype definitely use void when you have an empty parameter list.

1
Never say “never”.
Chapter 5

Pointers—Cower In Fear!

“How do you get to Carnegie Hall?”


“Practice!”
—20th-century joke of unknown origin
Pointers are one of the most feared things in the C language. In fact, they are the one thing that makes
this language challenging at all. But why?
Because they, quite honestly, can cause electric shocks to come up through the keyboard and physically
weld your arms permanently in place, cursing you to a life at the keyboard in this language from the 70s!
Really? Well, not really. I’m just trying to set you up for success.
Depending on what language you came from, you might already understand the concept of references,
where a variable refers to an object of some type.
This is very much the same, except we have to be more explicit with C about when we’re talking about
the reference or the thing it refers to.

5.1 Memory and Variables


Computer memory holds data of all kinds, right? It’ll hold floats, ints, or whatever you have. To
make memory easy to cope with, each byte of memory is identified by an integer. These integers increase
sequentially as you move up through memory1 . You can think of it as a bunch of numbered boxes, where
each box holds a byte2 of data. Or like a big array where each element holds a byte, if you come from a
language with arrays. The number that represents each box is called its address.
Now, not all data types use just a byte. For instance, an int is often four bytes, as is a float, but it really
depends on the system. You can use the sizeof operator to determine how many bytes of memory a
certain type uses.
// %zu is the format specifier for type size_t

printf("an int uses %zu bytes of memory\n", sizeof(int));

// That prints "4" for me, but can vary by system.

Memory Fun Facts: When you have a data type (like your typical int) that uses more than a
byte of memory, the bytes that make up the data are always adjacent to one another in memory.
Sometimes they’re in the order that you expect, and sometimes they’re not3 . While C doesn’t
1
Typically. I’m sure there are exceptions out there in the dark corridors of computing history.
2
A byte is a number made up of no more than 8 binary digits, or bits for short. This means in decimal digits just like grandma
used to use, it can hold an unsigned number between 0 and 255, inclusive.
3
The order that bytes come in is referred to as the endianness of the number. The usual suspects are big-endian (with the most
significant byte first) and little-endian (with the most-significant byte last), or, uncommonly now, mixed-endian (with the most-
significant bytes somewhere else).

29
30 Chapter 5. Pointers—Cower In Fear!

guarantee any particular memory order (it’s platform-dependent), it’s still generally possible
to write code in a way that’s platform-independent where you don’t have to even consider
these pesky byte orderings.
So anyway, if we can get on with it and get a drum roll and some foreboding music playing for the
definition of a pointer, a pointer is a variable that holds an address. Imagine the classical score from
2001: A Space Odyssey at this point. Ba bum ba bum ba bum BAAAAH!
Ok, so maybe a bit overwrought here, yes? There’s not a lot of mystery about pointers. They are the
address of data. Just like an int variable can hold the value 12, a pointer variable can hold the address of
data.
This means that all these things mean the same thing, i.e. a number that represents a point in memory:
• Index into memory (if you’re thinking of memory like a big array)
• Address
• Location
I’m going to use these interchangeably. And yes, I just threw location in there because you can never have
enough words that mean the same thing.
And a pointer variable holds that address number. Just like a float variable might hold 3.14159.
Imagine you have a bunch of Post-it® notes all numbered in sequence with their address. (The first one
is at index numbered 0, the next at index 1, and so on.)
In addition to the number representing their positions, you can also write another number of your choice
on each. It could be the number of dogs you have. Or the number of moons around Mars…
…Or, it could be the index of another Post-it note!
If you have written the number of dogs you have, that’s just a regular variable. But if you wrote the index
of another Post-it in there, that’s a pointer. It points to the other note!
Another analogy might be with house addresses. You can have a house with certain qualities, yard, metal
roof, solar, etc. Or you could have the address of that house. The address isn’t the same as the house itself.
One’s a full-blown house, and the other is just a few lines of text. But the address of the house is a pointer
to that house. It’s not the house itself, but it tells you where to find it.
And we can do the same thing in the computer with data. You can have a data variable that’s holding some
value. And that value is in memory at some address. And you could have a different pointer variable hold
the address of that data variable.
It’s not the data variable itself, but, like with a house address, it tells us where to find it.
When we have that, we say we have a “pointer to” that data. And we can follow the pointer to access the
data itself.
(Though it doesn’t seem particularly useful yet, this all becomes indispensable when used with function
calls. Bear with me until we get there.)
So if we have an int, say, and we want a pointer to it, what we want is some way to get the address of
that int, right? After all, the pointer just holds the address of the data. What operator do you suppose
we’d use to find the address of the int?
Well, by a shocking surprise that must come as something of a shock to you, gentle reader, we use the
address-of operator (which happens to be an ampersand: “&”)to find the address of the data. Ampersand.

So for a quick example, we’ll introduce a new format specifier for printf() so you can print a pointer.
You know already how %d prints a decimal integer, yes? Well, %p prints a pointer. Now, this pointer is
going to look like a garbage number (and it might be printed in hexadecimal4 instead of decimal), but it is
merely the index into memory the data is stored in. (Or the index into memory that the first byte of data
is stored in, if the data is multi-byte.) In virtually all circumstances, including this one, the actual value of
the number printed is unimportant to you, and I show it here only for demonstration of the address-of
operator.
4
That is, base 16 with digits 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, and F.
Another random document with
no related content on Scribd:
[717] 1 Cor. ii. 5.
[718] Heraclitus.
[719] Matt. vii. 7.
[720] Ps. xxii. 6.
[721] 1 John iv. 16.
[722] 1 Cor. i. 9, x. 13.
[723] Matt. xviii. 1.
[724] 1 Cor. iv. 15.
[725] John xiv. 6.
[726] By Plato.
[727] In Plato we have νῷ instead of Θεῷ.
[728] John i. 14.
[729] Matt. vii. 7.
[730] Matt. xi. 12.
[731] Hesiod. first line, “Works and Days,” 285. The other three
are variously ascribed to different authors.
[732] Plato, Alcibiades, book i.
[733] Plato, Republic, vi. p. 678.
[734] Matt. xx. 16.
[735] 1 Cor. viii. 7.
[736] 2 Thess. iii. 1, 2.
[737] Quoted by Socrates in the Phaedo, p. 52.
[738] Ecclus. xxvii. 12.
[739] Prov. x. 14.
[740] Prov. xxvi. 5.
[741] 1 Cor. ix. 22.
[742] Matt. v. 45.
[743] Rom. iii. 29, 30.
[744] 1 Cor. ii. 13.
[745] Bas relief.
[746] Isa. xlv. 3.
[747] Ps. lxxviii. 1, 2.
[748] 1 Cor. ii. 6–8.
[749] 1 Cor. ii. 9, 10.
[750] 1 Cor. ii. 14.
[751] 1 Cor. iii. 1–3.
[752] 1 Cor. iii. 10–13.
[753] Rom. i. 11.
[754] Jer. viii. 7.
[755] Iliad, ix. 311.
[756] Eph. iv. 26.
[757] Ex. xx. 17.
[758] It is so said of the rich: Matt. xix. 23; Mark x. 23; Luke
xviii. 24.
[759] Gen. i. 26.
[760] Matt. xi. 29, 30.
[761] Matt. xviii. 3.
[762] Ps. i. 1.
[763] Gal. v. 25.
[764] 2 Cor. v. 7.
[765] Heb. i. 1.
[766] Rev. v. 6; Isa. xi. 12.
[767] Ἄ—τλας, unsuffering.
[768] The Chaldaic ‫ֵּת יבּוָת א‬. The Hebrew is ‫ֵּת ָב ה‬, Sept. κιβωτός,
Vulg. arca.
[769] Eph. v. 23.
[770] 1 Cor. xi. 3; 2 Cor. xi. 31.
[771] And the whole place is very correctly called the Logeum
(λογεῖον), since everything in heaven has been created and
arranged in accordance with right reason (λόγοις) and proportion
(Philo, vol. iii. p. 195, Bohn’s translation).
[772] 1 Cor. xii. 11.
[773] i.e., the oracular breastplate.
[774] Lev. xvi. 23, 24.
[775] This line has given commentators considerable trouble.
Diodorus says that the Telchines—fabled sons of Ocean—were
the first inhabitants of Rhodes.
[776] σύνεσις. Sylburgius, with much probability, conjectures
σύνδεσις, binding together.
[777] Βέδυ, Ζὰψ, Χθὼν, Πλῆκτρον, Σφὶγξ, Κυαξζβὶ, Χθύπτης,
Φλεγμὸς, Δρώψ. On the interpretation of which, much learning
and ingenuity have been expended.
[778] Orpheus.
[779] Lev. xi.; Deut. xiv.
[780] Ps. xvii. 25, 26.
[781] Ex. xv. 1.
[782] Ex. xxi. 33, 36.
[783] Isa. i. 3.
[784] Matt. xi. 13; Luke xvi. 16.
[785] Mark i. 7; Luke iii. 16; John i. 27.
[786] 2 Cor. vi. 14, 15.
[787] 2 Cor. vi. 17, 18.
[788] Eph. iii. 3–5.
[789] Col. i. 9–11.
[790] Col. i. 25–27.
[791] Col. i. 27.
[792] Col. ii. 2, 3.
[793] Col. iv. 2.
[794] Col. iv. 3, 4.
[795] Heb. v. 12, 13, 14, vi. 1.
[796] Isa. ii. 16.
[797] Isa. xlv. 3.
[798] Ps. li. 6, Sept.
[799] Ps. xix. 2, 3.
[800] Rom. xv. 25, 26.
[801] 1 Cor. ii. 6, 7.
[802] 1 Cor. iii. 1–3.
[803] Ps. xxxiv. 8; according to the reading Χριστός for
χρηστός.
[804] 1 Cor. v. 7.
[805] Ex. xxxiii. 18.
[806] Prov. xxx. 2.
[807] Prov. iii. 18.
[808] Ex. xxx. 15, 16, etc.
[809] Gen. xxii. 3, 4.
[810] Or, “the desire of a very good soul,” according to the text
which reads Ἡ ψυχῆς ἀρίστης. The other reading is ἀρίστη.
[811] Baptism.
[812] Isa. lxvi. 1.
[813] Ps. 1. 15.
[814] Acts xvii. 24, 25.
[815] From some apocryphal writing.
[816] ἁγίᾳ is the reading of the text. This is with great
probability supposed to be changed from ἀνῃ, a usual contraction
for ἀνθρωπίνῃ.
[817] Rom. xi. 33.
[818] Alluding to Gen. xviii. 6; the word used is ἐγκρυφίαι,
which Clement, following Philo, from its derivation, takes to signify
occult mysteries.
[819] 1 Cor. vi. 6, 7.
[820] Col. ii. 2, 3.
[821] Matt. xii. 11; Mark iv. 11; Luke viii. 10.
[822] Ps. lxxviii. 2.
[823] Matt. xiii. 33.
[824] According to the conjecture of Sylburgius, σύντονος is
adopted for σύντομος.
[825] Empedocles.
[826] John i. 18.
[827] Acts xvii. 22, 23.
[828] Matt. xi. 27; Luke iii. 22.
[829] John viii. 24.
[830] John iii. 15, 16, 36, v. 24.
[831] Ps. ii. 12.
[832] The text ἐπίστηται, but the sense seems to require
ἐπίστευσε.
[833] πέποιθεν is confidence.
[834] John x. 1–3, 7.
[835] Eph. iii. 5.
[836] Joel ii. 28.
[837] Wisd. vii. 24.
[838] Ps. xxxvi. 5.
[839] Ps. civ. 4.
[840] Eusebius reads ποιητιχῶς.
[841] γενητόν.
[842] Gen. i. 1–3.
[843] Deut. xiii. 4.
[844] The text has πάλιν; Euseb. reads Πλάτων.
[845] The text has ἀνθρώπῳ; Plato and Eusebius, ἀνθρώπois.
[846] Deut. xxx. 15, 19, 20.
[847] τὴν χρυσῆν is supplied, according to a very probable
conjecture.
[848] “Spoken or” supplied from Plato and Eusebius.
[849] μόνον ἐν τῇ πόλει is here supplied from Plato.
[850] Iliad, xiv. 206.
[851] Iliad, xviii.
[852] Μέτρα is the reading of the text, but is plainly an error for
μέτρῳ, which is the reading of Eusebius.
[853] Eph. vi. 12.
[854] Ps. iii. 5.
[855] Matt. xxiv. 42, etc.
[856] Wisd. ii. 12.
[857] Isa. xl. 18, 25.
[858] H. Stephanus, in his Fragments of Bacchylides, reads
αἰκελείων (foul) instead of ἀεικαιλιαν of the text.
[859] Quoted in Exhortation to the Heathen, p. 72, and is here
corrected from the text there.
[860] This is quoted in Exhortation to the Heathen, p. 73, ch.
viii. The reading varies, and it has been variously amended. Θεῷ
is substituted above for σέο. Perhaps the simplest of the
emendations proposed on this passage is the change of σέο into
σο, with Thee.
[861] Heraclitus.
[862] Deut. vi. 4.
[863] See Exhortation, p. 76, where for “So” read “Lo.”
[864] “Οὖτις, Noman, Nobody; a fallacious name assumed by
Ulysses (with a primary allusion to μήτις, μῆτις, Odys. xx. 20), to
deceive Polyphemus.”—Liddel and Scott. The third line is 274 of
same book.
[865] Odys. ix. 410.
[866] Iliad, xxii. 8.
[867] Isa. xl. 18, 19.
[868] All these lines from Epicharmus: they have been
rendered as amended by Grotius.
[869] λόγος [or Word].
[870] Isa. i. 11, 16.
[871] This passage, with four more lines, is quoted by Justin
Martyr, De Monarchia, p. 335, and ascribed by him to Philemon.
[872] Jer. xxiii. 23, 24.
[873] Ps. iv. 6.
[874] In Justin Martyr, in the place above quoted, these lines
are joined to the preceding. They are also quoted by Eusebius,
but differently arranged. The translation adopts the arrangement
of Grotius.
[875] Isa. lxv. 24.
[876] These lines are quoted by Justin (De Monarchia), p. 333,
but ascribed by him part to Philemon, part to Euripides.
[877] Ascribed by Justin to Sophocles.
[878] Adopting the reading κεῖνος instead of καινός in the text.
[879] Quoted in Exhortation, p. 74.
[880] Isa. lxvi. 1.
[881] Isa. lx. 1, 2.
[882] Isa. xl. 12.
[883] Amos iv. 13.
[884] Deut. xxxii. 39.
[885] For οὐρανοὺς ὁρᾶς we read ἀνθρώπους (which is the
reading of Eusebius); and δρῆς (Sylburgius’ conjecture), also
from Eusebius, instead of ἃ θεμις ἀθέμιστα.
[886] Isa. x. 14.
[887] Jer. x. 12.
[888] Isa. xl. 13.
[889] Iliad, viii. 69.
[890] These lines of Æschylus are also quoted by Justin
Martyr, De Monarchia, p. 330. (Dread force, ἄπλατος ὁρμή;
Eusebius reads ὁρμῇ, dative. J. Langus has suggested
(ἄπλαστος) uncreated; ἄπληστος (insatiate) has also been
suggested.) The epithet of the text, which means primarily
unapproachable, then dread or terrible, is applied by Pindar to
fire.
[891] Ps. lxviii. 8.
[892] This Pythian oracle is given by Herodotus, and is quoted
also by Eusebius and Theodoret.
[893] γνωμικώτατα, Eusebius reads γενικώτατον, agreeing with
πατέρα.
[894] A game in which a potsherd with a black and white side
was cast on a line; and as the black or white turned up, one of the
players fled and the other pursued.
[895] Eusebius has κρίνει, which we have adopted, for κρίνειν
of the text.
[896] Plato, Rep. book vii.
[897] According to the reading in Eusebius, πᾶν ἔθνος ἑῷον,
πᾶν δὲ ἑσπερίων ᾐόνων, βόρειόν τε καὶ τό, κ.τ.λ.
[898] Instead of πρόνοιαν, Eusebius has προνομίαν (privilege).
[899] Clement seems to mean that they knew God only in a
roundabout and inaccurate way. The text has περίφασιν; but
περίφρασιν, which is in Eusebius, is preferable.
[900] Isa. xxxvi. 7, 8, 10.
[901] Jonah i. 6, 9, 14.
[902] Mal. i. 10, 11, 14.
[903] Perhaps Bacchylides.
[904] ἀρχαίαν.
[905] The reading of H. Stephanus, ἀγαθὰς Ὥρας, is adopted
in the translation. The text has ἀγαθὰ σωτῆρας. Some supply
Ὥρας, and at the same time retain σωτῆρας.
[906] Jer. iii. 19.
[907] John vi. 27.
[908] Isa. xxxii. 20.
[909] Rom. xiv. 2.
[910] Ps. cxii. 5, 9.
[911] Odyssey, xi. 420.
[912] Homer, Iliad, xxiii. 315: μέγ’ ἀμείνων is found in the Iliad
as in Musæus. In the text occurs instead περιγίνεται, which is
taken from line 318.

“By art rather than strength is the woodcutter greatly


superior;
By art the helmsman on the dark sea
Guides the swift ship when driven by winds;
By art one charioteer excels (περιγίνεται) another.”
—Iliad, xxiii. 315–318.
[913] φύλλον, for which Sylburg. suggests φῦλον.
[914] Iliad, vi. 141–149.
[915] Odyss. xxii. 412.
[916] Iliad, ix. 116.
[917] Ξυνός. So Livy, “communis Mars;” and Cicero, “cum
omnis belli Mars communis.”
[918] Iliad, xviii. 309.
[919] The text has: Νίκης ἀνθρώποισι θεῶν ἐκ πείρατα κεῖται.
In Iliad, vii. 101, 102, we read:

αὐτὰρ’ ὑπένερθεν,
Νίκης πείρατ’ ἔχοντα, ἐν ἀθανάτοισι θεοῖσιν.

[920] Iliad, xvi. 235.


[921] Odyss. xiv. 228.
[922] The text is corrupt and unintelligible. It has been restored
as above.
[923] In some lost tragedy.
[924] Said by Ajax of the sword received from Hector, with
which he killed himself.
[925] The imitator of Thucydides, said to be weaker but clearer
than his model. He is not specially clear here.
[926] The text has, ἀσφαλέστερα παρὰ δόξαν καὶ κακοπραγίαν;
for which Lowth reads, ἐπισφαλέστερα πρὸς κακοπραγίαν, as
translated above.
[927] Iliad, xxiv. Clement’s quotation differs somewhat from the
passage as it stands in Homer.
[928] The text has δοίη, which Stobæus has changed into δ’
ἵση, as above. Stobæus gives this quotation as follows:

“The bastard has equal strength with the legitimate;


Each good thing has its nature legitimate.”

[929] As no play bearing this name is mentioned by any one


else, various conjectures have been made as to the true reading;
among which are Clymene Temenos or Temenides.
[930] Odyssey, xiv. 187.
[931] In Theognis the quotation stands thus:

Οἶνον τοι πίνειν πουλὸν κακόν, ἢν δέ τις αὐτὸν


Πίνῃ ἐπισταμένως, oὐ κακὸς ἀλλ’ ἀγαθός.
“To drink much wine is bad; but if one drink
It with discretion, ’tis not bad, but good.”

[932] From Jupiter’s address (referring to Pandora) to


Prometheus, after stealing fire from heaven. The passage in
Hesiod runs thus:

“You rejoice at stealing fire and outwitting my mind;


But I will give you, and to future men, a great plague.
And for the fire will give to them a bane in which
All will delight their heart, embracing their own bane.”

[933] Translated as arranged by Grotius.


[934] Odyss.
[935] συμμανῆναι is doubtless here the true reading, for which
the text has συμβῆναι.
[936] The text has κατ’ ἄλλα. And although Sylburgius very
properly remarks, that the conjecture κατάλληλα instead is
uncertain, it is so suitable to the sense here, that we have no
hesitation in adopting it.
[937] The above is translated as amended by Grotius.
[938] παύροισι, “few,” instead of παρ’ οἷσι, and πράσσοντας
instead of πράσσοντα, and δύαις, “calamities,” instead of δύᾳ, are
adopted from Lyric Fragments.
[939] ψυδνός—ψυδρος—which, however, occurs nowhere but
here—is adopted as preferable to ψεδνός (bald), which yields no
sense, or ψυχρος. Sylburgius ms. Paris; Ruhnk reads ψυδρός.
[940] A mistake for Herodotus.
[941] Instead, of Μαραθωνίται, as in the text, we read from
Thucydides Μαραθῶνί τε.
[942] Πυτίνῃ (not, as in the text, Ποιτίνῃ), a flask covered with
plaited osiers. The name of a comedy by Cratinus (Liddel and
Scott’s Lexicon).
[943] Iliad, xii., Sarpedon to Glaucus.
[944] Grotius’ correction has been adopted, ἐγγύας δὲ ζαμία,
instead of ἐγγύα δὲ ζαμίας.
[945] In the text before In Hexameters we have τηρήσει, which
has occasioned much trouble to the critics. Although not entirely
satisfactory, yet the most probable is the correction θέλουσι as
above.
[946] Iliad, xvii. 53.
[947] i.e. Polyphemus, Odyss. ix. 372.
[948] According to the correction of Casaubon, who, instead of
ἀραρότως of the text, reads Ἀραρώς. Others ascribed the comedy
to Aristophanes himself.
[949] i.e. washed.
[950] Eusebius reads, “invoking the common Father, God,” viz.
Πανελλήνιος Ζεύς, as Pausanias relates.
[951] 1 Sam. xi. 18.
[952] Matt. v. 45.
[953] Instead of νοῦσον σιδηρόν, the sense requires that we
should, with Sylburgius, read νούσοισι δηρόν.
[954] Ps. lxxxiv. 1.
[955] Deut. x. 16, 17.
[956] Isa. xl. 26.
[957] 1 Tim. vi. 16.
[958] Deut. iv. 12.
[959] Ὡροσκόπος.
[960] We have the same statement made, Stromata i. 19, Ante-
Nicene Lib. p. 413, Potter 372; also v. 14, Ante-Nicene Lib. p.
298, Potter 730,—in all of which Lowth adopts περίφρασιν as the
true reading, instead of περίφασιν. In the first of these passages,
Clement instances as one of the circumlocutions or roundabout
expressions by which God was known to the Greek poets and
philosophers, “The Unknown God.” Joannes Clericus proposes to
read παράφασιν (palpitatio), touching, feeling after.
[961] i.e. “The word of God’s power is His Son.”
[962] Instead of ἡν...ἐξουσίας, as in the text, we read ὧν
ἐξουσιαν.
[963] None of the attempts to amend this passage are entirely
successful. The translation adopts the best suggestions made.
[964] i.e. of atonement.
[965] Jer. xxxi. 31, 32; Heb. viii. 8–10.
[966] Most likely taken from some apocryphal book bearing the
name of Paul.
[967] Matt. xxiii. 4; Luke xi. 47.
[968] Matt. ix. 22, etc.
[969] The passage which seems to be alluded to here is Job
xxviii. 22, “Destruction and Death say, We have heard the fame
thereof with our ears.”
[970] εὐηγγελίσθαι used actively for εὐαγγελίσαι, as also
immediately after εὐηγγελισμένοι for εὐαγγελισάμενοι.
[971] 1 Pet. iii. 19, 20.
[972] Potter, p. 452; Ante-Nicene Library, vol. ii. Clement, p. 28.
[973] Ezek. xviii. 23, 32, xxxiii. 11, etc.
[974] Hermas, book iii. chap. xvi. Ante-Nicene Library, 420.
Quoted also in Stromata ii. Ante-Nicene Library, p. 218, from
which the text here is corrected; Potter, 452.
[975] Matt. xxvii. 52.
[976] τάξιν.
[977] Rom. ix. 3.
[978] Apparently God’s voice to them. Sylburgius proposes to
read φύσεως instead of φωνῆς here.
[979] 1 Pet. iii. 19.
[980] 1 Cor. i. 29.
[981] Alluding apparently to such passages as Acts iii. 17, 19,
and xvii. 30.
[982] Deut. xxx. 15, 19.
[983] Isa. i. 19, 20.
[984] Ps. xvi. 9–11; Acts ii. 26–28.
[985] Isa. xi. 7.
[986] Isa. xliii. 20.
[987] Wisd. vi. 7.
[988] Ps. ix. 15.
[989] Ps. ix. 9.
[990] Ps. ix. 11.
[991] Ps. xi. 7.
[992] Ps. xi. 6, Septuagint version.
[993] Sylburgius’ conjecture, εὐεργετικόν, seems greatly
preferable to the reading of the text, ἐνεργητικόν.
[994] Grabe reads λόγος for λαός, “Word of the Beloved,” etc.
[995] Grabe suggests, instead of δρῦς here, δρύοψ, a kind of
woodpecker, mentioned by Aristophanes.
[996] Ps. cii. 9. The text reads, γῆν σποδόν. Clement seems to
have read in Ps. cii. 9 γῆν and σποδόν. The reading of the
Septuagint may have crept into the text from the margin.
[997] John i. 3.
[998] Gen. i. 1.
[999] Heb. i. 1.
[1000] Matt. xxiii. 8–10.
[1001] Eph. iii. 14, 15.
[1002] “Tried in a furnace of earth;” Jerome, “tried in the fire,
separated from earth.”
[1003] Ps. xii. 6.
[1004] Prov. x. 20.
[1005] The Latin translator appears to have read what seems
the true reading, ἐπίτασις, and not, as in the text, ἐπίστασις.
[1006] Col. ii. 8.
[1007] Heb. v. 12.
[1008] Col. ii. 8.
[1009] Ps. cxix. 125.
[1010] Ps. cxix. 69.
[1011] Ps. cxix. 20.
[1012] Acts x. 34, 35.
[1013] Ps. cxviii. 19, 20.
[1014] Ps. xxix. 3.
[1015] Ps. ix. 17.
[1016] Job xi. 2.
[1017] Jude 22, 25.
[1018] 2 Cor. xi. 14.
[1019] γνωστική.
[1020] γνωστικῶν, for which Hervetus, reading γνωστικόν, has
translated, “qui vere est cognitione præditus.” This is suitable and
easier, but doubtful.
[1021] Wisd. vii. 17, 18.
[1022] Adopting the various reading καθ’ ὅ, and the conjecture
ὁρᾶται, instead of καθ’ ὅν and ὁράσει in the text, as suggested by
Sylburgius.
[1023] 1 Tim. vi. 16.
[1024] Eph. i. 4, 5.
[1025] Quoted afterwards, p. 362, and Stromata, book vii. p.
743, Paris ed.
[1026] The text has ἐπίμικτος, which on account of its
harshness has been rejected by the authorities for ἐπίκτητος.
[1027] Our choice lies between the reading of the text,
προσίσεται; that of Hervetus, προσοίσεται; the conjecture of
Sylburgius, προσείσεται, or προσήσεται, used a little after in the
phrase προσήσεται τὴν ἀλήθειαν.
[1028] There is some difficulty in the sentence as it stands.
Hervetus omits in his translation the words rendered here, “let it
be by all means dissolved.” We have omitted διὰ τούτους, which
follows immediately after, but which is generally retained and
translated “by these,” i.e. philosophers.
[1029] τῶν λόγων, Sylburgius; τὸν λόγον is the reading of the
text.
[1030] Ps. cxii. 6.
[1031] Ps. cxii. 7.
[1032] Ps. cv. 3, 4.
[1033] Heb. i. 1.
[1034] Pindar.
[1035] Gen. xiv. 14. In Greek numerals.
[1036] The Lord’s sign is the cross, whose form is represented
by Τ; Ιη (the other two letters of τιή, 318) are the first two letters of
the name Ἰησοῦς (Jesus).
[1037] Gen. vi. 5.
[1038] The sum of the numbers from 1 to 15 inclusive is 120.
[1039] “Triangular numbers are those which can be disposed in
a triangle, as 3 ,6 , etc., being represented by the formula

(Liddel and Scott’s Lexicon). Each side of the triangle of


course contains an equal number of units, the sum of which
amounts to the number.
[1040] This number is called equality, because it is composed
of eight numbers, an even number; as fifty-six is called inequality,
because it is composed of seven numbers, an odd number.
[1041] The clause within brackets has been suggested by
Hervetus to complete the sense.
[1042] That is, 1 + 3 + 5 + 7 + 9 + 11 + 13 + 15 = 120; and 1 +
3 = 4 + 5 = 9 + 7 = 16 + 9 = 25 + 11 = 36 + 13 = 49 + 15 = 64,
giving us the numbers 4, 9, 16, 25, 36, 49, 64, the squares of 2, 3,
4, 5, 6, 7, 8.
[1043] ἑτερομήκεις, the product of two unequal factors, i.e. 2 +
4 + 6 + 8 + 10 + 12 + 14 = 56; and 2 + 4 = 6 = 3 × 2, 6 + 4 = 10 =
5 × 2, and so on.
[1044] The cross.
[1045] Eph. iv. 13.
[1046] Ex. xxv. 23. The table is said to be two cubits in length,
a cubit in breadth, and a cubit and a half in height; therefore it
was six cubits round.
[1047] Ex. xxv. 24.
[1048] The three styles of Greek music were the ἐναρμονικόν,
διάτονον, and χρωματικόν.
[1049] i.e. of Christ.
[1050] 1 Cor. x. 26, etc.
[1051] ψάλλοντες is substituted by Lowth for ψάλλειν of the
text; ἐν τῷ ψάλλειν has also been proposed.
[1052] Ps. xlv. 10.
[1053] Ps. xlv. 14, 15.
[1054] διδακτικήν, proposed by Sylburgius, seems greatly
preferable to the reading of the text, διδακτήν, and has been
adopted above.
[1055] Wisd. vi. 10.
[1056] Wisd. vii. 18.
[1057] Wisd. xiv. 2, 3.
[1058] That is, resurrection effected by divine power.
[1059] Such seems the only sense possible of this clause,—
obtained, however, by substituting for συνάλογοι λόγου, κ.τ.λ.,
σύλλογοι λόγον, κ.τ.λ.
[1060] John iii. 30.
[1061] John i. 3.
[1062] Eph. ii. 20, 21.
[1063] Matt. xiii. 47, 48.
[1064] Prudence, fortitude, justice, temperance.
[1065] i.e. that mentioned in the last sentence of chap. xi.,
which would more appropriately be transferred to chap. xii.
[1066] Wisd. ii. 22, 25.
[1067] Ps. xvii. 3, 4.
[1068] Sylburgius proposes κοσμικάς, worldly, instead of
κοσμίας, decorous; in which case the sentence would read: “and
[true] poverty, destitution in worldly desires.”
[1069] Gen. xviii. 12.
[1070] The reading of the text has, “not of the same mother,
much less of the same father,” which contradicts Gen. xx. 12, and
has been therefore amended as above.
[1071] 1 Sam. i. 13.
[1072] Or, “judging from the motion of the soul;” the text
reading here οὐ κινήματος ψυχῆς, for which, as above, is
proposed, οὐκ ἐκ κινήματος ψυχῆν.
[1073] Tob. xii. 8.
[1074] Metaphorical expression for perfect. The phrase “a
quadrangular man” is found in Plato and Aristotle.
[1075] 2 Cor. v. 1, 7.
[1076] Ex. xxxiv. 29.
[1077] Matt. v. 48.
[1078] John xiii. 33.
[1079] This is cited by Diogenes Laertius as the first dictum of
Epicurus. It is also referred to as such by Cicero, De Natura
Deorum, and others.
[1080] In opposition to the heretical opinion, that those who are
saved have an innate original excellence, on account of which
they are saved.
[1081] Or, “elected”—χειροτονούμενος. Acts xiv. 23, “And when
they had ordained (χειροτονήσαντες) them elders in every
church.” A different verb (καθίστημι) is used in Tit. i. 5.
[1082] Presbytery or eldership.
[1083] πρωτοκαθεδρία, Mark xii. 39, Luke xx. 46.
[1084] Rev. iv. 4, xi. 16.
[1085] Eph. ii. 14, 15, 16, iv. 13.
[1086] προκοπαί.
[1087] 1 Thess. iv. 17.
[1088] 1 Cor. xv. 41.
[1089] Eph. iv. 13.
[1090] Ps. xv. 1.
[1091] John i. 47; Matt. v. 8.
[1092] ἐποπτεία, the third and highest grade of initiation of the
Eleusinian mysteries (Liddel and Scott’s Lexicon).
[1093] John x. 16.
[1094] John x. 28.
[1095] Mark v. 34, etc.
[1096] The text here has ὁτι, for which has been substituted
(Potter and Sylb.) οἱ, as above; τήν after αὐλῆς (fold) requires to
be omitted also in rendering the sentence as we have done.
[1097] Wisd. iv. 17.
[1098] Wisd. v. 3–5.
[1099] Deut. iv. 19.
[1100] Isa. xl. 15.
[1101] The author reckons three kinds of actions, the first of
which is κατόρθωμα, right or perfect action, which is characteristic
of the perfect man and Gnostic alone, and raises him (εἰς τὴν
ἀνωτάτω δόξαν) to the height of glory. The second is the class of
τῶν μέσων, medium, or intermediate actions, which are done by
less perfect believers, and procure a lower grade of glory. In the
third place he reckons sinful actions (ἁμαρτητικάς), which are
done by those who fall away from salvation (Potter).
[1102] To produce this sense, καθῆκεν of the text is by Potter
changed into καθήκειν.
[1103] On the authority of one of the MS. Sylburgius reads
ὅλον instead of λόγον in the text.
[1104] Matt. viii. 26; Mark viii. 36; Luke ix. 25.
[1105] From the Acharneis of Aristophanes, quoted also by
Cicero; with various readings in each. Heinsius substitutes
παλαμάσθων for παλαμᾶσθαι of the text.
[1106] Wisd. iv. 9.
[1107] Wisd. iv. 14.
[1108] Matt. xiii. 8.
[1109] Ps. 1. 27.
[1110] Matt. xxv. 10.
[1111] Matt. x. 27; Luke xii. 3.
[1112] Matt. v. 20.
[1113] Ps. xlv. 4.
[1114] Hos. xiv. 9.
[1115] Amos v. 13.
[1116] Matt. xi. 15.
[1117] Ps. xviii. 11, 12.
[1118] Isa. l. 4.
[1119] Isa. l. 5.
[1120] Col. ii. 8.
[1121] Rom. xi. 17.
[1122] i.e. the graft is assimilated; so the Latin translator. But in
the text we have συνεξομοιουμένῃ, dative, agreeing with fatness,
which seems to be a mistake.
[1123] Or inoculation (ἐνοφθαλισμός).
[1124] Wisd. vi. 12–15.
[1125] Wisd. vi. 16.
[1126] Wisd. vi. 17–20.
[1127] 1 Cor. ix. 19.
[1128] Dan. v. 7, 29.
[1129] Matt. xiii. 34.
[1130] John i. 3.
[1131] Prov. viii. 9.
[1132] Heinsius, in a note, remarks that Plato regarded ὁσιότης
and δικαιοσύνη as identical, while others ascribe the former to the
immortals (as also θέμις); ὁσιότης, as the greater, comprehends
δικαιοσύνη. He also amends the text. Instead of κοινόν he reads
ὡς κοινόν τι, supplies κατά before θείαν δικαιοσύνην, and
changes ὑπάρχουσαν into ὑπαρχούσῃ.
[1133] μετ’ αὐτὸν τὸ ζῇν παρεβάλοντο. The translation of
Hervetus, which we have followed, supposes the reading αὐτοῦ
instead of αὐτόν. Others, retaining the latter, translated τὸ ζῇν
παρεβάλοντο (sacrificed life). But the former is most to the
author’s purpose.
[1134] If we retain the reading of the text, we must translate
“founding,” and understand the reference to be to the descent of
the new Jerusalem. But it seems better to change the reading as
above.
[1135] Prov. i. 1–4.
[1136] Prov. i. 5, 6.
[1137] i.e. Solomon.
[1138] Isa. viii. 1.
[1139] Mark x. 48, etc. etc.
[1140] Matt. xvi. 17.
[1141] i.e. the Commandments.
[1142] For perfect wisdom, which is knowledge of things divine
and human, which comprehends all that relates to the oversight of
the flock of men, becomes, in reference to life, art (Instructor,
book ii. chap. ii; Clem. Alex. vol. i. 204, Ante-Nicene Library).
[1143] Gal. v. 17.
[1144] The text reads ἐντολαῖς, which, however, Hervetus,
Heinsius, and Sylburgius, all concur in changing to the
nominative, as above.
[1145] Gal. v. 17.
[1146] Ex. xx. 2, 3.
[1147] i.e. commandment. The Decalogue is in Hebrew called
“the ten words.”
[1148] The text has τρίτος, but Sylburgius reads τέταρτος, the
third being either omitted, or embraced in what is said of the
second. The next mentioned is the fifth.
[1149] i.e. Christ.
[1150] μεσευθυς μέσος and εὐθύς, between the even ones,
applied by the Pythagoreans to 6, a half-way between 2 and 10,
the first and the last even numbers of the dinary scale.
[1151] Luke xx. 35.
[1152] i.e. with the three disciples.
[1153] The numeral ςτ’ = 6. This is said to be the Digamma in
its original place in the alphabet, and afterwards used in mss. and
old editions as a short form of ςτ (Liddel and Scott’s Lexicon).
[1154] That is, Christ, who answers to the numeral six.
[1155] Ps. xix. 1.
[1156] Rev. xxi. 6.
[1157] John i. 3.

You might also like