CS计算机代考程序代写 python RISC-V data structure c/c++ compiler Java c++ computer architecture AI COMP2017 & COMP9017: Systems Programming

COMP2017 & COMP9017: Systems Programming

C Crash Course (I): C Basics

for System Programming

Presented by
Dr. Shuaiwen Leon Song
USYD Future System Architecture Lab (FSA)
https://shuaiwen-leon-song.github.io/

https://shuaiwen-leon-song.github.io/

COMMONWEALTH OF AUSTRALIA

Copyright Regulations 1969

WARNING

This material has been reproduced and communicated to you by or on behalf of

the University of Sydney pursuant to Part VB of the Copyright Act 1968 (the Act).

The material in this communication may be subject to copyright under the Act. Any
further copying or communication of this material by you may be the subject of

copyright protection under the Act.

Do not remove this notice.

Acknowledgement

Some material in these slides was based on lectures by Dr. John

Stavrakakis from COMP2017/COMP9017, A/Prof Bob Kummerfeld
and Prof Judy Kay

Reading material: https://www.cs.rochester.edu/u/ferguson/csc/c/c-for-

java-programmers.pdf

The C Programming Language (K&R)

https://www.cs.rochester.edu/u/ferguson/csc/c/c-for-java-programmers.pdf

An interesting question

Q: Hi there,

I am confused why a scalable system need to maintain the same efficiency as processors are

added? Why don’t we think about improving the efficiency?

A: It is one of the metrics to measure scalability. Because scalable systems’ speedup are

bounded by the increasing number of processors while increasing problem size can help

improve the speedup. On the page 2 of the paper, it clearly shows this. No systems can scale

linearly so what is the best way to increase the problem size with respect to the number of

processors to keep the keep the efficiency fixed (please see the following paper for

definition). Iso-efficiency metric helps answer this. You can think about improving the

efficiency if the baseline is bad. But what if the efficiency is good, how can you maintain it

while you scale your system size? That is the question it tries to answer. Please read the paper:

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.416.729&rep=rep1&type=pdf

http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.416.729&rep=rep1&type=pdf

C-Language

› Mainly usedfor

– Systems software (OS, embedded systems, etc.)

– Software that needs hardware interaction

› Also..

– Application programming, science/engineering, etc.

› C-Compilers exist for nearly all computerarchitectures

› A very popular language

› C does not have features suchas

– Objects and Classes

– Templates

– Operator/Function overloading

› C++ overcomes this and is a successor ofC

› Writing a non-optimizing C-Compiler is straightforward

– Reason for the success story of C

Programming Using C: Choice of High Performance

Tensor Flow lower level optimizations

Edge devices: Coral provides on-device AI for both
prototyping and production projects. It’s a platform

of hardware components, software tools, and pre-

compiled machine learning models, allowing you

to create local AI in any form-factor.

Golden age of computer architecture:
https://dl.acm.org/doi/10.1145/3282307
Innovations like domain-specific hardware, enhanced
security, open instruction sets (RISC-V), and agile chip
development will lead the way.

Example: Operating System Linux in C

› Started in 1991 by Linus
Torvalds

› Linus’ UNIX -> Linux

› Kernel, i.e., core of the
operating system.

› To complete distribution, GNU
tools were used.

› In 1992 the first distributions
emerged.

› Now we have numerous
devices running Linux

– Smartphones, routers, …

› C is the language of choice

– HW Indepdence & Performance

Example: Python written in C

› Python is a scriptinglanguage.

› Was released in 2000; has been spreading rapidly because ease of use.

› Comprises several programmingparadigms

– Imperative

– Object-oriented

– Functional

› Easy tolearn

› Standard reference implementation

is written in C.

Guido van Rossum

Example: Apache Web-Server

› Apache Web-serveris
back-bone of the
internet

› Initially released1995

› surpass the 100million
website milestone in
2009

› Runs widely on
Windows, Unix, Mac,

› Written inC

C-Language (cont’)

› C-Programs consists of two languagecomponents

– Preprocessing Language

– C-Language

› PreprocessingLanguage

– Text-macro language

– Definition of macros

– Include files

– Conditional compilation

Java to C

› Differences

– Control flow structures are the same

– esp. before Java 1.4

– References are called “pointers” in C

– No garbage collection

– Programmer is responsible for allocating and freeing memory

– No classes or objects

› A C-program consists of a set of files containing:

– global variables

– function definitions

– “main” is the first function invoked

– functions have local variables

Java

/* This program prints “Hello world.” on a line and exits

*/

public class HelloWorld

