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

07 Arrays

Uploaded by

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

07 Arrays

Uploaded by

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

University of Washington

Roadmap Memory & data


Integers & floats
Machine code & C
C: Java:
x86 assembly
car *c = malloc(sizeof(car)); Car c = new Car(); Procedures & stacks
c->miles = 100; c.setMiles(100);
Arrays & structs
c->gals = 17; c.setGals(17);
float mpg = get_mpg(c); float mpg =
Memory & caches
free(c); c.getMPG(); Processes
Virtual memory
Assembly get_mpg: Memory allocation
language: pushq %rbp Java vs. C
movq %rsp, %rbp
...
popq %rbp
ret
OS:
Machine 0111010000011000
100011010000010000000010
code: 1000100111000010
110000011111101000011111

Computer
system:

Autumn 2013 Arrays & structs 1


University of Washington

Data Structures in Assembly


¢ Arrays
§ One-dimensional
§ Multi-dimensional (nested)
§ Multi-level
¢ Structs
§ Alignment
¢ Unions

Autumn 2013 Arrays & structs 2


University of Washington

Array Allocation
¢ Basic Principle
§ T A[N];
§ Array of data type T and length N
§ Contiguously allocated region of N * sizeof(T) bytes
char string[12];

x x + 12
int val[5];

x x+4 x+8 x + 12 x + 16 x + 20
double a[3];

x x+8 x + 16 x + 24
char* p[3]; IA32
(or char *p[3];)
x x+4 x+8 x + 12

x86-64
x x+8 x + 16 x + 24
Autumn 2013 Arrays & structs 3
University of Washington

Array Access
¢ Basic Principle
§ T A[N];
§ Array of data type T and length N
§ Identifier A can be used as a pointer to array element 0: Type T*

int val[5]; 9 8 1 9 5
x x+4 x+8 x + 12 x + 16 x + 20

¢ Reference Type Value


§ val[4] int
§ val int *
§ val+1 int *
§ &val[2] int *
§ val[5] int
§ *(val+1) int
Autumn 2013
§ val + i int * Arrays & structs 4
University of Washington

Array Access
¢ Basic Principle
§ T A[N];
§ Array of data type T and length N
§ Identifier A can be used as a pointer to array element 0: Type T*

int val[5]; 9 8 1 9 5
x x+4 x+8 x + 12 x + 16 x + 20

¢ Reference Type Value


§ val[4] int 5
§ val int * x
§ val+1 int * x+4
§ &val[2] int * x+8
§ val[5] int ?? (whatever is in memory at address x + 20)
§ *(val+1) int 8
Autumn 2013
§ val + i int * x + 4*i Arrays & structs 5
University of Washington

Array Example
typedef int zip_dig[5];

zip_dig cmu = { 1, 5, 2, 1, 3 };
zip_dig uw = { 9, 8, 1, 9, 5 }; initialization
zip_dig ucb = { 9, 4, 7, 2, 0 };

int uw[5] …

Autumn 2013 Arrays & structs 6


University of Washington

Array Example
typedef int zip_dig[5];

zip_dig cmu = { 1, 5, 2, 1, 3 };
zip_dig uw = { 9, 8, 1, 9, 5 };
zip_dig ucb = { 9, 4, 7, 2, 0 };

zip_dig cmu; 1 5 2 1 3
16 20 24 28 32 36
zip_dig uw ; 9 8 1 9 5
36 40 44 48 52 56
zip_dig ucb; 9 4 7 2 0
56 60 64 68 72 76

¢ Declaration “zip_dig uw” equivalent to “int uw[5]”


¢ Example arrays happened to be allocated in successive 20 byte blocks
§ Not guaranteed to happen in general
Autumn 2013 Arrays & structs 7
University of Washington

Array Accessing Example


zip_dig uw; 9 8 1 9 5
36 40 44 48 52 56

