Section 15.3 Records (struct
s)
While an array is useful for grouping homogeneous data items that are of the same data type, a record (struct
in C/C++) is used for grouping heterogeneous data items, which may be of the same or different data types. For example, an array is probably better for storing a list of test scores in a program that works with the struct
might be better for storing the coordinates of a point on an struct
are usually called fields. Accessing a field in a struct
also requires two address-related items:
The name of the
struct
, andThe name of the field.
/* structField1.c * Allocates two structs and assigns a value to each field * in each struct. * 2017-09-29: Bob Plantz */ #include <stdio.h> struct theTag { /* "template" for struct */ char aByte; int anInt; char anotherByte; }; int main(void) { struct theTag x; struct theTag y; x.aByte = 'a'; x.anInt = 123; x.anotherByte = 'b'; y.aByte = '1'; y.anInt = 456; y.anotherByte = '2'; printf("x: %c, %i, %c\ny: %c, %i, %c\n", x.aByte, x.anInt, x.anotherByte, y.aByte, y.anInt, y.anotherByte); return 0; }
struct
variables. (C)struct
data type:
struct aTag { /* Define new struct type */ char aByte; int anInt; char anotherByte; };
aTag
. Once a tag has been defined, we create variables of this new data type in the usual way:
struct aTag x; struct aTag y;
struct
variable:
struct { char aByte; int anInt; char anotherByte; } x; struct { char aByte; int anInt; char anotherByte; } y;
struct
as an argument to a function.
Assignment to each of the three fields in the βx
β struct
is accomplished by giving the name of the struct
variable, followed by a dot (.
), followed by the name of the field:
x.aByte = 'a'; x.anInt = 123; x.anotherByte = 'b';
.arch armv6 .file "structField1.c" .section .rodata .align 2 .LC0: .ascii "x: %c, %i, %c\012y: %c, %i, %c\012\000" .text .align 2 .global main .syntax unified .arm .fpu vfp .type main, %function main: @ args = 0, pretend = 0, frame = 24 @ frame_needed = 1, uses_anonymous_args = 0 push {fp, lr} add fp, sp, #4 sub sp, sp, #40 mov r3, #97 strb r3, [fp, #-16] @@ x.abyte = 'a'; mov r3, #123 str r3, [fp, #-12] @@ x.anInt = 123; mov r3, #98 strb r3, [fp, #-8] @@ x.anotherByte = 'b'; mov r3, #49 strb r3, [fp, #-28] @@ y.abyte = '1'; mov r3, #456 str r3, [fp, #-24] @@ y.anInt = 456; mov r3, #50 strb r3, [fp, #-20] @@ y.anotherByte = '2'; ldrb r3, [fp, #-16] @ zero_extendqisi2 mov ip, r3 ldr r2, [fp, #-12] @@ x.anInt ldrb r3, [fp, #-8] @ zero_extendqisi2 mov lr, r3 ldrb r3, [fp, #-28] @ zero_extendqisi2 mov r1, r3 ldr r3, [fp, #-24] ldrb r0, [fp, #-20] @ zero_extendqisi2 str r0, [sp, #8] @@ y.anotherByte str r3, [sp, #4] @@ y.anInt str r1, [sp] @@ y.aByte mov r3, lr @@ x.aByte mov r1, ip @@ x.anotherByte ldr r0, .L3 @@ formatting string bl printf mov r3, #0 mov r0, r3 sub sp, fp, #4 @ sp needed pop {fp, pc} .L4: .align 2 .L3: .word .LC0 .ident "GCC: (Raspbian 6.3.0-18+rpi1) 6.3.0 20170516"
struct
variables. (gcc asm)struct
to the address in the frame pointer to access the respective field. For example, x.aByte = 'a';
is implemented with:
mov r3, #97 strb r3, [fp, #-16]
struct
is relative to the fp
. Shaded areas represent unused memory.
struct
. The offsets are relative to the fp
.struct
in my assembly language solution, Listing 15.3.4.
# structField2.s # Allocates two structs and assigns a value to each field # in each struct, then displays the values. @ 2017-09-29: Bob Plantz @ Define my Raspberry Pi .cpu cortex-a53 .fpu neon-fp-armv8 .syntax unified @ modern syntax @ Constants for assembler .equ aChar,0 @ offsets within .equ anInt,4 @ each .equ anotherChar,8 @ struct .equ y,-36 @ y struct .equ x,-24 @ x struct .equ locals,24 @ space for the structs @ Constant program data .section .rodata .align 2 displayX: .asciz "x fields:\n" displayY: .asciz "y fields:\n" dispAChar: .asciz " aChar = " dispAnInt: .asciz " anInt = " dispOtherChar: .asciz " anotherChar = " @ The program .text .align 2 .global main .type main, %function main: sub sp, sp, 16 @ space for saving regs @ (keeping 8-byte sp align) str r4, [sp, 4] @ save r4 str fp, [sp, 8] @ fp str lr, [sp, 12] @ lr add fp, sp, 12 @ set our frame pointer sub sp, sp, locals @ for the structs @ fill the x struct add r4, fp, x @ address of x struct mov r1, '1 strb r1, [r4, aChar] @ x.aChar = '1': mov r1, 456 str r1, [r4, anInt] @ x.anInt = 456; mov r1, '2 strb r1, [r4, anotherChar] @ x.anotherChar = '2'; @ fill the y struct add r4, fp, y @ address of y struct mov r1, 'a strb r1, [r4, aChar] @ y.aChar = 'a': mov r1, 123 str r1, [r4, anInt] @ y.anInt = 123; mov r1, 'b strb r1, [r4, anotherChar] @ y.anotherChar = 'b'; @ display x struct add r4, fp, x @ address of x struct ldr r0, displayXaddr bl writeStr ldr r0, dispACharAddr @ display aChar bl writeStr ldrb r0, [r4, aChar] bl putChar bl newLine ldr r0, dispAnIntAddr @ display anInt bl writeStr ldr r0, [r4, anInt] bl putDecInt bl newLine ldr r0, dispOtherCharAddr @ display anotherChar bl writeStr ldrb r0, [r4, anotherChar] bl putChar bl newLine @ display y struct add r4, fp, y @ address of y struct ldr r0, displayXaddr bl writeStr ldr r0, dispACharAddr @ display aChar bl writeStr ldrb r0, [r4, aChar] bl putChar bl newLine ldr r0, dispAnIntAddr @ display anInt bl writeStr ldr r0, [r4, anInt] bl putDecInt bl newLine ldr r0, dispOtherCharAddr @ display anotherChar bl writeStr ldrb r0, [r4, anotherChar] bl putChar bl newLine mov r0, 0 @ return 0; add sp, sp, locals @ deallocate local var ldr r4, [sp, 4] @ restore r4 ldr fp, [sp, 8] @ fp ldr lr, [sp, 12] @ lr add sp, sp, 16 @ sp bx lr @ return .align 2 @ addresses of messages displayXaddr: .word displayX displayYaddr: .word displayY dispACharAddr: .word dispAChar dispAnIntAddr: .word dispAnInt dispOtherCharAddr: .word dispOtherChar
struct
variables. (prog asm)struct
. Then I can simply use the offset of each field, relative to this pointer, to access the field:
add r4, fp, x @ address of x struct mov r1, '1 strb r1, [r4, aChar] @ x.aChar = '1': mov r1, 456 str r1, [r4, anInt] @ x.anInt = 456; mov r1, '2 strb r1, [r4, anotherChar] @ x.anotherChar = '2';
struct
can be useful if it is large. Then its address is often used in an array of struct
s or passing a struct
as an argument to a function.