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

10.1 Array

1) Arrays are a fundamental data structure that store a collection of elements of the same type. They can be initialized with values or left uninitialized with garbage values. 2) Arrays in C/C++ are pointers - when an array is passed to a function, it decays to a pointer and the size is lost. The size must be explicitly passed. 3) Character arrays can store strings and require a null terminator. Modifying a character array modifies any other pointers pointing to the same memory location.

Uploaded by

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

10.1 Array

1) Arrays are a fundamental data structure that store a collection of elements of the same type. They can be initialized with values or left uninitialized with garbage values. 2) Arrays in C/C++ are pointers - when an array is passed to a function, it decays to a pointer and the size is lost. The size must be explicitly passed. 3) Character arrays can store strings and require a null terminator. Modifying a character array modifies any other pointers pointing to the same memory location.

Uploaded by

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

PIC 10A

Lecture 25 array

Arrays
A

long time ago


int a[5]; // Create an array of 5 ints, garbage
values.
// Set the values of the entries
a[0] = 1; a[1] = 2; a[2] = 5;
a[3] = 7; a[4] = 3;
// Print out elements in the array
for(int i=0; i<5; ++i) cout<<a[i]<<, ;
cout<<endl;

C-style arrays
Before

#include <vector>, all we had were arrays. This was


a dark time.

In

general, arrays are as simple a data structure as you can


haveint
while
still resembling a collection of objects.
a[5];

Array declaration
type name[size];
int a[5];
char b[10];
Cat c[7]; // user-defined
class

Array initialization
A

short-hand way of defining an array is using the bracket


notation { }.

int a[5] = {1,3,5,7,9}; // Array of


size 5
int a[] = {1,3,5,7,9}; // Array of
size 5
int a[10] = {1,3,5,7,9}; // Array
of size 10, first 5 values
initialized
to 1,3,5,7,9.
In general,
the input
argument inside the brackets is

optional. If it is larger than the number of elements, the


remaining
elements are
garbage
values.too many initializers.
int
a[3] = {1,3,5,7,9};
// Causes
ERROR,

arrays and pointers


int a[5];
Here

a is simply a special type of pointer. It points


to the first of 5 elements in memory, and its value
(i.e. the location it points to) cannot be changed
once initialized.

A pointer
int a[5];
Actually,
It

array a is a pointer.

points to the first element in


the array.

Address

Value Stored

0034F8D8

(Unknown)

0034F8DC

(Unknown)

0034F8E0

Garbage

0034F8E4

Garbage

0034F8E8

Garbage

0034F8EC

Garbage

0034F8F0

Garbage

0034F8F4

(Unknown)

0034F8F8

(Unknown)

A pointer
int a[5];
Actually,

array a is a pointer.

It

points to the first element in


the array.

And

since a is a pointer, we
can perform arithmetic, so
a+2 points to

Address

Value Stored

0034F8D8

(Unknown)

0034F8DC

(Unknown)

0034F8E0

Garbage

0034F8E4

Garbage

0034F8E8

Garbage

0034F8EC

Garbage

0034F8F0

Garbage

0034F8F4

(Unknown)

0034F8F8

(Unknown)

A pointer
int a[5];
Array

a is a special type of
pointer that we can refer to
but we cannot change the
value of a.

a = a+2; // ERROR!

Address

Value Stored

0034F8D8

(Unknown)

0034F8DC

(Unknown)

0034F8E0

Garbage

0034F8E4

Garbage

0034F8E8

Garbage

0034F8EC

Garbage

0034F8F0

Garbage

0034F8F4

(Unknown)

0034F8F8

(Unknown)

A helper

Address

Value Stored

0034F8D8

(Unknown)

0034F8DC

(Unknown)

0034F8E0

Garbage

0034F8E4

Garbage

0034F8E8

Garbage

0034F8EC

Garbage

0034F8F0

Garbage

int* p = a+3;

0034F8F4

(Unknown)

++p;

0034F8F8

(Unknown)

int a[5];
Even