int get_digit
(zip_dig z, int dig)
{
return z[dig];
} n Register %edx contains
starting address of array
IA32 n Register %eax contains
# %edx = z array index
# %eax = dig n Desired digit at
movl (%edx,%eax,4),%eax # z[dig] 4*%eax + %edx
n Use memory reference
(%edx,%eax,4)
Autumn 2013 Arrays & structs 8
University of Washington

Referencing Examples
zip_dig cmu; 1 5 2 1 3
16 20 24 28 32 36
zip_dig uw; 9 8 1 9 5
36 40 44 48 52 56
zip_dig ucb; 9 4 7 2 0
56 60 64 68 72 76

¢ Reference Address Value Guaranteed?


uw[3] 36 + 4* 3 = 48 9 Yes
uw[6] 36 + 4* 6 = 60 4 No
uw[-1] 36 + 4*-1 = 32 3 No
cmu[15] 16 + 4*15 = 76 ?? No
§ No bounds checking
§ Location of each separate array in memory is not guaranteed

Autumn 2013 Arrays & structs 9


University of Washington

Array Loop Example


int zd2int(zip_dig z)
{
zi = 10*0 + 9 = 9 int i;
int zi = 0;
for (i = 0; i < 5; i++) {
zi = 10*9 + 8 = 98 zi = 10 * zi + z[i];
}
zi = 10*98 + 1 = 981 return zi;
}

zi = 10*981 + 9 = 9819

zi = 10*9819 + 5 = 98195

9 8 1 9 5
Autumn 2013 Arrays & structs 10
University of Washington

Array Loop Example


int zd2int(zip_dig z)
{
¢ Original int i;
int zi = 0;
for (i = 0; i < 5; i++) {
zi = 10 * zi + z[i];
}
return zi;
}
¢ Transformed int zd2int(zip_dig z)
§ Eliminate loop variable i, {
use pointer zend instead int zi = 0;
int *zend = z + 4;
§ Convert array code to do {
pointer code zi = 10 * zi + *z;
§ Pointer arithmetic on z z++;
§ Express in do-while form } while (z <= zend);
return zi;
(no test at entrance)
}
Autumn 2013 Arrays & structs 11
University of Washington

Array Loop Implementation (IA32)


¢ Registers int zd2int(zip_dig z)
{
%ecx z
int zi = 0;
%eax zi int *zend = z + 4;
%ebx zend do {
¢ Computations zi = 10 * zi + *z;
z++;
§ 10*zi + *z implemented as } while(z <= zend);
*z + 2*(5*zi) return zi;
§ z++ increments by 4 }

# %ecx = z
xorl %eax,%eax # zi = 0
leal 16(%ecx),%ebx # zend = z+4
.L59:
leal (%eax,%eax,4),%edx # zi + 4*zi = 5*zi
movl (%ecx),%eax # *z
addl $4,%ecx # z++
leal (%eax,%edx,2),%eax # zi = *z + 2*(5*zi)
cmpl %ebx,%ecx # z : zend
jle .L59 # if <= goto loop
Autumn 2013 Arrays & structs 12
University of Washington

Nested Array Example


zip_dig sea[4] = Remember, T A[N] is
{{ 9, 8, 1, 9, 5 }, an array with elements
{ 9, 8, 1, 0, 5 }, of type T, with length N
{ 9, 8, 1, 0, 3 },
{ 9, 8, 1, 1, 5 }};

same as: What is the layout in memory?


int sea[4][5];

Autumn 2013 Arrays & structs 13


University of Washington

Nested Array Example


zip_dig sea[4] = Remember, T A[N] is
{{ 9, 8, 1, 9, 5 }, an array with elements
{ 9, 8, 1, 0, 5 }, of type T, with length N
{ 9, 8, 1, 0, 3 },
{ 9, 8, 1, 1, 5 }}; sea[3][2];

9 8 1 9 5 9 8 1 0 5 9 8 1 0 3 9 8 1 1 5

76 96 116 136 156

¢ “Row-major” ordering of all elements


¢ Guaranteed (in C)

Autumn 2013 Arrays & structs 14


University of Washington

Two-Dimensional (Nested) Arrays


