0% found this document useful (0 votes)
18 views

Chapter2_Basics of C and C++_part2

Uploaded by

dang8805
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
18 views

Chapter2_Basics of C and C++_part2

Uploaded by

dang8805
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 104

EE3491 - Kỹ thuật lập trình

EE3490E – Programming Techniques


Chapter 2: Basics of C and C++

Lecturer: Dr. Hoang Duc Chinh (Hoàng Đức Chính)


Department of Automation Engineering
School of Electrical and Electronic Engineering
Email: [email protected]

© HĐC 2024.1
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: Selection
2.6. Control flow: Loop
2.7. Input/Output
2.8. Pre-processor
2.9. Bitwise operation

© HĐC 2024.1 Chapter 2: Basic of C & C++ 2


2.5 Control flow

statement1

statement2 true condition false

. condition true statement


. statement1 statement2
.
false
statementN

a. Sequence b. Selection c. Loop

© HĐC 2024.1 Chapter 2: Basic of C & C++ 3


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!)

© HĐC 2024.1 Chapter 2: Basic of C & C++ 4


2.5.1 if .. else

 Decide on one case: use if  Decide on two case: use if ..


if(npoints >= 60) else
cout<< "Passed"; if(npoints >= 90)
if( npoints>= 80 && cout<< ‘A’;
npoints<= 90)
else if ( npoints>= 80)
{
cout<< ‘B’;
grade = ‘A’; else if (npoints>= 70)
cout<< grade; cout<< ‘C’;
} else if (npoints>= 60)
cout<< ‘D’;
else cout<< ‘F’;
condition true statement

false false
statement2 condition true statement1

© HĐC 2024.1 Chapter 2: Basic of C & C++ 5


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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 6


2.5.2 switch .. case
switch (expression)
{
case value1: expression
statements1
true
break; case value1 statement1 break
case value2: false
statements2 true
case value2 statement2 break
break;
false
. .
. .
. .
case valuen: false
true
statementsn case valueN statementn break
break; false
default: default statements break
statements
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 7


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";
}
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 8


2.6 Control flow: loop

Loop statements in C/C++:


 while (condition) { }
 do { } while (condition)
 for (init; condtion; post_action) { }

initial
statement statement

true update
condition
condition true statement statement
false true
false condition statement
false

© HĐC 2024.1 Chapter 2: Basic of C & C++ 9


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)

© HĐC 2024.1 Chapter 2: Basic of C & C++ 10


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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 11


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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 12


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’)
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 13


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;
}

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; }
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 14


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 << ' ';
} }

© HĐC 2024.1 Chapter 2: Basic of C & C++ 15


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, …)

© HĐC 2024.1 Chapter 2: Basic of C & C++ 16


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 17


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.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 18


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. %

© HĐC 2024.1 Chapter 2: Basic of C & C++ 19


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
*
preceding the argument that has to be formatted.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 20


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.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 21


printf()

 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):
%[flags][width][.precision][length]specifier
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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 22


Examples

%10.2f ____123.55 double


%10.4f __123.5500
%.2f 123.55
%10d _______475 int
%-10d 475_______
%10c _________a char

© HĐC 2024.1 Chapter 2: Basic of C & C++ 23


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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 24


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 25


If you miss &

The program is compiled successfully but…

© HĐC 2024.1 Chapter 2: Basic of C & C++ 26


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.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 27


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 %.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 28


scanf()

The format specifier can also contain sub-


specifiers: asterisk (*), width and length (in that order),
which are optional and follow these specifications:
%[*][width][length]specifier

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).

© HĐC 2024.1 Chapter 2: Basic of C & C++ 29


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*

© HĐC 2024.1 Chapter 2: Basic of C & C++ 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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 31


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 32


Consequence

© HĐC 2024.1 Chapter 2: Basic of C & C++ 33


What to do?

scanf returns an integer that


 Let the user know input value is entered successfully
 Be used to verify if all the inputs have been entered; if any
input is missing, it should request to continue entering or issue
an error

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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 34


Pause at a Breakpoint

© HĐC 2024.1 Chapter 2: Basic of C & C++ 35


assert()

It’s a must!

© HĐC 2024.1 Chapter 2: Basic of C & C++ 36


Robust approach
int score;
input buffer
scanf(“%d”, &score);
while (score != 0) {
printf(“%d \n”, score); A…
scanf(“%d”, &score);
}

/*Robustly read an integer, consuming nondigits*/