though array a cannot


change, we can define a nonconst int pointer and assign
and change at will.

++p;

Out of bounds

Address

Value Stored

0034F8D8

(Unknown)

int a[5];

0034F8DC

(Unknown)

0034F8E0

Garbage

int* p = a+3;
++p;
++p; // This is fine as
long as you dont
dereference.
cout<<*p<<endl; // logic
ERROR

0034F8E4

Garbage

0034F8E8

Garbage

0034F8EC

Garbage

0034F8F0

Garbage

0034F8F4

(Unknown)

0034F8F8

(Unknown)

This only causes a runtime error, the compiler


will not catch this.

We

just need to be careful, as before, not to


overstep the bounds of the array.

Same for double


double a[5];
The

same rules apply for array a


as a double.

The

addresses increment by 8
bytes to reflect the larger data
type.

double* p = a+3;
++p;
++p;

Address

Value Stored

0034F8D0

(Unknown)

0034F8D8

(Unknown)

0034F8E0

Garbage

0034F8E8

Garbage

0034F8F0

Garbage

0034F8F8

Garbage

0034F900

Garbage

0034F908

(Unknown)

0034F910

(Unknown)

Using ++p on a double pointer may seem strange,


but it is ok since p is a double* type and NOT of
type double.

The array/pointer duality


In

general, suppose we have a pointer to an array, for example

double a[5];
The

array/pointer duality law says that for each int n,

a[n] == *(a+n)
returns true. In other words, arrays really are just const
pointers and are interpreted as such.

Pass an array to function


Add

void printArray (int a[], int aSize);


[ ] to the variable name.
int main() {
double a[5];
a[0] = 1; a[1] = 2; a[2] = 5; a[3] =
7; a[4] = 3;
printArray(a, 5);
}
void printArray (int a[], int aSize) {
for(int i=0; i<aSize; ++i)
cout<<a[i]<<, ;
cout<<endl;
return;
}

How to access size of array


vector<int> v(10);
Recall

that vectors are classes, so the objects have


properties and can call member functions like v.size(), which
returns the number of elements.
double a[5];

The

pointer itself is not an object, and we cannot call a


similar function like a.size().

We

can, however, use the sizeof(a) function.

How to access size of array


double a[5];
We

used sizeof() previously to see how many bytes were


required to store variables of different data types.
cout<<one double = <<sizeof(a[0])<< bytes\n;
cout<<array of 5 doubles = <<sizeof(a)<<
bytes\n;
cout<<There are <<sizeof(a)/sizeof(a[0])<<
elements\n;

How to access size of arraybut


doesnt work in functions
Unfortunately,

void arraySize(int a[]);

The

int main() {
double a[5];
cout<<one double = <<sizeof(a[0])<<
bytes\n;
cout<<array of 5 doubles = <<sizeof(a)<<
bytes\n;
cout<<When passed in, array has size ;
arraySize(a);
}

the sizeof()
function doesnt work
when we pass an array
into a function.
array gets converted
to an ordinary pointer and
only returns the number
of bytes of a single data
type, in this case 8 bytes.

Usually

we need to pass
the size of the array to
the function!

void arraySize(int a[]) {


cout<<"sizeof(a) = "<<sizeof(a)<<endl;
return;
}
void printArray (int a[], int aSize);

A history lesson
In

old days we didnt have


#include <string>. We had to
use C-strings, which were char
arrays.

char name[] = John;


char

arrays have a \0
character that signifies the
end of the sequence of
characters.

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

0034F8DB

0034F8DC

0034F9DD

\0

0034F9DE

(Unknown)

0034F9DF

(Unknown)

char arrays
char name[] = John;
char refers to the data type of each element
name is the variable name
[] means that name is an array of values.

char arrays
char name[] = John;
John is initially stored as a const char* in some
temporary location in memory.
= copies the characters in John, which is stored in
some temporary location, to the locations pointed to by
array name. So name points to a char J and the
subsequent letters in John are stored consecutively in
memory.
This is a shorthand for
char name[5] = { J, o, h, n, \0};