¢ Declaration A[0][0] • • • A[0][C-1]
§ T A[R][C];
• •
§ 2D array of data type T
• •
§ R rows, C columns • •
§ Type T element requires K bytes
A[R-1][0] • • • A[R-1][C-1]
¢ Array size?

Autumn 2013 Arrays & structs 15


University of Washington

Two-Dimensional (Nested) Arrays


¢ Declaration A[0][0] • • • A[0][C-1]
§ T A[R][C];
• •
§ 2D array of data type T
• •
§ R rows, C columns • •
§ Type T element requires K bytes
A[R-1][0] • • • A[R-1][C-1]
¢ Array size
§ R * C * K bytes
¢ Arrangement
§ Row-major ordering
int A[R][C];
A A A A A A
[0] • • • [0] [1] • • • [1] • • • [R-1] • • • [R-1]
[0] [C-1] [0] [C-1] [0] [C-1]

4*R*C Bytes
Autumn 2013 Arrays & structs 16
University of Washington

Nested Array Row Access


¢ Row vectors
§ T A[R][C]: A[i] is array of C elements
§ Each element of type T requires K bytes
§ Starting address A + i * (C * K)

int A[R][C];

A[0] A[i] A[R-1]

A A A A A A
[0] ••• [0] • • • [i] ••• [i] • • • [R-1] ••• [R-1]
[0] [C-1] [0] [C-1] [0] [C-1]

A A+i*C*4 A+(R-1)*C*4

Autumn 2013 Arrays & structs 17


University of Washington

Nested Array Row Access Code


int *get_sea_zip(int index) int sea[4][5] =
{ {{ 9, 8, 1, 9, 5 },
return sea[index]; { 9, 8, 1, 0, 5 },
} { 9, 8, 1, 0, 3 },
{ 9, 8, 1, 1, 5 }};

¢ What data type is sea[index]?


¢ What is its starting address?

Autumn 2013 Arrays & structs 18


University of Washington

Nested Array Row Access Code


int* get_sea_zip(int index) int sea[4][5] =
{ {{ 9, 8, 1, 9, 5 },
return sea[index]; { 9, 8, 1, 0, 5 },
} { 9, 8, 1, 0, 3 },
{ 9, 8, 1, 1, 5 }};

¢ What data type is sea[index]?


¢ What is its starting address?

# %eax = index
leal (%eax,%eax,4),%eax # 5 * Translation?
index
leal sea(,%eax,4),%eax # sea + (20 * index)

Autumn 2013 Arrays & structs 19


University of Washington

Nested Array Row Access Code


int *get_sea_zip(int index) int sea[4][5] =
{ {{ 9, 8, 1, 9, 5 },
return sea[index]; { 9, 8, 1, 0, 5 },
} { 9, 8, 1, 0, 3 },
{ 9, 8, 1, 1, 5 }};

# %eax = index
leal (%eax,%eax,4),%eax # 5 * index
leal sea(,%eax,4),%eax # sea + (20 * index)

¢ Row Vector
§ sea[index] is array of 5 ints
§ Starting address sea+20*index
¢ IA32 Code
§ Computes and returns address
§ Compute as sea+4*(index+4*index)=sea+20*index
Autumn 2013 Arrays & structs 20
University of Washington

Nested Array Row Access

int A[R][C];

A[0] A[i] A[R-1]

A A A A A
[0] ••• [0] • • • ••• [i] ••• • • • [R-1] ••• [R-1]
[0] [C-1] [j] [0] [C-1]

A A + i*C*4 A + (R-1)*C*4

?
Autumn 2013 Arrays & structs 21
University of Washington

Nested Array Row Access


¢ Array Elements
§ A[i][j] is element of type T, which requires K bytes
§ Address A + i * (C * K) + j * K = A + (i * C + j)* K

int A[R][C];

A[0] A[i] A[R-1]

A A A A A
[0] ••• [0] • • • ••• [i] ••• • • • [R-1] ••• [R-1]
[0] [C-1] [j] [0] [C-1]

A A + i*C*4 A + (R-1)*C*4

