-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintroduction.tex
605 lines (546 loc) · 31.2 KB
/
introduction.tex
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
\chapter{Introduction}
C programming language is a relatively low-level programming language with an
inclination towards system programming. This book will try to serve both as a
tutorial and reference of C programming language. If you have not programmed
earlier then you should read in linear manner. Even if you have programmed it
would be better if you read the book in linear fashion because there are
certain points which you may miss if you skip chapters. Of all popular
mainstream languages C, and Lisp are two oldest but we cannot really say that
Lisp is really popular. It has a niche area(artificial intelligence) and it is
there for that. So let me redefine my statement. Of all general-purpose and
popular programming language C is the oldest. FORTRAN is another very old
language but it is not general purpose programming language. So what makes C so
special that it is still out there. Well, C and Unix were born almost together
in early 1970s. Then Unix was ported in C and the notion that operating systems
can be only written in assembly language, because it has to do time critical
things, was destroyed. After that Unix became very popular. Then when C++ was
not yet there Windows was written in C and more and more programs were written
in C. It might have been the case that Microsoft and Apple would have written
their OS in C++ had it been there. So, essentially what happened that there is
a lot of code base which is there in C. Also, C++'s backward compatibility is
one of the reasons why C++ is so popular. When C was invented there was no
structured programming language and code was mostly written in assembly. With C
it gave the power of assembly and benefits of structured language like code
reuse, modularity, and portability among others. Because of these reasons C
became immensely popular and is still popular.
C is simple, small, succinct. It may be dirty but is quick. It may have its
quirks but it is a success. C is really so simple yet so deceptive. It will
take one years of programming to really thoroughly understand it.
C is currently described by ISO\/IEC 9899:2011 which you can buy on web or you
can get the draft revision
\url{http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf}. It
is not necessary to buy the specification as draft is very much similar. I will
refer to specification in the form of (§ iso.x.x.x.x) to point to sections
where exact information is discussed. Note that specification is written for
accuracy and the language is not trivial to understand. At the same time, it
does not directly address programmers but compiler writers because there are
certain decisions which specification does not make but rather leaves for
compiler authors' decision.
\section{Why C?}
Because it is the most common denominator. Any language be it C++, Java, Perl,
Python etc have got bindings in C. Whenever you are willing to extend these
languages you need to know C. Also, if by any chance you are going towards
system programming you need to C. C is everywhere. There is no escape from
learning it; it does not matter whether you like it or not.
There is one more important point worth noting here is that C++ is far more
complex compared to C. It is generally accepted that one should not try to
learn C++ as one's first programming language. If you search web then you will
find that many great computer scientists like Ken Thompson, Richard Stallman,
Donald Knuth etc. clearly say that they do not like C++ because it is overly
complex. Also, the runtime(virtual functions) calculations of C++ make it
slightly slower than C. However, C++ has its own strengths and it excels as
well if used properly. Wherever there is a memory constraint or extreme high
performance is needed C is preferred. The simple syntax of C means its code is
very verbose for programmer in the sense that if you read code then you can
very easily see what instructions the code is going to translate into.
It is very easy to write interfaces to other languages because other languages
expose there objects in terms of C structures not the other way around. The
reason for this is huge popularity of C, maturity and large code base.
One more important feature is portability. Note that if you want your program
to have high degree of portability then you should not use C99 features but
rather ANSI C because ANSI C compilers are available on most platforms. Even
though Java claims to be portable or other interpreted languages they are
limited by the fact that the interpreters or VMs(JVM in case of Java) is not
available on all the platforms. Therefore, C is the MOST portable language.
One of the advantages with C is that since it is very old a lot of software has
been written using it. GNU/Linux for example uses C for its kernel. GNOME which
is one of the desktop environments of GNU/Linux is also written in C. The fact
is that since a lot of libraries are available in C thus it makes a lot of work
very easy to do in C since the infrastructure or ecosystem is developed and
mature. At the same time, since C is taught in many colleges and universities
as first course in programming a lot of people know C thus if you are writing
free(as in freedom) software then you have a much higher chance of getting
support if you write your code in C.
\section{History}
C was formally delivered to this world in 1972 and conceived by Dennis
MacAlistair Ritchie in 1968. What happened was there was a project for
development of a text processor and GE-645 was bought by AT\&T Bell Labs. At
that time Ken Thompson had developed a game called ``Space Travel''. Then they
had another machine PDP-11. Before that they had PDP-7. Now all the time the
code for ``Space Travel'' had to be rewritten and also the Unix had to be
ported. So when C was invented it was used to write Unix code in C. And then
``Space Travel''. I do not know what was the real motivation the language, the
OS or the game. But such is the story. Also, I have not studied much in this
about the exact events. In 1972 C was formally announced. C takes its features
from BCPL a language by Martin Richard and B by Ken Thompson. AT\&T Bells labs
gave Unix and a C compiler to many universities at a normal fees and it grew
with leaps and bounds from there and became a ubiquitous language. For many
years ``The C Programming Language'' served as a reference of C. Later it was
standardized by ANSI and then by ISO standards. A very detailed history of C
programming language can be found at
\url{http://cm.bell-labs.com/cm/cs/who/dmr/chist.html} which has been described
by Dennis Ritchie himself.
\index{Dennis Ritchie}
\index{Ken Thompson}
\section{Comparison with Other Languages}
C is a structured, statically typed, somewhat low-level, high-performance
compiled language. It does not support object-oriented programming like most
modern programming including C++, Java, Perl, Python, Ruby etc. However, that
does not mean you cannot do object-oriented programming in C. It is just that C
does not have support at the language level and it is painful to do so. C is
low level because it allows you to handle memory contents directly. You have
something called void which is raw representation of memory content. C also
does not support functional or generic programming but again it is possible to
do so with painful hacks. One of the coveted features is C programs deliver
very high performance if written correctly as it does not have runtime
penalties of virtual functions of OOP (object-oriented programming) languages.
\section{How to learn programming?}
Programming is exactly like Mathematics. As in Mathematics you need to read
theory, understand solved problems and then solve more and more problems by
yourself. If you cannot solve ask your teacher. Similarly, in programming you
need to read about language, try examples given, read code written by others
and then develop your own code. If you get stuck there are umpteen number of
tutorials, mailing lists and groups to help you. I recommend comp.lang.c user
group for C programming. Its interface is at
\url{http://groups.google.com/group/comp.lang.c/}. You should join it and
participate there. \url{http://www.stackoverflow.com/} is also a very good
forum to ask questions about programming in general. You can also come at my
website
\url{http://kunjika.libreprogramming.org} and ask questions or have a
discussion.
\section{What is a computer Program?}
Since this book is written for even beginner please allow me to start from
beginning. As the reader may know a computer consists of many components and
one of the most or rather most important part is processor often named as CPU
(central processing unit). The logic gates in CPUs are formed and instructions
like ADD (addition), SUB (subtraction), MUL (multiplication), DIV (division)
etc are implemented in hardware of CPU. When we write a program say C program
the instructions given in our program is translated to a format which operating
system can understand. In our case that is GNU/Linux this executable format is
known as ELF (executable and linkable format). For the curious you can read
\url{http://en.wikipedia.org/wiki/Executable\_and\_Linkable\_Format} and there are
lots of specification for different CPUs. Then operating system interprets
these files and ask CPU to perform action. So a C program does not directly
talk to processor but it rather talks to operating system or kernel of the
operating system and in turn the operating system or kernel provides services
to your program. There is a typical life cycle in development of a C
program. First you, the programmer, uses a text editor like \texttt{Emacs} to
enter the program then you use a compiler like \texttt{gcc} to compile the
program. Then you may get warnings and errors either from prepreocessor,
compiler or linker all of which are wrapped by \texttt{gcc} in one step. Now
there can be error in your compilation command, which, you used to compile the
program or the program itself. If the error is in command then we need to fix
the command or if the error is in program then we need to fix the program and
compile it again. However, only successful compilation does not guarantee that
program is working. It must run well also. If it does not run well then
somewhere in code things are wrong and then we need to either examine the
source code or debug it using a debugger like \texttt{gdb}. Given below is the
complete cycle of what we do in development of a program as a diagram for quick
understanding.
\begin{figure}[t!]
\begin{center}
\includegraphics{figs/flowchart-fig1.pdf}
\end{center}
\caption{Life cycle of development of a program}
\end{figure}
\section{Attributes of a Program}
You may be wondering so that is very easy. You just learn programming in C and
start hacking on keyboard to produce software. Well, that is partially true but
a program has several desired attributes which you must consider. Any program
cannot be considered a good program unless it satisfies following requirements
or possess following attributes (Note: These are generic attributes and not
specific to C programming language):
\index{program!attributes}
\begin{enumerate}
\item \textbf{Correctness:} Correctness means that a program satisfies its
requirement specification. It means that for a specified input the specified
output should be produced. This particular attribute is of most
significance. It does not matter whether other attributes are present or not
but this one is a must. If a program behavior is not correct then it is of no
use.
\item \textbf{Efficiency:} Efficiency is second to correctness only. Say you
are developing a text editor and you take 5 seconds to load a 10KB text file
then by no means you can persuade a user to use you text editor. A
program/software must be as efficient as possible. Sometimes it clashes with
other attributes and also depend on the problem domain that how strict are
the requirements.
\item \textbf{Security:} A very highly desirable feature in programs which deal
with more than one computer and also for desktop applications. It is very bad
if someone can take advantage of buffer overflow, stack overflow, integer
overflow etc. in your program and you must guard against these at all
times. Note that to provide security you must put extra checks which will go
against efficiency.
\item \textbf{Robustness:} Sometimes users will not give correct inputs. For
example they may enter a character when an integer is asked for or they can
give input beyond range. In such cases you must handle the erroneous
input. This is just one example. Sometimes your memory allocation may
fail. The rule is program defensively. All such input validations and checks
on memory do take a toll on our second attribute but that does not mean that
we can neglect it.
\item \textbf{Maintainaibility:} Even a one line program has to be maintained
if it is worth it! Typically the life of a program far exceeds the
development time. In almost all the cases the original programmer is not
maintainer. Because of these reasons you must strive for maintainability. You
should follow some coding standards like I highly recommend
\url{http://www.gnu.org/prep/standards/}. Clear documentation is one of the
prerequisites of maintainability.
\item \textbf{Extensibility:} Let us take our example of text editor and say
our editor is complete. Now someone else would like to provide a plugin which
will enable syntax highlighting and project management for this editor. So,
in order to do so you can choose a plugin-based extensible architecture or
you can allow them to extend the editor using scripting languages like Guile,
Python, Lua etc.This features allows user to collaborate and make your
program better. Remember the rule is the more the merrier here.
\item \textbf{Portability:} It is an elusive and painful but a goal which all
software desire. Let us say we write our text editor GUI using something like
Xlib directly then we will have to port the entire GUI for other non X-based
OSes. So we can choose some cross-platform GUI libraries like GTK+, Qt,
WxWidgets etc. Even then when system calls come in your software you can do
not much but either write wrappers and do conditional compilation.
\end{enumerate}
\section{Tools of the Trade}
At the very least you need a compiler, an editor and a linker. Almost all
GNU/Linux systems install GCC by default which is the compiler we are going to
use and it includes linker ld. There are several editors you can use from but I
am going to use Emacs along with Sr-speedbar and Flymake plugins. Other options
include VI, Kate, Gedit, Kwrite etc. A debugger is optional but if you want to
go far with C programming then you must learn to use a debugger. GDB is a very
nice debugger and we are going to use it for debugging in Emacs itself. Emacs
has native support for debugging with GDB. For dynamic memory checking, heap
corruption, cache corruption etc I am going to show you how to use
valgrind. Again, valgrind is optional but it becomes mandatory if you want to
work on large projects. For profiling gprof and for code coverage gcov. Note
that you can use gcc for compiling programs. Most of the GNU/Linux systems come
with gcc. For compiling programs I will use GNU Make though in the beginning I
will show you how to compile on command line. Again, profiling, code coverage
and make are optional to learn C but practically they are necessary to develop
any software worth its value.
You may choose another editor or IDE but I will recommend against IDEs for
beginners as they hide much of compilation process from the users. The reason
of choosing Emacs as an editor is its power. Emacs is hard to learn but it is
very powerful and I implore you to spend some time and learn it. Learning Emacs
will pay rich dividends in future to you. Emacs comes with its manual which you
can read in menu for Help. For using more tools like Sr-speedbar and Flymake
mode you can read more on Emacs Wiki. A lot of extensions are available at
Marmalade Repo. In fact it is wrong to say that Emacs is an editor. You can
read your email, play games, have a shell, read news, do remote editing, browse
web and many other things. It is so powerful that some people set it to run
when they login and they never get out of it.
\section{Bits and Bytes}
\index{bit}
\index{byte}
The smallest unit a computer can understand is called a bit. The term bit
was coined by John W. Tukey who had also coined ther term software. ``bit''
is a contraction for binary digit. His 1958 paper ``The Teaching of Concrete
Mathematics'' contains the first usage of the word softwrare. The values for a
\index{John Tukey}
bit is either 0 or 1. Consider a voltage. It can be 0V or 1.5V or whatever the
core CPU voltage is. CPU does not understand numbers but voltages :-). You
cannot expect an electronics hardware to understand the same semantics of 0 and
1 which we know. 0 and 1 are abstraction of CPUs voltages in programming. Four
bits form a nibble and eight a byte. A byte is the area of memory which
can be addressed by CPU and its content manipulated. To address a memory a CPU
has say 4 or 8 or up to 256 pins. For example, in a common 32-bit CPU there are
32 pins whose voltages may represent 0 or 1. Consider all pins are low i.e. 0
then the memory location pointed to is 00000000000000000000000000000000 i.e. a
8 bit memory at location 0 can be accessed. This memory is also called primary
memory or RAM (Random Access Memory). So computing this way we can see that a
32-bit processor can access $2^{32}$ bytes or 4,294,967,296 bytes. You can
arrive at this number by 4*1024*1024*1024. This is equivalent to 4GB of
RAM. However, modern Intel processors have 36 physical pins to address up to
64GB of memory. That does not mean that all 64-bit CPUs have 64 pins for
addressing memory as 16 Exabytes(approximately 16 * 10 18 ) is really, really
huge amount of memory which is not needed by any single monolithic system
practically and will be very expensive, thus it is not practical Another point
is that this much memory will require huge area because RAM is not as compact
as hard disk. There are more important practical aspects that if such a
computer fails then it will cause massive loss in productivity of the system
which employs such a computer. Thus computers are kept much smaller than this
size and tasks are divided on those computers and in case one of them fails
then it does not affect the entire system. But all that is an architectural
concern the point I am saying is it is impractical as of now to have so much
RAM in a system but again no one knows future.
Since a byte has 8 bits, its value may range from 0 to 255 as $2^8$ is 256. For
unsigned data type this will be the range. When all bits are 0 value is zero
and when all are high it is 255. Computers use two's complement form to
represent binary number. So if these 8-bits represent signed number the range
will be from $-2^7$ to $2^7-1$ that is -128 to 127. s you will see later at
lowest levels C allows you to access even one bit using something called
bit-fields. If you read specification it will signify the range of one 8-bit
byte as -127 to 127 because it also takes in to consideration of 1’s complement
computers in which positive and negative zeroes are different.
\section{Notes on Number Sytems}
A number system is a system which determines the rules and symbols for numbers
on how we are going to use them. A number system consists of symbols for
representing numbers and a dot for representing fractional numbers. Minus sign
is used to represent negative numbers. A number system ranges from $-\infty$ to
$\infty$. It is best represented by a straight line given below:
\begin{figure}[H]
\begin{center}
\includegraphics{figs/ns.pdf}
\end{center}
\caption{Number Axis}
\end{figure}
Each point on this axis represents a number. It may be integer or fractional
number. An integer is a whole number like -1, -2, 0, 5, 7 etc. Floating-point
numbers have fractional parts like 1.234. The important fact to note is that
between any two points there exists infinite numbers. In other words between
any two numbers there exists infinite numbers. For example, between 1.2 and 1.3
there are 1.21, 1.22, 1.23..., 1.29. Moreover between 1.21 and 1.22 there are
1.211, 1.212, 1.213 and so on. It enables us to represent a point on this
axis. The numbers I have written are supposedly in decimal number system. Base
of decimal number system is 10. Why because it consists of 10 distinct symbols
0 through 9. Similarly we can have any other number system. Popular number
systems in computers are binary, octal and hexadecimal not to mention decimal
of course.
A number in a generic number system is given below:
\begin{equation}
(.. c_mb^{m-1} + c_{m-1}b^{m-2}+ ... + c_2b^1 + c1_b^0 + c_{-1}b^{-1} +
... + c_{-m}b^{-m} ) \\ = (... c_mc_{m-1}...c_2c_1.c_{-1}...c_{-m})_b
\end{equation}
All the terms with $c$ are called digits. The leftmost or leading digit is
called \textit{most significant digit} and the rightmost or trailing digit is
called \textit{least significant digit}. The . is called a point which
separates the integral part which is towards its left from the fractional part
which is towards its right. $b$ is known as radix or base of the number
system. Note that all digits will be between $0$ to $b-1$. So in our decimal
system $b$ is 10 therefore we have digits from 0 to 9. In binary number system
it is 2 therefore digits permitted are 0 and 1.
\subsection{Binary Number System}
\label{bns}
As the name suggests binary number system has base of 2. Therefore it has only
two symbols. 0 and 1. This is the most popular system for computers because TTL
NAND and NOR gates which are the most basic logic gates using which other gates
are implemented in processor has only two voltage output levels because of
their operation in cut-off and saturation zones. These terms are better
understood with the help of a book on electronics which is out of scope of this
book. All binary numbers consist of 0 and 1. So the count is like 0, 1, 10, 11,
100, 101, 110, 111, 1000 and so on.
\subsubsection{Conversion of Unsigned Decimals and Binaries}
Consider a decimal number. Let us say 53 then how would be convert it to
binary. The technique is that of division. Please examine following carefully:
\hspace*{2cm}
\begin{Verbatim}[frame=single]
2 | 53 | 1
----------
2 | 26 | 0
----------
2 | 13 | 1
----------
2 | 6 | 0
----------
2 | 3 | 1
----------
| 1 |
\end{Verbatim}
So the binary is $110101_2$. First we divide 53 by 2 and write the
remainder. Then quotient is 26. We repeat the process for 26 therefore
remainder is 0 and quotient is 13. This we go on repeating till we have 1 as
quotient. Note that all the remainders will be 0 or 1 because divisor is
2. Similarly, final quotient is always 1. Now we take final quotient and start
writing remainders from top to bottom.
To convert binary to decimal let us examine following:
$1*2^5 +1*2^4 +0*2^3 +1*2^2 +0*2^1 +1*2^0 =53_{10}$
The power is to 2 because 2 is the base of source. It starts from 0 for unit's
position and increases to 1 and 2 for ten's and hundred's position and so
on. 1's and 0's are the values of that place. If you note carefully powers of 2
grow like 1, 2, 4, 8, 16, 32, 64, 128 and so on. Any number can be written by
using these powers at most one time. For example consider 100. I know it is
less than 128 so I will use 64. Then 36 remains. So I will use 32 and then
4. This means 100=64+32+4 which means power 6, 5 and 2 have been
used. Therefore, I can quickly write down number as $1100100_2$.
\label{fractional binary numbers}
Fractional numbers are slightly more complicated. Let us consider $1.1_2$ . In
decimal it will be $1+\frac{1}{2}$. This is 1.5 in decimal. Note that when you
convert a fractional part of binary to decimal denominator will always be power
of 2. For that matter when you convert from any base to decimal denominator
will be powers of that base. \textbf{Important:} Therefore, when you convert
from decimal to some base n then denominator of that decimal number can have
only those prime factors which are available in the set of prime factors of
$n$.
Let us say we have a fractional number in decimal .59 then to convert it to
decimal we multiply it with 2 which yields 1.018 which is greater than 1 so our
equivalent binary number is .1. Now we subtract 1 from 1.18 to get .18 which
is less than 1 so we multiply it with 2 again to get .36. Now since this is
less than 1 our equivalent binary number is .10. Repeating the process we get
.72 and .100 then 1.44 and .1001. We put 1 in binary part because decimal part
has become greater than 1. Now again we subtract 1 from decimal part to get .44
and repeat the process.
Operations such as addition, subtraction, multiplication and division are
similar in all number systems.
\subsection{2's Complement and 1's Complement}
2's complement and 1's complement are used to convert binary numbers to decimal
values. In 1's complement the number is obtained by inverting bits i.e. making
0 bit to 1 bit and 1 bit to 0 bit of the binary number in question.
Consider the following table which contains some numbers for 1's complement
of some 8-bit numbers.
The 2's complement of an $N$-bit number is defined as the complement with
respect to $2^N$; i.e. it is the result of subtracting the number
from $2^N$, which in binary is one followed by $N$ zeroes. This is also
equivalent to taking the 1's complement and then adding one, since the sum of
a number and its 1's complement is all 1 bits.
%\begin{table}[!bp]
\begin{center}
\begin{longtable}{|c|r|r|}
\hline
\textbf{Bits}&\textbf{Unsigned Value}&\textbf{1's Complement Value}\\
\hline
0111 1111&127&127\\
\hline
0111 1110&126&126\\
\hline
0000 0010&2&2\\
\hline
0000 0001&1&1\\
\hline
0000 0000&0&0\\
\hline
1111 1111&255&-0\\
\hline
1111 1110&254&-1\\
\hline
1000 0010&130&-125\\
\hline
1000 0001&129&-126\\
\hline
1000 0000&128&-127\\
\hline
\caption{8-bit 1's complement integers}
\end{longtable}
\end{center}
%\end{table}
For signed numbers MSB(most significant bit) decides sign in both 1's
complement as well as 2's complement. 1's complement has two zeroes. Positive
and negative. As you see in table that 1111 1111 is -0 because MSB is 1 so it
is a negative number and then if you invert all remaining bits then it turns
out to be 0. In a 1's complement system negative numbers are represented by the
arithmetic negative of the value. An $N$-bit 1's complement number system can
represent integers in the range $-2^{N-1} - 1$ to $-2^{N-1} - 1$.
Now it is easy to do addition, subtraction, multiplication, division and other
arithmetic operations. Subtraction for 1's complement is a bit
different. Consider the following:
\begin{Verbatim}[frame=single]
0000 0110 6
- 0001 0011 19
=========== ====
1 1111 0011 -12 -An end-around borrow is produced, and the sign bit
of the intermediate result is 1.
- 0000 0001 1 -Subtract the end-around borrow from the result.
=========== ====
1111 0010 -13 -The correct result (6 - 19 = -13)
\end{Verbatim}
Borrows are propagated to the left. If the borrow extends past the end then it
is said to have ``wrapped around'', a condition called an ``end-around
borrow''. When this occurs, the bit must be subtracted from the right-most bit
or least significant bit(LSB). This does not occur in 2's complement arithmetic.
As you see in table and also you can verify the value becomes negative if its
1's complement is computed. However, 2's complement is used on most of
computers because of two zeroes in 1's complement, borrowing being complicated
etc.
Consider following table of 2's complement 3-bit binary numbers:
%\begin{table}[H]
\begin{center}
\begin{longtable}{|c|r|r|}
\hline
\textbf{Bits}&\textbf{Unsigned value}&\textbf{2's complement value}\\
\hline
011&3&3\\
\hline
010&2&2\\
\hline
001&1&1\\
\hline
000&0&0\\
\hline
111&7&-1\\
\hline
110&6&-2\\
\hline
101&5&-3\\
\hline
100&4&-4\\
\hline
\caption{3-bit 2's complement integers}
\end{longtable}
\end{center}
%\end{table}
Clearly, since $N$-bit 1's complement can represent numbers in range
$-2^{N-1}-1$ to $2^{N-1} + 1$ 2's complement of $N$-bit can represent
$-2^{N-1}$ to $2^{N-1} - 1$ as it does not have negative 0 i.e. its range is
more by 1 number.
The 2' complement system has the advantage that operations of addition,
subtraction, and multiplication are same as unsigned binary numbers (as long as
the inputs are represented in the same number of bits and any overflow beyond
those bits is discarded from the result). This property makes the system both
simpler to implement and capable of easily handling higher precision
arithmetic. Also, as mentioned above zero has only a single
representation, avoiding the subtleties associated with negative zero, which
exists in 1's complement systems.
The value $v$ of an $N$-bit integer $b_{N-1} b_{N-2} \dots b_0 $is given by the
following formula:
\begin{equation}
v=-b_{N-1} 2^{N-1} + \sum_{i=0}^{N-2} b_i 2^i
\end{equation}
I will leave it up to you, the reader, to perform basic operations like
addition, subtraction, multiplication, division etc.
\section{Compiling and Executing}
\index{program!compilation}
\index{program!execution}
To compile and execute a program create a new file, edit it and save it. The
extension of file should be \texttt{*.c}. For example,
\texttt{myprogram.c}. After that you can give this command at terminal. Here is
the corrected code.
\begin{minted}[frame=single]{c}
#include <stdio.h>
int main()
{
return 0;
}
\end{minted}
Execute the following command on your command prompt:
\\\\\$gcc nothing.c -o nothing\\\\
Here \texttt{nothing.c} is the name of the file with which it was saved.
Then you will see a file named my program is created by compiler if no errors
were there in your program. In case of errors, like we had in one shown to you
they have to be resolved first. Executable \texttt{nothing} is produced then
you can execute it like
\\\\\$./nothing\\\\
Note that in both the commands \texttt{\$} is not part of command but it is
prompt. For you it may be \texttt{\%} or \texttt{\#} or something fancier
(depends on the imagination of your system administrator). To execute this
command your working directory must be same as the directory your program is
in.
\color{nicered}
\dangersign[3ex] Also, note that on some systems \texttt{TAB} auto completes filename so do
not do the following by accident:
\\\\\$gcc nothing.c -o nothing.c\\\\
\color{black}
This will overwrite your \texttt{nothing.c} by the result of compilation binary
with the same name \texttt{nothing.c}. Let us see how to compile this program
using a Makefile. Edit your \texttt{Makefile} like this:
\begin{minted}[frame=single]{makefile}
#sample Makefile
check-syntax:
gcc -o nul -Wall -S $(CHK_SOURCES)
nothing: nothing.c
gcc -Wall -std=c11 -pedantic nothing.c -o nothing
\end{minted}
Now from do this from menu. \texttt{Tools->compile} As the command issue
\texttt{make -k test}. Another way to do the same using keyboard only is type
\texttt{M-x compile} and repeat \texttt{make -k test} as previous time. Your
code will be compiled. Makefiles are better than executing commands
repeatedly again and again however you must know underlying commands. I will
discuss the compiler options as appropriate. \texttt{-Wall} will enable all the
warnings from \texttt{gcc}, \texttt{-std=c11} enables new features of C11
standard and \texttt{-pedantic} ensures specification conformance.
So let us get started with basics of C.