int read_int (void) {
int status, input;
char junk;
status = scanf(“%d”, &input);
while (status < 1) { /* unsuccessful read */
scanf(“%c”, &junk); /* consume 1 char */
status = scanf(“%d”, &input); /*try again*/
}
return (input);
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 37


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 38


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 39


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 40


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;

© HĐC 2024.1 Chapter 2: Basic of C & C++ 41


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 42


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 43


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.

© HĐC 2024.1 Chapter 2: Basic of C & C++ 44


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 45


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 46


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 47


2.8.2 Macro Substitution

Keyword #define can be used to define


 Constants
 Macros

© HĐC 2024.1 Chapter 2: Basic of C & C++ 48


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ Trang 49


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 50


#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 */

© HĐC 2024.1 Chapter 2: Basic of C & C++ 51


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));

© HĐC 2024.1 Chapter 2: Basic of C & C++ 52


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;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 53


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)))

© HĐC 2024.1 Chapter 2: Basic of C & C++ 54


Disadvantages of Macro

Be careful with some pitfalls when using macro.


 Inappropriate usage of parentheses
 Side effect of ++, -- operator
 No data type verification

© HĐC 2024.1 Chapter 2: Basic of C & C++ 55


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 56


Macro pitfalls

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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 57


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);

© HĐC 2024.1 Chapter 2: Basic of C & C++ 58


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)

© HĐC 2024.1 Chapter 2: Basic of C & C++ 59


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));

© HĐC 2024.1 Chapter 2: Basic of C & C++ 60


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);

© HĐC 2024.1 Chapter 2: Basic of C & C++ 61


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 62


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 63


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 64


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 65


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 66


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 67


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 68


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 69


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 70


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 71


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);

© HĐC 2024.1 Chapter 2: Basic of C & C++ 72


Bitwise operators

Attention: developers should not confuse bitwise


operators with logical operators
& | ~ << >>

&& || ! < >

© HĐC 2024.1 Chapter 2: Basic of C & C++ 73


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 74


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 75


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 76


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 77


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 78


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 79


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 80


Warning

If bit shift operator is perform by a number larger than


size of (sizeof) the left operand, the result may be
unspecified

© HĐC 2024.1 Chapter 2: Basic of C & C++ 81


Bitwise operators precedence

Precedence of bitwise operators in C:


 NOT ~
 AND &
 XOR ^
 OR |
However, () should be used in all cases

© HĐC 2024.1 Chapter 2: Basic of C & C++ 82


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; }
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 83


Checksum 8 bit

#include <reg51.h>  Summation:


void main(void) {
unsigned char mydata[]
25H+ 62H+ 3FH+ 52H =
={0x25,0x62,0x3F,0x52}; 118H
unsigned char sum=0, x
 Two complements of
unsigned char chksumbyte;
for (x=0;x<4;x++) { 118H is E8H
P2=mydata[x];
sum=sum+mydata[x];
P1=sum;
}
chksumbyte=~sum+1;
P1=chksumbyte;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 84


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;
 Verify the check sum: unsigned char x;
for (x=0;x<5;x++)
25H+ 62H+ 3FH+ 52H + E8H = 0
chksum=chksum+mydata[x];
if (chksum==0)
P0=‘Good’;
else
P0=‘Bad’;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 85


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

© HĐC 2024.1 Chapter 2: Basic of C & C++ 86


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 */
};

© HĐC 2024.1 Chapter 2: Basic of C & C++ 87


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) */

© HĐC 2024.1 Chapter 2: Basic of C & C++ 88


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).

© HĐC 2024.1 Chapter 2: Basic of C & C++ 89


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;

© HĐC 2024.1 Chapter 2: Basic of C & C++ 90


Example

Implement an operation to swap 2 variables using XOR


#define SWAP(a,b) {a^=b; b^=a; a^=b;}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 91


Union vs Struct revision

Structure Union
struct example union example
{ {
char X; // size 1 byte char X; // size 1 byte
float Y; // size 4 bytes float Y; // size 4 bytes
} }

Each member is allocated a different slot


Memory sharing Largest member

X Y X&Y

1 byte 4 byte

5 byte 4 byte
Total size of all members

© HĐC 2024.1 Chapter 2: Basic of C & C++ 92


Bit Field
32 bits
1111 4 8 16

ready
error
write_protected
disk_spinning command error_code sector_number

struct Disk_Register
{
unsigned int ready:1; // 1 bit field named “ready”
unsigned int error:1; // 1 bit field named “error”
unsigned int wr_prot:1;
unsigned int dsk_spinning:1;
unsigned int command:4; // 4 bits field named “command”
unsigned int error_code:8;
unsigned int s:1;
}
Assuming that we have a 32-bit register with the above parameters
© HĐC 2024.1 Chapter 2: Basic of C & C++ 93
Bit Field Example 1
struct Disk_Register
{
unsigned int ready:1 ; // 1 bit field named "ready"
unsigned int error:1 ; // 1 bit field named "error"
unsigned int wr_prot:1 ;
unsigned int dsk_spinning:1 ;
unsigned int command:4 ; // 4 bits field named "command"
unsigned int error_code:8 ;
unsigned int sector_no:16 ;
};