A + i*C*4 + j*4
Autumn 2013 Arrays & structs 22
University of Washington

Nested Array Element Access Code


int get_sea_digit int sea[4][5] =
(int index, int dig) {{ 9, 8, 1, 9, 5 },
{ { 9, 8, 1, 0, 5 },
return sea[index][dig]; { 9, 8, 1, 0, 3 },
} { 9, 8, 1, 1, 5 }};

# %ecx = dig
# %eax = index
leal 0(,%ecx,4),%edx # 4*dig
leal (%eax,%eax,4),%eax # 5*index
movl sea(%edx,%eax,4),%eax # *(sea + 4*dig + 20*index)

¢ Array Elements
§ sea[index][dig] is int
§ Address: sea + 20*index + 4*dig
¢ IA32 Code
§ Computes address sea + 4*dig + 4*(index+4*index)
§ movl performs memory reference
Autumn 2013 Arrays & structs 23
University of Washington

Strange Referencing Examples

zip_dig
sea[4]; 9 8 1 9 5 9 8 1 0 5 9 8 1 0 3 9 8 1 1 5

76 96 116 136 156

¢ Reference Address Value Guaranteed?


sea[3][3] 76+20*3+4*3 = 148 1 Yes
sea[2][5] 76+20*2+4*5 = 136 9 Yes
sea[2][-1] 76+20*2+4*-1 = 112 5 Yes
sea[4][-1] 76+20*4+4*-1 = 152 5 Yes
sea[0][19] 76+20*0+4*19 = 152 5 Yes
sea[0][-1] 76+20*0+4*-1 = 72 ?? No
¢ Code does not do any bounds checking
¢ Ordering of elements within array guaranteed

Autumn 2013 Arrays & structs 24


University of Washington

N-dimensional arrays…

double heatMap3D[1024][1024][1024];

total size in bytes?


1024*1024*1024*8 = 8,589,934,592 = roughly 8GB

&heapMap3D[300][800][2] = ?

in bytes: base + 300*1024*1024*8 + 800*1024*8 + 2*8


= base + 8*(2 + 1024*(800+ 1024*(300)))
= base + 2,523,136,016
Autumn 2013 Arrays & structs 25
University of Washington

Multi-Level Array Example


int cmu[5] = { 1, 5, 2, 1, 3 };
int uw[5] = { 9, 8, 1, 9, 5 };
int ucb[5] = { 9, 4, 7, 2, 0 };

int* univ[3] = {uw, cmu, ucb};

int univ2D[3] = {
{ 9, 8, 1, 9, 5 },
{ 1, 5, 2, 1,
{ 9, 4, 7, 2,
3
0
},
}
Same thing as a 2D array?
};

No. One array declaration = one contiguous block of memory.


Autumn 2013 Arrays & structs 26
University of Washington

Multi-Level Array Example


¢ Variable univ denotes
int cmu[5] = { 1, 5, 2, 1, 3 };
int uw[5] = { 9, 8, 1, 9, 5 };
array of 3 elements
int ucb[5] = { 9, 4, 7, 2, 0 }; ¢ Each element is a pointer
§ 4 bytes
int* univ[3] = {uw, cmu, ucb};
¢ Each pointer points to array
of ints
cmu
1 5 2 1 3
univ
16 20 24 28 32 36
160 36 uw
9 8 1 9 5
164 16
168 60 ucb 36 40 44 48 52 56
9 4 7 2 0
60 64 68 72 76 80

Note: this is how Java represents multi-dimensional arrays.


Autumn 2013 Arrays & structs 27
University of Washington

Element Access in Multi-Level Array


cmu
1 5 2 1 3
int get_univ_digit univ
16 20 24 28 32 36
(int index, int dig) 160 36 uw
9 8 1 9 5
{ 164 16
36 40 44 48 52 56
60 ucb
return univ[index][dig]; 168
9 4 7 2 0

} 60 64 68 72 76 80

# %ecx = index
# %eax = dig
leal 0(,%ecx,4),%edx # 4*index
movl univ(%edx),%edx # Mem[univ+4*index]
movl (%edx,%eax,4),%eax # Mem[...+4*dig]