{

public static void main (String args[])

{

System.out.println (“Hello world.”);

}

}

The most known C-Program

(int argc, char **argv)

#include

int main

{

printf(“Hello World!\n”);

return 0;

}

› Prints “Hello world!” on standard output

› Does not read from standard input

› Variable argc stores number of arguments

› Variable argv pointers to arguments

int main(int argc, char **argv)

{

int ftemp; /* the fahrenheit temperature */

printf(“Please enter a fahrenheit temperature”);

is %d centigrade”,

(ftemp – 32) * 5 /

ftemp,

9);

scanf(“%d”, &ftemp);

printf(“%d fahrenheit

return 0;

}

Running C Code

› Create a program text in a file whose name has the suffix “.c”

› Compile the program using the command gcc

– gcc hello.c –o hello

– gcc hello.c

› Use all those compiler flags

› Run the program by typing the name of the object file

produced by the compiler. (The default is a.out.)

› ./hello

› ./a.out

Java vs C

Philosophical differences

› C closer to underlyingmachine

› C has simple memory model

– pointers, bit-level operators

– arrays very close to memory model

› C assume programmer knows best

› Java object-oriented v Cprocedural

– No object

– No polymorphism

– No inheritance

Strong similarities

› Blockstructured

› Most controlstructures

– if, else, while, do … while, switch, for (mostly),

– break, continue (no labels in C)

› Arrays

› Operators (mainly the same)

› Basic data types (mainly similar)

More differences – preprocessor