Shared Memory
string s = Harry;
string t = s;
t[0] = L;

Each

char n[] = Harry;


char* m = n;
m[0] = L;

string is a separate
object, and setting t=s copies
all of the characters from s
into t.
character array, on the other
hand, is defined using
pointers, and so m and n point
to the same character in
memory.

string s = Harry;

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

0034F8DB

0034F8DC

0034F9DD

0034F9F9

(Unknown)

0034F9FA

(Unknown)

0034F9FB

(Unknown)

0034F9FC

(Unknown)

0034F9FD

(Unknown)

0034F9FE

(Unknown)

0034F9FF

(Unknown)

0034FA00

(Unknown)

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

string s = Harry;

0034F8DB

string t = s;

0034F8DC

0034F9DD

0034F9F9

(Unknown)

0034F9FA

0034F9FB

0034F9FC

0034F9FD

0034F9FE

0034FA1A

(Unknown)

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

string s = Harry;

0034F8DB

string t = s;

0034F8DC

0034F9DD

0034F9F9

(Unknown)

0034F9FA

0034F9FB

0034F9FC

0034F9FD

0034F9FE

0034FA1A

(Unknown)

t[0] = L;

char n[] = Harry;

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

0034F8DB

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

(Unknown)

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

char n[] = Harry;

0034F8DB

char* m = n;

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

0034F8D9

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

char n[] = Harry;

0034F8DB

char* m = n;

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

0034F8D9

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

m[0] = L;

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

char n[] = Harry;

0034F8DB

char* m = n;

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

0034F8D9

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

m[0] = L;
m[4] = s;

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

char n[] = Harry;

0034F8DB

char* m = n;

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

0034F8D9

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

m[0] = L;
m[4] = s;
n[3] = x;

Address

Value Stored

0034F8D7

(Unknown)

0034F8D8

(Unknown)

0034F8D9

0034F8DA

char n[] = Harry;

0034F8DB

char* m = n;

0034F8DC

0034F9DD

0034F9DE

\0

0034F9DF

(Unknown)

0034F9E0

0034F8D9

0034F9E1

0034F8D9

0034F9E2

(Unknown)

0034F9E3

(Unknown)

0034F9E4

(Unknown)

0034F9E5

(Unknown)

0034F9E6

(Unknown)

m[0] = L;
m[4] = s;
n[3] = x;
m[3] = y;

What is a const pointer?


We

can mean different things by a const pointer in general.

1.The

pointer cannot change the value of the contents that it is


pointing to.

2.The

pointer itself cannot change value. Whatever location in


memory it initially points to it cannot change value.

3.Both,

the pointer cannot change the contents of memory and it


maintains its initial value.

const int* p
The pointer cannot change the value of the contents
that it is pointing to.
. This follows the standard convention of placing const
in front of a variable type.
1.

int a[] = {2,3,5,7,11,13};


const int* p = a; // p now points to the 2
p=p+2; // This is legal because the const only
applies to the values that p points to.
*p = 5; // ERROR! p doesnt have permission
to change contents of what it is pointing
to.

int* const p
2. The pointer itself cannot change value. Whatever
location in memory it initially points to it cannot
change value.

This is precisely how arrays are handled. The


pointer cannot change to another value but we can
change
the values that it points to.
int a[] = {2,3,5,7,11,13};
int* const p = a; // p now points to the 2
p=p+2; // ERROR. p cannot point to a
different location.
*p = 5; // This is legal, changes a[0] to 5.

const int* const p


3.

Both, the pointer cannot change the contents of


memory and it maintains its initial value.

This is the most restrictive case. Once the pointer is


set is cannot be moved, and cannot change the
contents of the address it points to.
int a[] = {2,3,5,7,11,13};
const int* const p = a; // p now points to the 2
p=p+2; // ERROR. p cannot point to a
different location.
*p = 5; // ERROR, cannot make changes to
contents it is pointing to.

You might also like