¢ Computation (IA32)
§ Element access Mem[Mem[univ+4*index]+4*dig]
§ Must do two memory reads
§ First get pointer to row array
§ Then access element within array
Autumn 2013 Arrays & structs 28
University of Washington

Array Element Accesses


Nested array Multi-level array
int get_sea_digit int get_univ_digit
(int index, int dig) (int index, int dig)
{ {
return sea[index][dig]; return univ[index][dig];
} }
cmu
1 5 2 1 3
univ
16 20 24 28 32 36
160 36 uw
9 8 1 9 5
164 16
ucb 36 40 44 48 52 56
168 60
9 4 7 2 0

60 64 68 72 76 80

Access looks similar, but it isn’t:


Mem[sea+20*index+4*dig] Mem[Mem[univ+4*index]+4*dig]

Autumn 2013 Arrays & structs 29


University of Washington

Strange Referencing Examples


cmu
1 5 2 1 3
univ
16 20 24 28 32 36
160 36 uw
9 8 1 9 5
164 16
168 60 ucb 36 40 44 48 52 56
9 4 7 2 0
60 64 68 72 76 80

¢ Reference Address Value Guaranteed?


univ[2][3] 60+4*3 = 72 2 Yes
univ[1][5] 16+4*5 = 36 9 No
univ[2][-2] 60+4*-2 = 52 5 No
univ[3][-1] #@%!^?? ?? No
univ[1][12] 16+4*12 = 64 4 No
§ Code does not do any bounds checking
§ Location of each lower-level array in memory is not guaranteed
Autumn 2013 Arrays & structs 30
University of Washington

Using Nested Arrays


#define N 16
typedef int fix_matrix[N][N];

/* Compute element i,k of


fixed matrix product */
int fix_prod_ele
(fix_matrix a, fix_matrix b,
int i, int k)
{
int j;
int result = 0;
for (j = 0; j < N; j++)
result += a[i][j]*b[j][k];
return result;
}

Autumn 2013 Arrays & structs 31


University of Washington

Using Nested Arrays: arrays of arrays


#define N 16
¢ Strengths typedef int fix_matrix[N][N];

§ Generates very efficient /* Compute element i,k of


assembly code fixed matrix product */
int fix_prod_ele
§ Avoids multiply in index
(fix_matrix a, fix_matrix b,
computation int i, int k)
{
int j;
¢ Limitation int result = 0;
§ Only works for fixed array size for (j = 0; j < N; j++)
result += a[i][j]*b[j][k];
return result;
}

a b k-th column
x
i-th row
Autumn 2013 Arrays & structs 32
University of Washington

Dynamic Nested Arrays:


arrays of pointers to arrays
¢ Strength int * new_var_matrix(int n)
{
§ Can create matrix of any size return (int *)
¢ Programming calloc(sizeof(int), n*n);
}
§ Must do index computation
explicitly int var_ele
(int *a, int i, int j, int n)
¢ Performance {
§ Accessing single element costly return a[i*n+j];
§ Must do multiplication }

movl 12(%ebp),%eax # i
movl 8(%ebp),%edx # a
imull 20(%ebp),%eax # n*i
addl 16(%ebp),%eax # n*i+j
movl (%edx,%eax,4),%eax # Mem[a+4*(i*n+j)]

Autumn 2013 Arrays & structs 33


University of Washington

Arrays in C
¢ Contiguous allocations of memory
¢ No bounds checking
¢ Can usually be treated like a pointer to first element
¢ int a[4][5] => array of arrays
§ all levels in one contiguous block of memory
¢ int* b[4] => array of pointers to arrays
§ first level in one contiguous block of memory
§ parts anywhere in memory

Autumn 2013 Arrays & structs 34


University of Washington

Structures
struct rec { Memory Layout
int i;
int a[3]; i a p
int* p; 0 4 16 20
};

¢ Characteristics
§ Contiguously-allocated region of memory
§ Refer to members within structure by names
§ Members may be of different types