› C macros(#define)

› C has declaration for variables and functions,
often in header files that are included

› conditional compilation (#if, #ifdef, #ifndef,

#else, #elif, etc.)

#define N 1000

//add.h

Int add(int a, int b);

//add.c
#include “add.h”
Int add(int a, int b) {

return a + b
}

#include

#define x 10

int main()

{

#ifdef x

printf(“hello\n”); // this is compiled

as x is defined

#else

printf(“bye\n”); // this isn’t

compiled

#endif

return 0;

}

Arrays and memory

› Arrays can be handled withpointers

› Arrays can be created and initializedin declaration

› C strings are just arrays (withtermination character)

› sizeofoperator

› create dynamic data structures withmalloc()

› C allows declarations only at blockstart (C89 standard)

C99 Standard

1. Will compiler report errors?

2. What the printout will be like?

0:
some string
1: !
some string
2: ”
some string
3: #
some string
4: $
some string
5: %
some string
6: &
some string
7: ‘
some string
8: (
some string
9: )
some string

ASCII: American Standard Code for Information

Interchange

Summary

› C and Java have some similarities

– syntax, control structures

› but some deep differences

– Java is OO, C much closer to the hardware

› C is higher performance than Java

› C is widely used for embedded systems, operating

systems, etc.

› C has evolved into OO forms (Objective C, C++)

Functions in C

A function consists of

– A function declaration:

– Name of function,

– Return type of function,

– Parameter list and their types

– Followed by a function body:

– Local variables & control flow

int foo(float f1, char c2)

…..

int foo(float f1, char c2)

{

int x = 0;

return x;

}

Functions in C

› External or forward function declarations do not have a

function body, just a semicolon

– parameter types are specified without variable names

› A function with a given name can only be defined once

› If no return value exists for a function, use the type void

› If no parameters exist use, use type void

int foo(float, char);

void foo(….) { ….}

void foo(void) { ….}

extern int foo(float, char);

Functions in C

› Functions with arbitrary numbers ofparameters
are possible

› In this case, a special interface is required for

querying values of parameters

– Lookup the va_args interface

– At least one fixed parameter in the function is necessary

– Function call is simple

int printf(const char *format, …)

printf(“%d, %f”, 10, 10.5);

Example: using va_arg interface

Example: Function

› Compute factorial n!

int factorial (int n)
{

int result;

if (n > 1 )

{
result = n * factorial(n-1);

}

else

{

result = 1;

}

return result;

}

local variable

function declaration

control flow

Function Example: Factorial (recursive vs iterative)

// C program to find factorial of given number

#include

// Function to find factorial of given number
unsigned int factorial(unsigned int n)
{

if (n == 0)
return 1;

return n * factorial(n – 1);
}

// Driver code
int main()
{

int num = 5;
printf(“Factorial of %d is %d”,

num, factorial(num));
return 0;

}

#include

// Function to find factorial of given number
unsigned int factorial(unsigned int n)
{

int res = 1, i;
for (i = 2; i <= n; i++) res *= i; return res; } // Driver code int main() { int num = 5; printf("Factorial of %d is %d", num, factorial(num)); return 0; } Control-structures in C › Mostly the same as inJava › statements are terminated by a semicolon; the null statement isallowed. › A statement can be a sequence of statements inside a block ;….; ;

{

;

;

}

Control-structures in C

› if statements:

› while statements:

if ( )

If ( )

else

while ( )

do

while ( )

Control-structures in C

› for statement:

for ( ; ; )

Control-structures in C

› for statement example:

for ( x = 0; x < 100; x++) counter[x] = x; Control-structures in C › return, break and continue statements: › return will return to the calling function, optionally returning avalue. › break ends the loop immediately when it is encountered. › continue skips the current iteration of the loop and continues with the next iteration. return;
break;
continue;

Control-structures in C

› switch statement:

switch(…)

{

case : ;

case …: …

default: …

}

Switch Statement Example

// Following is a simple C program
// to demonstrate syntax of switch.
#include
int main()
{
int x = 2;
switch (x)
{

case 1: printf(“Choice is 1”);
break;

case 2: printf(“Choice is 2”);
break;

case 3: printf(“Choice is 3”);
break;

default: printf(“Choice other than 1, 2 and 3”);
break;

}
return 0;
}

C modules

› Programs consist of “modules”

– A module is a file, i.e., hello.c

› Modules consist of

– Function declarations

– Function definitions

– Global variables

› Modules are translated to object files

› Object files are linked by linker with other object files and

standard libraries

C file or module

› A module can refer to global variables and functions of other modules

– use the extern qualifier for global variables

› Symbols can only be defined in one module

› Data structures definitions and declarations, macro definitions and external
function declarations are found in modules

– These are commonly found in header files

#include

#include

int global1;

int foo(int x,int y)

{

return x + y;

}

#include

#include

extern int global1;

extern int foo(int x,int y);

int foo2(int x,int y)

{

return foo(x,y)+global1;

}

Module example

extern int foo();

foo.c

int foo()

{

printf (“hello from foo\n”);

return 0;

}

foo.h

Module example

}

extern int foo();

int main(int argc, char **argv)

{

foo();
return 0;

}

foo.c

int foo()

{

printf (“hello from foo\n”);

return 0;

foo.h

sample.c
#include “foo.h”

Input/Output functions

› Basic Input: int getchar(void);

– reads from standard input next character

– returns -1 (defined as the symbol EOF) if end of input

reached

› Basic Output: void putchar(int c);

– Write a character (represented as an integer) to standard

output

› getchar/putchar are very simple

printf()-function

› printf()-function writes to standardoutput:

– Strings

– variables of primitive a data-type

› Returnvalue:

– Number of printed characters

› Arguments

– First argument is a format string

– Followed my an arbitrary number of parameters depending on format string

› Example:

printf(“%d %f\n”, 10, 10.5);

– Output: 10 10.5

– %d print an integer followed later as a parameter

– %f print a float followed later as a parameter

– \n means print new line

int printf(const char *format, …);

Format string codes for printf

Code Description

%c Character

%d Integer

%u Unsigned integer

%f, %g, %e Double floating point

number

%x Hexadecimal

%ld long

%.2f Print floating point numbers

with two decimal points

%s String

%p Pointer

%% Print %

scanf()-function

› scanf()-function reads from standard input:

– Values of primitive data-type and strings

› Return value:

– Number of successfully read items

› Argument

– First argument is a format string

– Followed my an arbitrary number of parameters depending on format string

– Parameters must be pointers – not values

› Example:

– Read an integer and store it in x

– Read a float and store it in f

– Same format string as in scanf

int scanf(const char *format, …);

int x;

float f;

scanf(“%d %f”, &x, &f);

scanf example

Simple variables

› C has a number of simple data types

– float, int, char etc

– each implies an interpretation of the bit pattern stored in the
memory.

› Declarations label and reserve memory:

int counter;

› Initialization or assignment specifies content:
int counter = 0;

counter = 0;

reserve memory for an integer and call it

“counter”

C- Data Types

Number converter (binary, decimal, hexadecimal):
http://easyonlineconverter.com/converters/dec-to-bin-to-hex-converter.html

sizeof(type) is your best friend!

Example: Detect Integer Overflow

CHAR_BIT : 8

CHAR_MAX : 127

CHAR_MIN : -128

INT_MAX : 2147483647

INT_MIN : -2147483648

LONG_MAX : 9223372036854775807

LONG_MIN : -9223372036854775808

SCHAR_MAX : 127

SCHAR_MIN : -128

SHRT_MAX : 32767

SHRT_MIN : -32768

UCHAR_MAX : 255

UINT_MAX : 4294967295

ULONG_MAX : 18446744073709551615

USHRT_MAX : 65535

0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0
0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1
1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1

Memory

1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1
0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1
0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0

Memory

char a;

1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1
0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1
0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0

Memory

char a;

a = ‘$’;

Arrays

› Arrays are indexed collections of the sametype

› Declaration of anarray:
int counters[MAX];

char alphabet[26];

› Initialisation of anarray:

for (i = 0; i < MAX; i++) counters[i] = i; 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1 Memory 0 1 0 0 0 0 1 000 1 0 0 0 0 1 char ch[2]; 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1 “ch[0]” Memory “ch[1]” 0 1 0 0 0 0 1 0 char ch[2]; printf(”%c\n”, ch[1]); 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1 “ch[0]” Memory “ch[1]” char ch[2]; printf(”%c\n”, ch[1]);  “ch[0]” 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1 Output of random data Memory “ch[1]” 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1  “ch[0]” 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 Output of random data Memory “ch[1]” char ch[2]; printf(”%c\n”, ch[1]); ch[0] = ’A’; ch[1] = ’B’; 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 “ch[0]”  AB Output of random data 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 0 1 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 0 0 1 1 1 Output of initialised data Memory “ch[1]” char ch[2]; printf(”%c\n”, ch[1]); ch[0] = ’A’; ch[1] = ’B’; printf(”%c%c\n”, ch[0], ch[1]); Strings › Strings may be initialised at the time ofdeclaration using an “array-like” notational convenience: char myHobby[] = ”rowing”; The compiler can determine the required size by counting characters, so the array size is optional. A larger size may be specified. Strings › Strings resemble an array ofcharacters. › However, in C, all strings areNULL-terminated. Note: NULL is the binary value 0 (denoted ‘\0’), not the ASCII representation of the character 0. char myHobby[] = ”rowing”; ’r’ ’o’ ’w’ ’i’ ’n’ ’g’’\0’ 1 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0 char str[] = ”A”; printf(”%s\n”, str); “str” 0 1 0 0 0 0 0 1 A Memory 0 0 0 0 0 0 0 0 sizeof operator › Not all h/w architectures are the same - different sizes for basic types › C specification does not dictate exactly how many bytes an int will be › sizeof operator returns the number of bytes used to represent the given type or expression - sizeof( char ) - sizeof( int ) - sizeof( float * ) - sizeof ( 1 ) sizeof operator › Not all h/w architectures are the same - different sizes for basic types › C specification does not dictate exactly how many bytes an int will be › sizeof operator returns the number of bytes used to represent the given type or expression. - sizeof( char ) - sizeof( int ), sizeof( double ) - sizeof( float * ) - sizeof ( 1 ), sizeof ( 1/2 ), sizeof (1.0 / 2.0) - sizeof( p ) ???? sizeof › Special case for p, what is it? - char p; - char *p; - char p[8]; › But… - char msg[100]; // 100 - char *p = msg; // 8 - char msg2[] = “hello message”; // 14 - char *p = msg2; // 8 - char *p = “program has ended”; // 8 › sizeof needs to be used carefully Less familiar types › The types char will support the value range from CHAR_MIN to CHAR_MAX as defined in file – #define UCHAR_MAX 255 /* max value for an unsigned char */

– #define CHAR_MAX 127 /* max value for a char */

– #define CHAR_MIN (-128) /* min value for a char */

› Most C implementations default types as signed values, but
a warning that you should not assume this.

› unsigned and signed enforce the sign usage

– char ch;

– signed char ch;

– unsigned char ch;

– unsigned int total;

#include
int main()
{
printf(“%lu”, sizeof(void));
return 0;
}

#include
int main()
{
printf(“%lu”,sizeof(void *));
return 0;
}

Void Pointer size

Since NULL is typically defined as ((void*)0), let us discuss a little bit about void type as well. As per C11

standard clause 6.2.5, “The void type comprises an empty set of values; it is an incomplete object type that

cannot be completed”. Even C11 clause 6.5.3.4 mentions that “The sizeof operator shall not be applied to an

expression that has function type or an incomplete type, to the parenthesized name of such a type, or to an

expression that designates a bit-field member.” Basically, it means that void is an incomplete type whose

size doesn’t make any sense in C programs but implementations (such as gcc) can choose sizeof(void) as 1

so that the flat memory pointed by void pointer can be viewed as untyped memory i.e. a sequence of bytes.

But the output of the following needn’t to same on all platforms.

On gcc, the above would output 1. What about sizeof(void *)? Here C11 has mentioned

guidelines. From clause 6.2.5, “A pointer to void shall have the same representation

and alignment requirements as a pointer to a character type”. That’s why the output of

the following would be same as any pointer size on a machine.

Less familiar const

› constprevents the value being modified

– const char *fileheader = “P1”

– fileheader[1] = ‘3’;

› It can be used to help avoid arbitrary changes tomemory

› The value constprotects depends where it appears

– char * const fileheader = “P1”

– fileheader = “P3”;

› Reading right to left:

– Is an address, points to a char, that is constant

– Is an address, that is constant

Illegal: change of address value

Illegal: change of char value

Less familiar const

› constprevents the value being modified

– const char *fileheader = “P1”

– fileheader[1] = ‘3’;

› It can be used to help avoid arbitrary changes tomemory

› The value constprotects depends where it appears

– char * const fileheader = “P1”

– fileheader = “P3”;

› You can cast if you know if the memory iswritable

Illegal: change of address value

Illegal: change of char value

char fileheader[] = {‘P’, ‘1’};

const char *dataptr = (char*)fileheader;

char *p = (char*)dataptr;

p[1] = ‘3’;

writable

Non-writable

Floating point types

› Exact bit representation unknown, usually IEEE754

› Generally, floating point number x is defined as:

› s sign

› b base of exponent (e.g. 2, 10,16)

› e exponent

› p precision

› fk nonnegative integer less than b

+0

+ve / 0 = +infinite

NaN (not a number)

-0

-ve / 0 = -infinite

Zero exponents…

FACULTY OF

ENGINEERING

Variable Scope and Lifetime

Scope and Lifetime of Variables in C

Declaration vs. Definition

• A declaration tells the compiler the type of a

variable, object or function.

• A definition allocates memory for a variable

or object and is the implementation of a

function.

• Multiple declarations are allowed, but only

one definition.

Scope and Lifetime of Variables in C

Declaration vs. Definition:

//add.h

Int add(int a, int b);

//add.c
#include “add.h”
Int add(int a, int b) {

return a + b
}

Scope and Lifetime of Variables in C

Scope & Lifetime:

• The scope of a declaration is the part of the

program for which the declaration is in

effect.

• C/C++ use lexical scoping (aka. static

scope).

• The lifetime of a variable or object is the

time period in which the variable/object has

valid memory.

• Lifetime is also called “allocation method” or

“storage duration.”

Scope and Lifetime of Variables in C

Lifetime:

• Static: The memory for static objects is allocated at

compile/link time. It’s lifetime is the entire duration of the

program’s execution.

Scope and Lifetime of Variables in C

Lifetime:

• Static: The memory for static objects is allocated at

compile/link time. It’s lifetime is the entire duration of the

program’s execution.

• Automatic: An automatic variable has a lifetime that begins

when program execution enters the function or statement

block or compound and ends when execution leaves the

block. Automatic variables are stored in a “function call

stack”.

Stack Overflow (I)

1. If we declare large number of local variables or declare an array or matrix or any

higher dimensional array of large size can result in overflow of stack.

// C program to demonstrate stack overflow
// by allocating a large local memory
#include

int main() {

// Creating a matrix of size 10^5 x 10^5
// which may result in stack overflow.
int mat[100000][100000];
}

Stack Overflow (II)

// C program to demonstrate stack overflow
// by creating a non-terminating recursive
// function.
#include

void fun(int x)
{

if (x == 1)
return;
x = 6;
fun(x);

}

int main()
{
int x = 5;
fun(x);
}

2. If function recursively call itself infinite times then the stack is unable to store large

number of local variables used by every function call and will result in overflow of stack.

Program Crashing!!!

Core Dump/Segmentation Fault

Core Dump/Segmentation fault is a specific kind of error caused by accessing memory that

“does not belong to you.”

•When a piece of code tries to do read and write operation in a read only location in memory

or freed block of memory, it is known as core dump.

•It is an error indicating memory corruption.

Six Main Ways:

1. Modifying a string literal (writing to read-only memory)

2. Accessing an address that is freed (not allowed in compiler)

3. Accessing out of array index bounds

4. Improper use of scanf() (input fetched from STDIN is placed in invalid memory,

causing memory corruption)

5. Stack Overflow

6. Dereferencing uninitialized pointer (A pointer must point to valid memory

before accessing it).

Scope and Lifetime of Variables in C

Lifetime:

• Static: The memory for static objects is allocated at

compile/link time. It’s lifetime is the entire duration of the

program’s execution.

• Automatic: An automatic variable has a lifetime that begins

when program execution enters the function or statement

block or compound and ends when execution leaves the

block. Automatic variables are stored in a “function call

stack”.

• Dynamic: The lifetime of a dynamic object begins when

memory is allocated for the object (e.g., by a call to

malloc()) and ends when memory is deallocated (e.g., by a

call to free() or using delete). Dynamic objects are stored

in “the heap”.

Scope and Lifetime of Variables in C

int cnt_even = 0;

int *cnt_odd = NULL;

int count_even_and_odd(int arr[], int len) {

static int cnt_call_times = 0;

cnt_call_times++;

if (cnt_odd == NULL) {

cnt_odd = malloc(sizeof(int)); *cnt_odd = 0;

}

int i;

for (i = 0; i < len; i++) { if (arr[i] % 2 == 0) cnt_even++; else (*cnt_odd)++; } return cnt_call_times; } A very simple program for counting even and odd number count. Return how many time the function was called. Scope and Lifetime of Variables in C int cnt_even = 0; int *cnt_odd = NULL; int count_even_and_odd(int arr[], int len) { static int cnt_call_times = 0; cnt_call_times++; if (cnt_odd == NULL) { cnt_odd = malloc(sizeof(int)); *cnt_odd = 0; } int i; for (i = 0; i < len; i++) { if (arr[i] % 2 == 0) cnt_even++; else (*cnt_odd)++; } return cnt_call_times; } A very simple program for counting even and odd number count. Return how many time the function was called. Lifetime: Static Scope and Lifetime of Variables in C int cnt_even = 0; int *cnt_odd = NULL; int count_even_and_odd(int arr[], int len) { static int cnt_call_times = 0; cnt_call_times++; if (cnt_odd == NULL) { cnt_odd = malloc(sizeof(int)); *cnt_odd = 0; } int i; for (i = 0; i < len; i++) { if (arr[i] % 2 == 0) cnt_even++; else (*cnt_odd)++; } return cnt_call_times; } A very simple program for counting even and odd number count. Return how many time the function was called. Lifetime: Static Dymamic Scope and Lifetime of Variables in C int cnt_even = 0; int *cnt_odd = NULL; int count_even_and_odd(int arr[], int len) { static int cnt_call_times = 0; cnt_call_times++; if (cnt_odd == NULL) { cnt_odd = malloc(sizeof(int)); *cnt_odd = 0; } int i; for (i = 0; i < len; i++) { if (arr[i] % 2 == 0) cnt_even++; else (*cnt_odd)++; } return cnt_call_times; } A very simple program for counting even and odd number count. Return how many time the function was called. Lifetime: Static Dymamic Automatic Static Variables • All the static variables that do not have an explicit initialization or are initialized to zero are stored in the uninitialized data segment( also known as the BSS segment). In computer programming, the name .bss or bss is used by many compilers and linkers for the portion of an object file or executable containing statically-allocated variables that are not explicitly initialized to any value. It is often referred to as the "bss section" or "bss segment". • Compared to this, the static variables that are initialized are stored in the initialized data segment. • Local statics may look useful, however they cause major problems when trying to port code to a multi-task/multi-threading environment, and should generally be avoided where possible. https://en.wikipedia.org/wiki/Computer_programming https://en.wikipedia.org/wiki/Compiler https://en.wikipedia.org/wiki/Linker_(computing) https://en.wikipedia.org/wiki/Object_file https://en.wikipedia.org/wiki/Static_variable •global variables -------> data

•static variables ——-> data

•constant data types —–> code (ready-only) and/or data. Consider string literals for a

situation when a constant itself would be stored in the data segment, and references to it

would be embedded in the code

•local variables(declared and defined in functions) ——–> stack

•variables declared and defined in main function —–> stack

•pointers(ex: char *arr, int *arr) ——-> data or stack, depending on the context. C
lets you declare a global or a static pointer, in which case the pointer itself would end
up in the data segment.

•dynamically allocated space (using malloc, calloc, realloc) ——–> heap

It is worth mentioning that “stack” is officially called “automatic storage class”.

This shows the typical layout of a simple

computer’s program memory with the text,

various data, and stack and heap sections.

Scope and Lifetime of Variables in C

Scope:

• The scope of an object is the part of the program where the

variable can be accessed (i.e. it is visible).
• File scope
• Block scope

• A variable must be declared before it is accessed
• scope of a variable is determined by the placement of its

declaration

Scope and Lifetime of Variables in C

File Scope

• Any variable declared with file scope can be accessed by

any function defined after the declaration

Block Scope

• Block scope is defined by the pairing of the curly braces {

and } . A variable declared within a block can only be

accessed within that block.

int global_a = 0; // File Scope

Int func() {

int local_b = 1; // Block Scope

int i = 10;

while(i–) {

int b; // Block Scope

}

}

Scope and Lifetime of Variables in C

Scope Overlapping:

Rule: An inner scope identifier always hides an outer scope

identifier

int k = 20;

int main()

{

int k = 10;

printf( “In main, k is %d\n”, k);

}

//output: In main, k is 10

FACULTY OF

ENGINEERING

Pointers

Memory

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

Random values initially

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

› a pointer is essentially a variable that
stores a memory address

› we can find out the address of a variable using

the & operator

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

Memory

char initial = ‘A’;

char *initp = &initial

&initial is the address of initial
initp is a pointer to initial

00100010

01010010

00110110

00101010

10100010

01100010

00111010

00100110

11100010

0x100

0x101

0x102

0x103

0x104

0x105

0x106

0x107

0x108

address content

Pointers

0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1

1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1 0 1 0 0 0 1 1 1

0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 1
0 1 0 0 0 1 1 11 0 0 1 0 1 0 0 1 1 0 0 1 1 0 0 0 0 1 0 1 1 1 1 0 0 1 0 1 0 0 1

variable name: “count”
address of count: 0x1000 = 4,096

0 0 0 1 0 1 1 0 0 1 0 0 0 1 0 0 0 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1 0 0 0 0 1 1 1 0
0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 1 0 1 0 1 1 1 0 1 0 1 0 1 1 0 0 0 0 1 0 0 1

1 0 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0

Clearly, the value of a pointer can

only be determined at run-time.

Somewhere in memory…

Somewhere else in memory…

Label: “ptr”

int count;

int *ptr;

count = 2;

ptr = &count;

printf(”%d\n”, count);

printf(”%d\n”, *ptr);

printf(”%d\n”, &count);

printf(”%d\n”, ptr);

2

2

4096

4096

Label: “count”

Pointers (notation)

› Pointer operators:

– address operator, ‘&’

– indirection operator, ‘*’

Note that these operators are “overloaded”, that is they have
more than one meaning.

– ‘&’ is also used in C as the bitwise ‘AND’ operator

– ‘*’ is also used in C as the multiplication operator

Pointers (notation)

› The indirection operator, ‘*’, is used in a variable
declaration to declare a “pointer to a variable of the
specified type”:

int * countp; /* pointer to an integer */

Type is “a pointer to an integer”

Variable name, “countp”

What do the following
mean?

float * amt;

int ** tricky;

Answers:

A pointer (labeled “amt”) to
a float.

A pointer (labeled “tricky”)
to a pointer to an int.

Pointers (notation)

…prints ‘2’ to standard output.

› The indirection operator, ‘*’, is used to “unravel” the
indirection:

countp points to an integer variable that contains the value 2.

Then…

2
printf(”%d”, *countp);

countp

Unravel the

indirection

What is output in the following?

printf(”%d”, count);

17

printf(”%d”, *countp);

17

printf(”%d”, countp);

Don’t know… but it will be
the address of count.
Why?

17

countp

count

› The address operator, ‘&’, is used to accessthe
address of a variable.

›This completes the picture! A pointer can be

assigned the address of a variable simply:

int * countp = &count;

Declare “a pointer to an integer” called countp

Assign countp the address of count.

An example of the the address operator in action…

Receiving an integer from standard input:

int age;

scanf(”%d”, &age);

This argument is required by scanf()

to be a pointer. Since we are using

a simple integer, age, we pass it’s
address.

Examples

Use of pointer notation to manipulate arrays…

char msg[] = ”Hello!”;

char *str = &msg[0];

OR:
char *str = msg;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

Pointers and arrays

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

msg[0]

str[0]

*str

msg[1]

str[1]

*(str+1)

Pointer notation leads to some (intimidating?) shortcuts as
part of the C idiom.

Moving through a string:

while (*str != ’\0’)

str++;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

The previous example may exploit the fact that C

treats ‘0’ as FALSE:

while (*str)

str++;

’H’ ’e’ ’l’ ’l’ ’o’ ’!’ ’/0’

Examples

› Some mathematical operations are moreconvenient
using pointers

– e.g., array operations

› However, we have only looked at static data. Pointers
are essential in dealing with dynamic data structures.

› Imagine you are writing a texteditor.

– You could estimate the largest line-length and create arrays of
that size (problematic).

– Or you could dynamically allocate memory as needed, using
pointers.

›What is the value held by p? and how much
memory is used by p (in bytes)?

› int p;

› char p;

› void foo( int *p )

› char *p;

› char **p;

›What is the value held by p? and how much
memory is used by p (in bytes)?

› int p;

› char p;

› void foo( int *p )

› char *p;

› char **p;

› int **p;

› long *p;

› void *p;

› const unsigned long long int * const p;

› bubblebobble ************p;

› char *p

– Address to a single char value

– Address to a single char value that is the first in an array

› char *argv[]

– Array of “the type” with unknown length

– Type is char *

› char **argv

– * Address to the first element to an array of type char *

– Then, each element in * is an…

– * address to the first element to an array of type char

char argv[][3]; // oh no!

› Interpretations of int **data;

1. Pointer to pointer to single int value

2. Array of addresses that point to a single int

3. Address that points to one array of int values

4. Array of addresses that point to arrays of int values

Pointer interpretation

› Interpretations of int **data;

1. Pointer to pointer to single int value

2. Array of addresses that point to a single int

3. Address that points to one array of int values

4. Array of addresses that point to arrays of int values

› Thinking about each * as an array:

1. Array size ==1, Array size ==1

2. Array size >=1, Array size == 1

3. Array size ==1, Array size >= 1

4. Array size >=1, Array size >= 1

Pointer interpretation

› When you call a function in Java, compare passing a
primitive type and Object type.

› You may have heard:

– Pass by value

– Pass by reference

What is the meaning of this in C?

› void has no size, but sizeof(void*) is the size of an address

› Pointers are unsigned numbers, why?

Pointer comments

0x0100 0x0104 0x0105

› int *p = NULL;

› int x[4];

› p = x;

x = 0x0100
0x0101 0x0101 0x0102 0x0103

0 0 0 17

0x0106 0x0107 0x0108 0x0109 0x010A 0x010B 0x010C 0x010D 0x010E

*(p + 0) *(p + 1) *(p + 2)

› Seeking to the nth byte from a starting address?

*(p + 3)

Pointer arithmetic

0x0100 0x0104 0x0105

› int *p = NULL;

› int x[4];

› p = x;

x = 0x0100
0x0101 0x0101 0x0102 0x0103

0 0 0 17

0x0106 0x0107 0x0108 0x0109 0x010A 0x010B 0x010C 0x010D 0x010E

*(p + 0) *(p + 1) *(p + 2) *(p + 3)

› Seeking to the nth byte from a starting address?

void *get_address( sometype *data , int n) {

unsigned char *ptr = (unsigned char*)data;

return (void*)(ptr + n);

}

Pointer arithmetic

Q1

Assume that an int variable takes 4 bytes and a char variable takes 1 byte

(A) Number of elements between two pointer are: 5.

Number of bytes between two pointers are: 20

(B) Number of elements between two pointer are: 20.

Number of bytes between two pointers are: 20

(C) Number of elements between two pointer are: 5.

Number of bytes between two pointers are: 5

(D) Compiler Error

(E) Runtime Error

Q2

(A) Compiler Error

(B) Garbage Value

(C) Runtime Error

(D) G

Q3

(A) 10 20 30 40

(B) Machine Dependent

(C) 10 20

(D) Northing

Q4

Assuming 32-bit machine:
(A) sizeof arri[] = 3 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 4

(B) sizeof arri[] = 12 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 1

(C) sizeof arri[] = 3 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 1

(D) sizeof arri[] = 12 sizeof ptri = 4 sizeof arrc[] = 3 sizeof ptrc = 4

Q5

(A) 2 2

(B) 2 1

(C) 0 1

(D) 0 2

Q6

S1: will generate a compilation error

S2: may generate a segmentation fault at runtime depending on the arguments passed

S3: correctly implements the swap procedure for all input pointers referring to integers

stored in memory locations accessible to the process

S4: implements the swap procedure correctly for some but not all valid input pointers

S5: may add or subtract integers and pointers.

(A) S1

(B) S2 and S3

(C) S2 and S4

(D) S2 and S5

Q7

(A) 18

(B) 19

(C) 21

(D) 22

Q8

(A) 12

(B) Compiler Error

(C) Runt Time Error

(D) 0

Q9

(A)
(geeksquiz, geeksforgeeks) (geeksforgeeks, geeksquiz)

(B)
(geeksforgeeks, geeksquiz) (geeksquiz, geeksforgeeks)

(C)
(geeksquiz, geeksforgeeks) (geeksquiz, geeksforgeeks)

(D)
(geeksforgeeks, geeksquiz) (geeksforgeeks, geeksquiz)

Q10

(A) ab

(B) cd

(C) ef

(D) gh

End of Section