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

EE3491/EE3490E –

Kỹ thuật lập trình /


Programming Techniques
Chapter 2: Basics of C
and C++
Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính)
Department of Automation Engineering, SEEE
© DIA 2022.2
Content
2.1. C/C++ Program Structure
2.2. Variables and Basis Data Types
2.3. Derived Data Types
2.4. User-defined data type
2.5. Control flow: Decision making
2.6. Control flow: Loop
2.7. Input/Output
2.8. Pre-processor
2.9. Bitwise operation
Chapter 2: Basic of C & C++ © DIA 2022.2 2
2.5 Control flow: decision making
 Making decisions (branching statement)
 if .. else: decision statement to select 1 or 2 cases
 switch .. case: decision statement to select multiple
cases
 break: jumping instruction to end (early) a scope
 continue: skips the current iteration of the loop and
continues with the next iteration
 return: jumping instruction and end (early) a function
 goto: jumping to a label (should not use!)

Chapter 2: Basic of C & C++ © DIA 2022.2 3


2.5.1 if .. else
 Decide on one case: use if  Decide on two case: use if .. else
if(npoints >= 60) if(npoints >= 90)
cout<< "Passed"; cout<< ‘A’;
if( npoints>= 80 && else if ( npoints>= 80)
npoints<= 90) cout<< ‘B’;
{ else if (npoints>= 70)
grade = ‘A’; cout<< ‘C’;
cout<< grade; else if (npoints>= 60)
} cout<< ‘D’;
else cout<< ‘F’;

Chapter 2: Basic of C & C++ © DIA 2022.2 4


Example: max() function
int max1(inta, intb) { int max4(int a, int b) {
int c; if(a > b)
if (a > b)c = a; return a;
else c = b; else
return c; return b;
} }
int max2(int a,int b) { int max5(int a, int b) {
int c = a; if (a > b)
if (a < b) return a;
c = b; return b;
return c; }
} int max6(int a, int b) {
int max3(int a, int b) { return(a > b)? a: b;
if (a < b)
}
a = b;
return a;
}
Chapter 2: Basic of C & C++ © DIA 2022.2 5
2.5.2 switch .. case
Signal input;
int i = 0;
while(i++ < 8) {
input = readInput(i); // read from input module i
switch(input.type) {
case BINARY_8:
cout<< input.value.byte; break;
case BINARY_16:
cout<< input.value.word; break;
case ANALOG_1:
cout<< input.value.real; break;
case ANALOG_2:
cout<< input.value.lreal; break;
default:
cout<< "Unknown signal type";
}
}
Chapter 2: Basic of C & C++ © DIA 2022.2 6
2.6 Control flow: loop
 Loop statements in C/C++:
 while (condition) { }
 do { } while (condition)
 for (init; condtion; post_action) { }
 Loop can be performed with if .. else and goto,
however never do that way
 Loop is usually applied to work with arrays and other
data structure access via array variable and index,
pointer or iterator (may be discussed later)

Chapter 2: Basic of C & C++ © DIA 2022.2 7