Autumn 2013 Arrays & structs 35


University of Washington

Structures
struct rec {
¢ Accessing Structure Member int i;
int a[3];
§ Given an instance of the struct, we can use
int* p;
the . operator, just like Java: };
§ struct rec r1; r1.i = val;
§ What if we have a pointer to a struct: struct rec* r = &r1;

Autumn 2013 Arrays & structs 36


University of Washington

Structures
struct rec {
¢ Accessing Structure Member int i;
int a[3];
§ Given an instance of the struct, we can use
int* p;
the . operator, just like Java: };
§ struct rec r1; r1.i = val;
§ What if we have a pointer to a struct: struct rec* r = &r1;
§ Using * and . operators: (*r).i = val;
§ Or, use -> operator for short: r->i = val;
§ Pointer indicates first byte of structure; access members with offsets

void
set_i(struct rec* r, IA32 Assembly
int val) # %eax = val
{ # %edx = r
r->i = val; movl %eax,0(%edx) # Mem[r+0] = val
}

Autumn 2013 Arrays & structs 37


University of Washington

Generating Pointer to Structure Member


struct rec {
int i; r r+4+4*idx
int a[3];
int* p; i a p
};
0 4 16 20

¢ Generating Pointer to int* find_address_of_elem


Array Element (struct rec* r, int idx)
§ Offset of each structure {
member determined return &r->a[idx];
}
at compile time

&(r->a[idx])
# %ecx = idx
# %edx = r
leal 0(,%ecx,4),%eax # 4*idx
leal 4(%eax,%edx),%eax # r+4*idx+4
Autumn 2013 Arrays & structs 38
University of Washington

Generating Pointer to Structure Member


struct rec {
int i; r r+4+4*idx
int a[3];
int* p; i a p
};
0 4 16 20

¢ Generating Pointer to int* find_address_of_elem


Array Element (struct rec* r, int idx)
§ Offset of each structure {
member determined return &r->a[idx];
}
at compile time

&(r->a[idx])
# %ecx = idx OR
# %edx = r
leal 4(%edx,%ecx,4),%eax # r+4*idx+4

Autumn 2013 Arrays & structs 39


University of Washington

Accessing to Structure Member


struct rec {
int i; r r+4+4*idx
int a[3];
int* p; i a p
};
0 4 16 20

¢ Reading Array Element int* find_address_of_elem


§ Offset of each structure (struct rec* r, int idx)
member still determined {
at compile time return &r->a[idx];
}

# %ecx = idx
# %edx = r
movl 4(%edx,%ecx,4),%eax # Mem[r+4*idx+4]

Autumn 2013 Arrays & structs 40


University of Washington

Structures & Alignment


¢ Unaligned Data struct S1 {
char c;
c v i double v;
p p+1 p+9 p+13 int i;
} * p;

¢ How would it look like if data items were aligned (address


multiple of type size) ?

Autumn 2013 Arrays & structs 41


University of Washington

Structures & Alignment


¢ Unaligned Data struct S1 {
char c;
c v i double v;
p p+1 p+9 p+13 int i;
} * p;

¢ Aligned Data
§ Primitive data type requires K bytes
§ Address must be multiple of K

c 7 bytes v i
p+0 p+8 p+16 p+20

Multiple of 8 Multiple of 4

internal fragmentation
Autumn 2013 Arrays & structs 42
University of Washington

Alignment Principles
¢ Aligned Data
§ Primitive data type requires K bytes
§ Address must be multiple of K
¢ Aligned data is required on some machines; it is advised
on IA32
§ Treated differently by IA32 Linux, x86-64 Linux, Windows, Mac OS X, …
¢ What is the motivation for alignment?

Autumn 2013 Arrays & structs 43


University of Washington