void printBits( int a )


{
int i;

for ( i = 31; i >= 0; i-- )


{
if ( (a & (1<<i) ) != 0 )
putchar('1');
else
putchar('0');
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 94


Bit Field Example 1
int main( int argc, char* argv[] )
{
struct Disk_Register r;

printf( "sizeof(r) = %lu\n", sizeof(r) );

int *p = (int *) &r; // Make p point to r

*p = 0; // Clear all 32 bits in r


printBits( *p ); // Print the bits in r
putchar('\n');

r.error = 1; // Set the error bit (bit #30)


printBits( *p ); // Print the bits in r
putchar('\n');

r.dsk_spinning = 1; // Set the disk spinning bit (#28)


printBits( *p ); // Print the bits in r
putchar('\n');
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 95


Working with Union
struct Disk_Register
{
unsigned int ready:1 ; // 1 bit field named "ready"
unsigned int error:1 ; // 1 bit field named "error"
unsigned int wr_prot:1 ;
unsigned int dsk_spinning:1 ;
unsigned int command:4 ; // 4 bits field named "command"
unsigned int error_code:8 ;
unsigned int sector_no:16 ;
};

/* Re-map the 32 bits Disk Register AND an integer together */


union U_Disk_Register
{
struct Disk_Register Reg; // 32 bits mapped as struct Disk_Register
int Whole_Reg; // 32 bits as one int
};

© HĐC 2024.1 Chapter 2: Basic of C & C++ 96


Working with Union
int main( int argc, char* argv[] )
{
union U_Disk_Register r;

printf( "sizeof(r) = %d\n", sizeof(r) );

r.Whole_Reg = 0; // Clear all 32 bits

r.Reg.error = 1; // Set the error bit (bit #30)


printBits( r.Whole_Reg ); // Call the printBits() function
putchar('\n');

r.Reg.dsk_spinning = 1; // Set the dsk_spinning bit (bit #28)


printBits( r.Whole_Reg ); // Call the printBits() function
putchar('\n');
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 97


Bit Field Example 2

© HĐC 2024.1 Chapter 2: Basic of C & C++ 98


Float to IEEE 32bit conversion
(or mantisa)

E.g.:

© HĐC 2024.1 Chapter 2: Basic of C & C++ 99


Float to IEEE 32bit conversion

#include <stdio.h>

void printBinary(int n, int i)


{
// Prints the binary representation of a number n up to i-bits.
int k;
for (k = i - 1; k >= 0; k--) {
if ((n >> k) & 1)
printf("1");
else
printf("0");
}
}

typedef union {
float f;
struct {
// Order is important. Here the members of the union data tructure
// use the same memory (32 bits). The ordering is taken from LSB
// to MSB.
unsigned int mantissa : 23;
unsigned int exponent : 8;
unsigned int sign : 1;
} raw;
} myfloat;

© HĐC 2024.1 Chapter 2: Basic of C & C++ 100


Float to IEEE 32bit conversion

// Function to convert real value to IEEE foating point representation


void printIEEE(myfloat var)
{
// Prints the IEEE 754 representation of a float value (32 bits)
printf("%d | ", var.raw.sign);
printBinary(var.raw.exponent, 8);
printf(" | ");
printBinary(var.raw.mantissa, 23);
printf("\n");
}

// Driver Code
int main()
{
// Instantiate the union
myfloat var;
// Get the real value
var.f = -2234.32425;

// Get the IEEE floating point representation


printf("IEEE 754 representation of %f is : \n", var.f);
printIEEE(var);

return 0;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 101


Convert float to hex and hex to float

#include <stdio.h>

int main(void) {
union {
float f;
unsigned char b[sizeof(float)];
} v;

v.f = 3.1415926535897932384626433832795F;

size_t i;
printf("%.20f is stored as ", v.f);
for (i = 0; i < sizeof(v.b); ++i) {
printf("%02X%c", v.b[i], i < sizeof(v.b) - 1 ? '-':'\n');
}

v.f = 0.0;

v.b[0] = 0xdb;
v.b[1] = 0x0f;
v.b[2] = 0x49;
v.b[3] = 0x40;

printf("PI value is %.20f \n", v.f);


return 0;
}

© HĐC 2024.1 Chapter 2: Basic of C & C++ 102


Further exploration

What is double precision floating format?


The conversion formula

© HĐC 2024.1 Chapter 2: Basic of C & C++ 103


End of Chapter 2

You might also like