2.6.1 while
#include <iostream.h>
void main() {
char input[32];
cout << "\nEnter your full name:";
cin.getline(input,31);
short nLetters=0, nSpaces=0;
short i=0;
while (input[i] != 0) {
if (input[i] == ' ')
++nSpaces;
else
++nLetters;
++i;
}
cout << "\nYour name has " << nLetters << " letters";
cout << "\nYou have " << nSpaces -1 << " middle name";
cin >> i;
}
Chapter 2: Basic of C & C++ © DIA 2022.2 8
while and condition statement
#include <iostream.h>
void main() {
char input[32], family_name[16]={0};
cout << "\nEnter your full name:";
cin.getline(input,31);
short i=0;
while (input[i] != 0) {
if (input[i] !=' ') break;
family_name[i]= input[i];
++i;
}
cout << "\nYour family name is" << family_name;
cin >> i;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 9


2.6.2 do while...
#include <iostream.h>
void main() {
char input[32], family_name[16]={0};
short i; char answer;
do {
cout << "\nEnter your full name:";
cin.getline(input,31);
i=0;
while(input[i] != 0&& input[i] !=' ') {
family_name[i]= input[i];
++i;
}
cout << "\nYour family name is" << family_name;
cout<< "\nDoyou want to continue? (Y/N):“;
cin >> answer;
} while(answer == ‘Y’|| answer == ‘y’)
}

Chapter 2: Basic of C & C++ © DIA 2022.2 10


2.6.3 for
short i =0; for (short i =0;input[i]!=0; ++i)
while(input[i]!= 0) {
{ if (input[i]==' ')
if (input[i]==' ') ++nSpaces;
++nSpaces; else
else ++nLetters;
++nLetters; ++i;
++i; }
}

short i =0; short i =0;


for (;input[i]!=0;) for (;input[i]!=0; ++i)
{ {
if (input[i]==' ') if (input[i]==' ')
++nSpaces; ++nSpaces;
else else
++nLetters; ++nLetters;
++i; }
}
Chapter 2: Basic of C & C++ © DIA 2022.2 11
Range-based for loop
 Added since C++ 11
 Executes a for loop over a range
for ( range_declaration : range_expression)
loop_statement
 E.g.:
int main() int main()
{ {
// Iterating over whole array // Iterating over array
std::vector<int> v = int a[] =
{0, 1, 2, 3, 4, 5}; {0, 1, 2, 3, 4, 5};
for (auto i : v) for (int n : a)
std::cout << i << ' '; std::cout << n << ' ';
} }
Chapter 2: Basic of C & C++ © DIA 2022.2 12
Loop summary
 while and for structure are similar, only one is needed
 do .. while is a bit different but can be used the same as
while or for
 Loop structures can be nested freely, however one
should avoid to nest too many loops to handle the
program, functions can be used instead
 Loop control can be combined with if .. else and break,
return
 Check loop condition carefully (array index, pointer,
…)
Chapter 2: Basic of C & C++ © DIA 2022.2 13
2.7 Input and Output
 The functions printf and scanf provide output and input
respectively
printf(“control string”, list of expressions);
scanf(“control string”, list of &variables);

 Declared in <stdio.h>
 Control string: a character array defines the format of
input/output string
 Expressions: contain data to be presented
 Variables: variables store input data (may be provided by
users)
 & (ampersand): required symbol
Chapter 2: Basic of C & C++ © DIA 2022.2 14
printf()
int printf ( const char * format, ... );
 A format specifier follows this prototype:
%[flags][width][.precision][length]specifier
 Returning value:
 On success, the total number of characters written is returned
 If a writing error occurs, the error indicator (ferror) is set and a
negative number is returned
 If a multibyte character encoding error occurs while writing
wide characters, errno is set to EILSEQ and a negative number
is returned.

Chapter 2: Basic of C & C++ © DIA 2022.2 15


printf()
%[flags][width][.precision][length]specifier
specifier Output Example
d or i Signed decimal integer 392
u Unsigned decimal integer 7235
o Unsigned octal 610
x Unsigned hexadecimal integer 7fa
X Unsigned hexadecimal integer (uppercase) 7FA
f Decimal floating point, lowercase 392.65
F Decimal floating point, uppercase 392.65
e Scientific notation (mantissa/exponent), lowercase 3.9265e+2
E Scientific notation (mantissa/exponent), uppercase 3.9265E+2
g Use the shortest representation: %e or %f 392.65
G Use the shortest representation: %E or %F 392.65
a Hexadecimal floating point, lowercase -0xc.90fep-2
A Hexadecimal floating point, uppercase -0XC.90FEP-2
c Character a
s String of characters sample
p Pointer address b8000000
Nothing printed.
n The corresponding argument must be a pointer to a signed int.
The number of characters written so far is stored in the pointed location.
% A % followed by another % character will write a single % to the stream. %

Chapter 2: Basic of C & C++ © DIA 2022.2 16


printf()
%[flags][width][.precision][length]specifier
flags description
Left-justify within the given field width; Right justification is the default (see width sub-
-
specifier).
Forces to preceed the result with a plus or minus sign (+ or -) even for positive numbers. By
+
default, only negative numbers are preceded with a - sign.
(space) If no sign is going to be written, a blank space is inserted before the value.
Used with o, x or X specifiers the value is preceeded with 0, 0x or 0X respectively for values
different than zero.
#
Used with a, A, e, E, f, F, g or G it forces the written output to contain a decimal point even if
no more digits follow. By default, if no digits follow, no decimal point is written.
Left-pads the number with zeroes (0) instead of spaces when padding is specified
0
(see width sub-specifier).

width description
Minimum number of characters to be printed. If the value to be printed is shorter than this
(number) number, the result is padded with blank spaces. The value is not truncated even if the result is
larger.
The width is not specified in the format string, but as an additional integer value argument
*
Chapter 2: Basic ofpreceding
C & C++ the argument that has to be formatted. © DIA 2022.2 17
printf()
%[flags][width][.precision][length]specifier

.precision description
For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value
to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated
even if the result is longer. A precision of 0 means that no character is written for the value 0.
For a, A, e, E, f and F specifiers: this is the number of digits to be printed after the decimal point (by default, this
.number is 6).
For g and G specifiers: This is the maximum number of significant digits to be printed.
For s: this is the maximum number of characters to be printed. By default all characters are printed until the
ending null character is encountered.
If the period is specified without an explicit value for precision, 0 is assumed.
The precision is not specified in the format string, but as an additional integer value argument preceding the
.*
argument that has to be formatted.

Chapter 2: Basic of C & C++ © DIA 2022.2 18


printf()
%[flags][width][.precision][length]specifier
 The length sub-specifier modifies the length of the data type. This is a chart
showing the types used to interpret the corresponding arguments with and
without length specifier (if a different type is used, the proper type promotion
or conversion is performed, if allowed):
specifiers
length di uoxX fFeEgGaA c s p n
(none) int unsigned int double int char* void* int*
hh signed char unsigned char signed char*
unsigned
h short int short int*
short int
unsigned long
l long int wint_t wchar_t* long int*
int
unsigned long
ll long long int long long int*
long int
j intmax_t uintmax_t intmax_t*
z size_t size_t size_t*
t ptrdiff_t ptrdiff_t ptrdiff_t*
L long double
Chapter 2: Basic of C & C++ © DIA 2022.2 19
Examples
%10.2f ____123.55 double
%10.4f __123.5500
%.2f 123.55
%10d _______475 int
%-10d 475_______
%10c _________a char

Chapter 2: Basic of C & C++ © DIA 2022.2 20


Examples
/* printf example */
#include <stdio.h>

int main()
{
printf ("Characters: %c %c \n", 'a', 65);
printf ("Decimals: %d %ld\n", 1977, 650000L);
printf ("Preceding with blanks: %10d \n", 1977);
printf ("Preceding with zeros: %010d \n", 1977);
printf ("Some different radices: %d %x %o %#x %#o \n",
100, 100, 100, 100, 100);
printf ("floats: %4.2f %+.0e %E \n", 3.1416, 3.1416, 3.1416);
printf ("Width trick: %*d \n", 5, 10);
printf ("%s \n", "A string");
return 0;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 21


scanf()
scanf(“control string”, &input list);

int numPushups;

printf(“Hello. Do how many pushups? ”);


scanf(“%d”, &numPushups);
printf(“Do %d pushups.\n”, numPushups);

output: Hello. Do how many pushups? 5


Do 5 pushups.
 Variables in the input list must come with the & sign as a prefix

Chapter 2: Basic of C & C++ © DIA 2022.2 22


If you miss &
 The program is compiled successfully but…

Chapter 2: Basic of C & C++ © DIA 2022.2 23


scanf()
int scanf ( const char * format, ... );
 A format specifier for scanf follows this prototype:
%[*][width][length]specifier
 Returning value:
 On success, the function returns the number of items of the
argument list successfully filled
 If a reading error happens or the end-of-file is reached while
reading, the proper indicator is set (feof or ferror). And, if
either happens before any data could be successfully read, EOF
is returned.
 If an encoding error happens interpreting wide characters, the
function sets errno to EILSEQ.

Chapter 2: Basic of C & C++ © DIA 2022.2 24


scanf()
%[*][width][length]specifier
specifier Description Characters extracted
Any number of digits, optionally preceded by a sign (+ or -).
i Integer Decimal digits assumed by default (0-9), but a 0 prefix introduces octal digits (0-7), and 0x hexadecimal digits (0-f).
Signed argument.
Decimal Any number of decimal digits (0-9), optionally preceded by a sign (+ or -).
d or u
integer d is for a signed argument, and u for an unsigned.
Any number of octal digits (0-7), optionally preceded by a sign (+ or -).
o Octal integer
Unsigned argument.
Any number of hexadecimal digits (0-9, a-f, A-F), optionally preceded by 0x or 0X, and all optionally preceded by a sign
Hexadecimal
x (+ or -).
integer
Unsigned argument.
f, e, g A series of decimal digits, optionally containing a decimal point, optionally preceeded by a sign (+ or -) and optionally
Floating point
followed by the e or E character and a decimal integer (or some of the other sequences supported by strtod).
a number
Implementations complying with C99 also support hexadecimal floating-point format when preceded by 0x or 0X.
The next character. If a width other than 1 is specified, the function reads exactly width characters and stores them in the
c Character
successive locations of the array passed as argument. No null character is appended at the end.
String of Any number of non-whitespace characters, stopping at the first whitespace character found. A terminating null character
s
characters is automatically added at the end of the stored sequence.
Pointer A sequence of characters representing a pointer. The particular format used depends on the system and library
p
address implementation, but it is the same as the one used to format %p in fprintf.
Any number of the characters specified between the brackets.
[characters] Scanset
A dash (-) that is not the first character may produce non-portable behavior in some library implementations.
Negated
[^characters] Any number of characters none of them specified as characters between the brackets.
scanset
No input is consumed.
n Count
The number of characters read so far from stdin is stored in the pointed location.
% % A % followed by another % matches a single %.
Chapter 2: Basic of C & C++ © DIA 2022.2 25
scanf()
%[*][width][length]specifier

 The format specifier can also contain sub-


specifiers: asterisk (*), width and length (in that order),
which are optional and follow these specifications:
sub-specifier description
An optional starting asterisk indicates that the data is to be read from the
* stream but ignored (i.e. it is not stored in the location pointed by an
argument).
Specifies the maximum number of characters to be read in the current
width
reading operation (optional).
One of hh, h, l, ll, j, z, t, L (optional).
length This alters the expected type of the storage pointed by the corresponding
argument (see below).

Chapter 2: Basic of C & C++ © DIA 2022.2 26


scanf()
%[*][width][length]specifier

specifiers

length di uox fega c s [] [^] p n


(none) int* unsigned int* float* char* void** int*

hh signed char* unsigned char* signed char*


unsigned short
h short int* short int*
int*
unsigned long
l long int* double* wchar_t* long int*
int*
unsigned long
ll long long int* long long int*
long int*
j intmax_t* uintmax_t* intmax_t*
z size_t* size_t* size_t*
t ptrdiff_t* ptrdiff_t* ptrdiff_t*
L long double*

Chapter 2: Basic of C & C++ © DIA 2022.2 27


Common errors with Input/Ouput
 Assume that the following statement is used
scanf("%lf", &fahrenheit);
 The string “comfortable” is entered as an input
 This input is not read by the program, and thus fahrenheit is
not initialized
 A number of errors will occur as results of the above issue
 This is a mistake of the programmer, not the user

Chapter 2: Basic of C & C++ © DIA 2022.2 28


Consequence

Chapter 2: Basic of C & C++ © DIA 2022.2 29


What to do?
 Function scanf() return the input variable which has
been read successfully

int scanfCount;
scanfCount = scanf(“%d”, &studentID);
/* if scanfCount is not equal to 1 at this point,
the user has made some kind of mistake.
Handle it. */

Chapter 2: Basic of C & C++ © DIA 2022.2 30


Example
/* scanf example */
#include <stdio.h>

int main ()
{
char str [80];
int i;

printf ("Enter your family name: ");


scanf ("%79s",str);
printf ("Enter your age: ");
scanf ("%d",&i);
printf ("Mr. %s , %d years old.\n",str,i);
printf ("Enter a hexadecimal number: ");
scanf ("%x",&i);
printf ("You have entered %#x (%d).\n",i,i);

return 0;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 31


Pause at a Breakpoint

Chapter 2: Basic of C & C++ © DIA 2022.2 32


assert()

It’s a must!

Chapter 2: Basic of C & C++ © DIA 2022.2 33


Input/Output summary
printf(“control string”, output list);
 control string : data type and desired format
 output list : operations, values to be written (on the screen)
scanf(“control string”, &input list);
 control string: variables, values to be read
 input list: data type and desired format
 Can be used to initialized variables
 Attention:
 do not use & with printf(),
 must use & with scanf()
 In these two statements: conversion specification in the
control string must be compatible with input/output stream
in terms of quantity, order and data type

Chapter 2: Basic of C & C++ © DIA 2022.2 34


Input/Output in C++
 C++ uses a convenient abstraction called streams to
perform input and output operations in sequential media
such as the screen, the keyboard or a file.
 A stream is an entity where a program can either insert
or extract characters to/from.
 The basis stream:
 cin standard input stream
 cout standard output stream
 cerr standard error (output) stream
 clog standard logging (output) stream
 Hearder file required: iostream
Chapter 2: Basic of C & C++ © DIA 2022.2 35
Standard output: cout
 Output Stream: If the direction of flow of bytes is
from main memory to device( display screen ) then this
process is called output. The C++ cout statement is
the instance of the ostream class.
 cout is used together with the insertion operator <<
 The << operator inserts the data that follows it into the
stream that precedes it.
cout << “Hello world”; // prints the string Hello world
cout << x // print the value of variable x
int age = 21;
cout << “I am” << age << “ years old”;
// prints I am 21 years old
Chapter 2: Basic of C & C++ © DIA 2022.2 36
Standard output: cin
 Input Stream: If the direction of flow of bytes is from
the device(for example, Keyboard) to the main memory
then this process is called input. C++ cin statement is
the instance of the class istream.
 cin is used together with the extraction operator >>
 The >> operator is followed by the variable where the
extracted data is stored.
int age = 21;
cin >> age;

Chapter 2: Basic of C & C++ © DIA 2022.2 37


Formatting I/O in C++
 A few standard ios class functions are
 width(): The width method is used to set the required field
width. The output will be displayed in the given width
 precision(): The precision method is used to set the number of
the decimal point to a float value
 fill(): The fill method is used to set a character to fill in the
blank space of a field
 setf(): The setf method is used to set various flags for
formatting output
 unsetf(): The unsetf method is used To remove the flag setting

Chapter 2: Basic of C & C++ © DIA 2022.2 38


Formatting I/O in C++
 Examples:
cout.precision(8);
cout << 1234.56789 << ' ' << 1234.56789 << ' ' << 123456 << '\n';
cout.precision(4);
cout << 1234.56789 << ' ' << 1234.56789 << ' ' << 123456 << '\n';
// This produces:
// 1234.5679 1234.5679 123456
// 1235 1235 123456
cout.width(4);
cout.fill('#');
cout << "ab"; // print ##ab

Chapter 2: Basic of C & C++ © DIA 2022.2 39


Other Input/Output standard
libraries
 iostream: iostream stands for standard input-output stream. This
header file contains definitions of objects like cin, cout, cerr, etc.
 iomanip: iomanip stands for input-output manipulators. The
methods declared in these files are used for manipulating
streams. This file contains definitions of setw, setprecision, etc.
 fstream: This header file mainly describes the file stream. This
header file is used to handle the data being read from a file as
input or data being written into the file as output.
 sstream: This header file defines a type called stringstream
that allows a string to be treated as a stream, and thus allowing
extraction or insertion operations from/to strings in the same way
as they are performed on cin and cout.

Chapter 2: Basic of C & C++ © DIA 2022.2 40


2.8. Preprocessor
 Preprocessor statements appear before the program is
compiled
 It is not a part of the compiler, but is a separate step in the
compilation process
 Tasks to do:
 Combine other files into the file being compiled
 Define constant, macro
 Compile the program with conditions
 Implement precompile statements with conditions
 Precompile statements start with # (hash)
 Only space characters can be put in front of pre-processor statements
in that line

Chapter 2: Basic of C & C++ © DIA 2022.2 41


Preprocessor
 A preprocessor is effective within the file where it is
defined
 A preprocessor is not the basic syntax of C
 However, its utilization may change the program
structure
 All preprocessor commands begin with a hash symbol
(#)
 Two most frequently used features are:
 #include
 #define
Chapter 2: Basic of C & C++ © DIA 2022.2 42
2.8.1 File Inclusion: #include
 #include is usually used with header files, e.g.:
#include <standard.h> searching follows an
implementation-defined rule to find the file
#include “myheader.h” searching for the file typically
begins where the source program was found

 These source lines are replaced by the content of the


file, i.e. standard.h or myheader.h

Chapter 2: Basic of C & C++ © DIA 2022.2 43


2.8.2 Macro Substitution
 Keyword #define can be used to define
 Constants
 Macros

Chapter 2: Basic of C & C++ © DIA 2022.2 44


Constant definition
 It is used to avoid “magic numbers \ hard code” in the
program
 Common form
#define name text
 It calls for a macro substitution of the simplest kind -
subsequent occurrences of the token name will be
replaced by the text before the program is compiled
 The name in a #define has the same form as a variable
name; the replacement text is arbitrary

Trang
Chapter 2: Basic of C & C++ © DIA 2022.2
45
Constant definition
#define BUFFERSIZE 256
#define MIN_VALUE -32
#define PI 3.14159
 Attention:
 There are neither = nor ; in the line
 Name defined by #define can be removed by using #undef
(it may be redefined later)
 Substitutions are made only for tokens, and do not take place
within quoted strings, e.g. there is no substitution for PI in
printf("PI")
 UPPERCASE WORD is used as the constant name in
order to differentiate with variable and function names
Chapter 2: Basic of C & C++ © DIA 2022.2 46
#define, const and enum
 It is possible to replace #define with constant
or enum
#define ARRAYSIZE 10
const int ArraySize = 10;
double array[ARRAYSIZE]; /* Valid. */

#define PI 3.14159
#define ARRAYSIZE 10
const double Pi = 3.14159; /* Preferred */
enum {ARRAYSIZE = 10}; /* Preferred */

Chapter 2: Basic of C & C++ © DIA 2022.2 47


Macro definition
 #define is usually used to create macros
#define max(x,y) ((x)>(y) ? (x) : (y))
 Macro looks like a function call, however it is not really
a function. Macro name (max) is replaced by statement
with respect to operands before the program is
compiled
int a = 4, b = -7, c;
c = MAX(a,b);
is replaced by:
c = ((a)>(b) ? (a) : (b));

Chapter 2: Basic of C & C++ © DIA 2022.2 48


Why to used Macro
 Speed
 Implementation as a function, the code is copied to the program
before being compiled
 It is not really effective with program running on PC
 Common code
 Macro enable to work with all kinds of data type (int,
double…)
int max(int x, int y) {
return x > y ? x : y;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 49


Macro examples
#define SQR(x) ((x)*(x))
#define SGN(x) (((x)<0) ? -1 : 1)
#define ABS(x) (((x)<0) ? -(x) : (x))
#define ISDIGIT(x) ((x) >= '0' && (x) <= '9‘)
#define NELEMS(array)
sizeof(array)/sizeof(array[0]))

#define CLAMP(val,low,high) \
((val)<(low) ? (low) : (val) > (high) ? (high) :
(val))

#define ROUND(val) \
((val)>0 ? (int)((val)+0.5) : -(int)(0.5-(val)))

Chapter 2: Basic of C & C++ © DIA 2022.2 50


Disadvantages of Macro
 Be careful with some pitfalls when using macro.
 Inappropriate usage of parentheses
 Side effect of ++, -- operator
 No data type verification

Chapter 2: Basic of C & C++ © DIA 2022.2 51


Macro pitfalls
#define SQR(x) x * x
 Example:
int a = 7;
b = SQR(a+1);
will be replaced by
b = a+1 * a+1;
 Solution: use parentheses to avoid the confusion

Chapter 2: Basic of C & C++ © DIA 2022.2 52


Macro pitfalls
 Example
b = ABS(a++);
would become
b = (((a++)<0) ? -(a++) : (a++));
 Solution: do not use these operators in the macro

Chapter 2: Basic of C & C++ © DIA 2022.2 53


Macro pitfalls
 Inconsistent use of data type would result in wrong
calculation
int a = 7, b;
double c = 5.3, d;
d = SQR(a);
b = SQR(c);

Chapter 2: Basic of C & C++ © DIA 2022.2 54


Long Macro statement
 If the macro line is too long, it should be broken into
multiple line by using \
#define ERROR(condition, message) \
if (condition) printf(message)

Chapter 2: Basic of C & C++ © DIA 2022.2 55


Example
#define TIMELOOP(CODE) { \
t0 = clock(); \
for (i = 0; i < n; ++i) { CODE; } \
printf("%7d ", clock() - t0); \
}
 Its usage would be:
TIMELOOP(y = sin(x));

Chapter 2: Basic of C & C++ © DIA 2022.2 56


Constant character array in Macro
 If the operand of macro has # in front, it will be
replaced by a constant character array
#define PRINT_DEBUG(expr) \
printf(#expr " = %g\n", expr)
Example:
PRINT_DEBUG(x/y);
printf("x/y" " = %g\n", x/y);

Chapter 2: Basic of C & C++ © DIA 2022.2 57


Pre-defined Macros
 Pre-defined macros in compiler

__LINE__ contains the current line number of the


program in the compilation. It gives the line
number where it is called.
__FILE__ holds the file name of the currently executing
program in the computer

__DATE__ gives the date at which source code of this


program is converted into object code

__TIME__ gives the time at which program was compiled


__STDC__ is used to confirm the compiler standard
Chapter 2: Basic of C & C++ © DIA 2022.2 58
Example
#define PRINT_DEBUG(expr, type) \
printf(__FILE__ "[%d](" #expr "): \
%" type##Conv "\n", __LINE__,
(expr))
 The following codes
#define intConv “d”
#define doubleConv “f”
PRINT_DEBUG(x/y, int);
print out the filename, line numbers in order, and results
Chapter 2: Basic of C & C++ © DIA 2022.2 59
2.8.3 Conditional inclusion
 Conditional preprocessor statements in C
#if, #elif, #else, #endif
#ifdef, #ifndef
 Goals
 To add debugging codes in the program
 To add the code which is not standard
 To avoid insert header files multiple times

Chapter 2: Basic of C & C++ © DIA 2022.2 60


Debugging
 Compile the program in debug mode
#define DEBUG
 Debugging code can be inserted
#ifdef DEBUG
printf("Pointer %#x points
to value %f", pd, *pd);
#endif

Chapter 2: Basic of C & C++ © DIA 2022.2 61


Non-standard code
 Applied in the case that codes are used for different
microprocessors
#ifdef __WIN32__
return WaitForSingleObject(Handle,0)==

WAIT_OBJECT_0;
#elif defined(__QNX__)||defined(__linux__)
if(flock(fd,LOCK_EX|LOCK_NB) == -1)
return 0;
else
return 1;
#endif
Chapter 2: Basic of C & C++ © DIA 2022.2 62
Non-standard code
 Applied in the case that codes are used for different microprocessors
#if defined(ARDUINO) && ((ARDUINO) >= 100)
//arduino core v1.0 or later
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#if defined(__AVR__)
#include <avr/pgmspace.h>
//use for PROGMEM Arduino AVR
#elif defined(ESP8266)
#include <pgmspace.h>
//use for PROGMEM Arduino ESP8266
#elif defined(_VARIANT_ARDUINO_STM32_)
#include <avr/pgmspace.h>
//use for PROGMEM Arduino STM32
#endif

Chapter 2: Basic of C & C++ © DIA 2022.2 63


One time inclusion of header files
 A header file should be included only once (although a
few file may use it)
 Duplicated inclusion will result in repeated definition of
variables, functions, labels, and thus the program
cannot be compiled successfully
 Solution: using “header guards”
#ifndef A_HEADER_H_
#define A_HEADER_H_

/* Contents of header file is here. */


#endif
Chapter 2: Basic of C & C++ © DIA 2022.2 64
Header guard example: htu21d.h
#ifndef HTU21D_h
#define HTU21D_h

#define HTU21D_ADDRESS 0x40 //chip i2c address
#define HTU21D_USER_REGISTER_WRITE 0xE6 //write user register
#define HTU21D_USER_REGISTER_READ 0xE7 //read user register

class HTU21D{
public:
HTU21D(HTU21D_RESOLUTION = HTU21D_RES_RH12_TEMP14);
#if defined(ESP8266)
bool begin(uint8_t sda = SDA, uint8_t scl = SCL);
#else
bool begin(void);
#endif
float readHumidity(HTU21D_HUMD_OPERATION_MODE =\\
HTU21D_TRIGGER_HUMD_MEASURE_HOLD);
float readTemperature(HTU21D_TEMP_OPERATION_MODE =\\
HTU21D_TRIGGER_TEMP_MEASURE_HOLD);
… };
#endif
Chapter 2: Basic of C & C++ © DIA 2022.2 65
2.9. Bitwise operation
 C provides operators
 To change each bit individually
 To perform operations which are usually available in
Assembler only
 The C program with bitwise operation can run in
different OS, however most of these kind of programs
are written to work in specific hardware

Chapter 2: Basic of C & C++ © DIA 2022.2 66


Negative numbers
 Bit MSB (most significant bit) is 1, the number is
negative
 Two’s complement to represent negative number, e.g.:
-22425 as a binary number: 1010 1000 0110 0111
 The algorithm:
 Subtract 1 from the original number 22425, we get 22424
 Convert to binary
0101 0111 1001 1000
 Perform 1’s complement by inverting each bit
1010 1000 0110 0111 = -22425

Chapter 2: Basic of C & C++ © DIA 2022.2 67


Bitwise operators
 6 bitwise operators in C:
& | ^ ~ << >>
 These operators are applicable with the data types:
char, short, int, long.
 They can be used for floating point arithmetic
 5 bit assignment operators
&= |= ^= <<= >>=
 Bit assignment operators are similar to arithmetic
assignment operators
z &= x | y;
z = z & (x | y);

Chapter 2: Basic of C & C++ © DIA 2022.2 68


Bitwise operators
 Attention: developers should not confuse bitwise
operators with logical operators
& | ~ << >>

&& || ! < >

Chapter 2: Basic of C & C++ © DIA 2022.2 69


AND &
 Perform AND bit-by-bit operation of two integers
 E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 & b2;
b1 00011001 25
b2 01001101 & 77
b3 00001001 9
 It is used to
 Reset bit
 Select a bit to verify

Chapter 2: Basic of C & C++ © DIA 2022.2 70


OR |
 Perform OR bit-by-bit operation of two integers
 E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 | b2;
b1 00011001 25
b2 01101010 | 106
b3 01111011 123
 It is used to
 Set a bit

Chapter 2: Basic of C & C++ © DIA 2022.2 71


XOR ^
 Perform XOR bit-by-bit operation of two integers
 E.g.: b1, b2, b3 are unsigned char numbers
b3 = b1 ^ b2;
b1 00011001 25
b2 01001101 ^ 77
b3 01010100 84
 It is used to
 Set a bit

Chapter 2: Basic of C & C++ © DIA 2022.2 72


NOT ~
 Perform NOT (1’s complement) operation of an integer
 E.g.: b1, b2 are unsigned char numbers
b2 = ~b1;
b1 00011001 25
b2 11100110 230
 It is used to
 Invert status of a bit or a group of bits

Chapter 2: Basic of C & C++ © DIA 2022.2 73


Left shift <<
 Perform left shift operation of an integer by a number
of bits specified by the right operand
 E.g.: b1, b2 are unsigned char numbers
b2 = b1 << 2;
b1 00011010 26
b2 01101000 104
 Attention:
 MSB disappears, inserted bit at LSB is always 0
 The operator is equivalent to multiplying the number with 2^n:
b2 = b1*4

Chapter 2: Basic of C & C++ © DIA 2022.2 74


Right shift >>
 A bit more complex: shift the bits of an integer to the
right by a number specified by the right operand
 LSB disappears, inserted bit at MSB is
 0 if the number is unsigned
 1 (arithmetical right shift) hoặc 0 (logical right shift)
signed char x = -75; /* 1011 0101 */
signed char y = x>>2; /* 0010 1101 (logical) */
/* 1110 1101 (arithmetic) */
 The result depends on the computer and the OS.
 It is 45 with logical right shift and -19 with arithmetical right
shift in the above example.
 In fact, right shift is usually applied for unsigned numbers and
it is equivalent to dividing the number by 2^n
Chapter 2: Basic of C & C++ © DIA 2022.2 75
2 raised to the n-th power
 Bit shift operators are often used in exchange of
multiplication
 They are faster than multiply operator
x * 2 x << 1
x / 16 x >> 4
x % 8 x & 7
 However, using bit shift operators make the code more
difficult to read

Chapter 2: Basic of C & C++ © DIA 2022.2 76


Warning
 If bit shift operator is perform by a number larger than
size of (sizeof) the left operand, the result may be
unspecified

Chapter 2: Basic of C & C++ © DIA 2022.2 77


Bitwise operators precedence
 Precedence of bitwise operators in C:
 NOT ~
 AND &
 XOR ^
 OR |
 However, () should be used in all cases

Chapter 2: Basic of C & C++ © DIA 2022.2 78


Checksum 8 bit
#include <reg51.h> #include <reg51.h>
void main(void) { void main(void) {
unsigned char mydata[] unsigned char mydata[]
={0x25,0x62,0x3F,0x52}; ={0x25,0x62,0x3F,0x52,0xE8};
unsigned char sum=0, x unsigned char shksum=0;
unsigned char chksumbyte; unsigned char x;
for (x=0;x<4;x++) { for (x=0;x<5;x++)
P2=mydata[x]; chksum=chksum+mydata[x];
sum=sum+mydata[x]; if (chksum==0)
P1=sum; P0=‘Good’;
} else
chksumbyte=~sum+1; P0=‘Bad’;
P1=chksumbyte; }
}

Chapter 2: Basic of C & C++ © DIA 2022.2 79


Checksum 8 bit
#include <reg51.h>  Summation:
void main(void) {
unsigned char mydata[]
25H+ 62H+ 3FH+ 52H = 118H
={0x25,0x62,0x3F,0x52};  Two complements of 118H
unsigned char sum=0, x
unsigned char chksumbyte;
is E8H
for (x=0;x<4;x++) {
P2=mydata[x];
sum=sum+mydata[x];
P1=sum;
}
chksumbyte=~sum+1;
P1=chksumbyte;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 80


Checksum 8 bit
 Summation: #include <reg51.h>
void main(void) {
25H+ 62H+ 3FH+ 52H = 118H unsigned char mydata[]
 Two complements of 118H is ={0x25,0x62,0x3F,0x52,0xE8};
E8H unsigned char shksum=0;
unsigned char x;
 Verify the check sum: for (x=0;x<5;x++)
25H+ 62H+ 3FH+ 52H + E8H = 0 chksum=chksum+mydata[x];
if (chksum==0)
P0=‘Good’;
else
P0=‘Bad’;
}

Chapter 2: Basic of C & C++ © DIA 2022.2 81


Bit masking
 Bit operators are used for 2 main purposes:
 Save memory by storing status flags in one byte
 Interface with hardware register
 In these 2 cases, it is required the capability of
modifying each bit and check each bit status.
 C enables to create macro, which can set, reset (clear)
bit or reverse bit status, named masking

Chapter 2: Basic of C & C++ © DIA 2022.2 82


Bit masking
 Step 1: Create one integer which represents the status of
each bit or a group of bits
 E.g.:
enum {
FIRST = 0x01, /* 0001 binary */
SECND = 0x02, /* 0010 binary */
THIRD = 0x04, /* 0100 binary */
FORTH = 0x08, /* 1000 binary */
ALL = 0x0f /* 1111 binary */
};

Chapter 2: Basic of C & C++ © DIA 2022.2 83


Bit masking
 In another way:
enum {
FIRST = 1 << 0,
SECND = 1 << 1,
THIRD = 1 << 2,
FORTH = 1 << 3,
ALL = ~(~0 << 4)
};
 The last line is used to set/reset a group of bit
1111 1111 /* ~0 */
1111 0000 /* ~0 << 4 */
0000 1111 /* ~(~0 << 4) */
Chapter 2: Basic of C & C++ © DIA 2022.2 84
Operations with Bit masking
unsigned flags = 0;
flags |= SECND | THIRD | FORTH; /* (1110). */
flags &= ~(FIRST | THIRD); /* (1010). */
flags ^= (THIRD | FORTH); /* (1100). */
if ((flags & (FIRST | FORTH)) == 0)
flags &= ~ALL; /* (0000). */
 Operator | (can be called a pipe ) is used to obtain a combination of bit masks
 Operator ~ is used to reverse all the bits (all bits are 1 except the ones with
masks)
 Operator |= is used to set bits
 Operator &= is used to reset bits
 Operator ^= is used to flip bits
 Operator & is used to select bits (for checking status).

Chapter 2: Basic of C & C++ © DIA 2022.2 85


Macro for each bit
#define BitSet(arg,posn) ((arg) | (1L << (posn)))
#define BitClr(arg,posn) ((arg) & ~(1L << (posn)))
#define BitFlp(arg,posn) ((arg) ^ (1L << (posn)))
#define BitTst(arg,posn) ((arg) & (1L << (posn)))

enum {FIRST, SECND, THIRD};


unsigned flags = 0;

flags = BitSet(flags, FIRST); /* Set first bit. */


flags = BitFlp(flags, THIRD); /* Toggle third bit. */
if (BitTst(flags, SECND) == 0)/* Test second bit. */
flags = 0;

Chapter 2: Basic of C & C++ © DIA 2022.2 86


Example
 Implement an operation to swap 2 variables using XOR
 #define SWAP(a,b) {a^=b; b^=a; a^=b;}

Chapter 2: Basic of C & C++ © DIA 2022.2 87


Union vs Struct revision

Chapter 2: Basic of C & C++ © DIA 2022.2 88


Bit Field

Assuming that we have a 32bit register with the above parameters

Chapter 2: Basic of C & C++ © DIA 2022.2 89


Bit Field Example 1

Chapter 2: Basic of C & C++ © DIA 2022.2 90


Working with Union

Chapter 2: Basic of C & C++ © DIA 2022.2 91


Examples with Union

Chapter 2: Basic of C & C++ © DIA 2022.2 92


Bit Field Example 2

Chapter 2: Basic of C & C++ © DIA 2022.2 93


Float to IEEE 32bit conversion
(or mantisa)

 E.g.:

Chapter 2: Basic of C & C++ © DIA 2022.2 94


Float to IEEE 32bit conversion

Chapter 2: Basic of C & C++ © DIA 2022.2 95


Convert float to hex and hex to float

Chapter 2: Basic of C & C++ © DIA 2022.2 96


Further exploration
 What is double precision floating format?
 The conversion formula

Chapter 2: Basic of C & C++ © DIA 2022.2 97


End of Chapter 2

Chapter 2: Basic of C & C++ © DIA 2022.2 98

You might also like