Alignment Principles
¢ Aligned Data
§ Primitive data type requires K bytes
§ Address must be multiple of K
¢ Aligned data is required on some machines; it is advised
on IA32
§ Treated differently by IA32 Linux, x86-64 Linux, Windows, Mac OS X, …
¢ Motivation for Aligning Data
§ Physical memory is accessed by aligned chunks of 4 or 8 bytes (system-
dependent)
§ Inefficient to load or store datum that spans these boundaries
§ Also, virtual memory is very tricky when datum spans two pages (later…)
¢ Compiler
§ Inserts padding in structure to ensure correct alignment of fields
§ sizeof() should be used to get true size of structs
Autumn 2013 Arrays & structs 44
University of Washington

Specific Cases of Alignment (IA32)


¢ 1 byte: char, …
§ no restrictions on address
¢ 2 bytes: short, …
§ lowest 1 bit of address must be 02
¢ 4 bytes: int, float, char *, …
§ lowest 2 bits of address must be 002
¢ 8 bytes: double, …
§ Windows (and most other OSs & instruction sets): lowest 3 bits 0002
§ Linux: lowest 2 bits of address must be 002
§ i.e., treated liked 2 contiguous 4-byte primitive data items

Autumn 2013 Arrays & structs 45


University of Washington

Saving Space
¢ Put large data types first:
struct S1 { struct S2 {
char c; double v;
double v; int i;
int i; char c;
} * p; } * q;

¢ Effect (example x86-64, both have K=8)


c 7 bytes v i
p+0 p+8 p+16 p+20

v i c But actually…
q+0 q+8 q+12 q+13

Autumn 2013 Arrays & structs 46


University of Washington

Struct Alignment Principles

¢ Size must be a multiple of the largest primitive type inside.

K=8 so size mod 8 = 0

c 7 bytes v i
p+0 p+8 p+16 p+20

v i c 3 bytes
q+0 q+8 q+12 q+16

Autumn 2013 Arrays & structs 47


University of Washington

Arrays of Structures
¢ Satisfy alignment requirement struct S2 {
for every element double v;
int i;
¢ How would accessing an element work? char c;
} a[10];

a[0] a[1] a[2] •••


a+0 a+16 a+32 a+48

v i c 3 bytes
a+16 a+24 a+28 a+32

Autumn 2013 Arrays & structs


external fragmentation 48
University of Washington

Unions
¢ Allocated according to largest element
¢ Can only use one member at a time
union U {
char c;
int i[2]; c
double v; i[0] i[1]
} *up;
v
struct S { up+0 up+4 up+8
char c;
int i[2];
double v;
} *sp;

c 3 bytes i[0] i[1] 4 bytes v


sp+0 sp+4 sp+8 sp+16 sp+24
Autumn 2013 Arrays & structs 49
University of Washington

What Are Unions Good For?


¢ Unions allow the same region of memory to be referenced as
different types
§ Different “views” of the same memory location
§ Can be used to circumvent C’s type system (bad idea)
¢ Better idea: use a struct inside a union to access some
memory location either as a whole or by its parts
¢ But watch out for endianness at a small scale…
¢ Layout details are implementation/machine-specific…
union int_or_bytes {
int i;
struct bytes {
char b0, b1, b2, b3;
}
Autumn 2013
} Arrays & structs 50
University of Washington

Unions For Embedded Programming


typedef union
{
unsigned char byte;
struct {
(Note: the placement of these
unsigned char b0:1;
unsigned char b1:1; fields and other parts of this
unsigned char b2:1; example are implementation-
unsigned char b3:1; dependent)
unsigned char reserved:4;
} bits;
} hw_register;

hw_register reg;
reg.byte = 0x3F; // 001111112
reg.bits.b2 = 0; // 001110112
reg.bits.b3 = 0; // 001100112
unsigned short a = reg.byte;
printf("0x%X\n", a); // output: 0x33

Autumn 2013 Arrays & structs 51


University of Washington

Summary
¢ Arrays in C
§ Contiguous allocations of memory
§ No bounds checking
§ Can usually be treated like a pointer to first element
¢ Structures
§ Allocate bytes in order declared
§ Pad in middle and at end to satisfy alignment
¢ Unions
§ Provide different views of the same memory location

Autumn 2013 Arrays & structs 52

You might also like

pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy