Vorlesung 9 Flashcards

1
Q

Arrays

A
  • Arrays (Felder, Vektoren) dienen zum Speichern einer festen Anzahl von
    Werten gleichen Typs.
  • Anwendungsbeispiele:
  • Vektoren, Matrizen
  • Liste von Namen
  • Syntax (Definition eines Arrays):
    Datentyp Bezeichner[Elementanzahl];
  • Beispiel:
    float vektor[3];
    short int a, b[10], c;
  • Die Elementanzahl muss positiv sein.
  • Ungeeignet, wenn die Anzahl der Daten unbekannt ist, dann muss
    dynamische Speicherverwaltung verwendet werden.
  • Durch die Definition eines Arrays werden so viele Variablen erzeugt, wie das
    Array Elemente hat.
  • int b[10] erzeugt:
  • Variablenname b für Zugriff auf das gesamte Array
  • Variablennamen für Zugriff auf die einzelnen Elemente:
    b[0], b[1], …, b[9]
  • Die Indizierung beginnt immer bei 0.
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
2
Q

Arrays im Speicher

A

Elemente werden geordnet, direkt hintereinander im Speicher abgelegt.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
3
Q

Speicherbedarf von Arrays

A
  • Speicherbedarf: Elementanzahl · Größe des Datentyps
  • Beispiele:
  • int wert[250]; braucht z.B. 4 · 250 = 1000 Byte
  • double wert[1000]; braucht z.B. 8 · 1000 = 8000 Byte
  • Vorsicht:
  • Der gesamte Speicher für die Arrays wird erst zur Laufzeit angefordert.
  • Bei zu großen Arrays oder lokal definierte Arrays kann es
    Probleme geben (siehe Stack, später).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
4
Q

Zeichenketten als char-Arrays

A
  • Eine der wichtigsten Anwendungen von Arrays ist die Darstellung und
    Verarbeitung von Zeichenfolgen (Strings / Text).
  • Zeichenfolgen treten meist auf bei
  • Ein- und Ausgabe (Benutzerschnittstellen)
  • Verarbeitung von Text-Dateien
  • In C gibt es keinen Datentyp String, stattdessen werden
    char-Arrays verwendet.
  • Die Standardbibliotheken von C enthalten eine Menge Funktionen für
    Zeichenketten (später mehr dazu).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
5
Q

Darstellung von Zeichenfolgen

A

Eine String-Literal wird intern als char-Array dargestellt.
● Die Länge ist um 1 größer als die Anzahl der Zeichen in der
Stringkonstanten.
● Zusatzfeld für die Speicherung von des Null-Zeichens ‘\0’, welches das
Ende des Strings anzeigt

  • Wenn man eine Zeichenfolge bearbeitet, muss man immer prüfen, ob das
    aktuelle Zeichen das ‘\0’-Zeichen ist.
  • Vorsicht: Fehler, wenn das Null-Zeichen mitten in einem String vorkommt
    (z.B. bei der Konkatenation zweier Strings).
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
6
Q

Initialisierung von Arrays

A
  • Automatische Initialisierung wie bei Variablen:
  • globale Arrays werden mit 0 initialisiert
  • lokale Arrays werden nicht automatisch initialisiert
  • Manuelle Initialisierung erfolgt durch Anhängen einer Liste
    von Werten

int vector1[5] = {6, -4, 6, 2, -1};
int vector2[5] = {6, -6, 2};
int vector3[] = {3, -5, 7, 2, -1};
char hello[6] = {‘h’, ‘e’, ‘l’, ‘l’, ‘o’, ‘\0’};
char str[] = “hello world\n”;

  • Listenwerte dürfen Literale und Variablen sein.
    int vector1[5] = {6, -4, 6, 2, -1};
  • Es dürfen auch weniger Elemente in der Liste stehen als die angegebene
    Elementenanzahl, die übrigen Elemente bleiben uninitialisiert, bzw. werden
    bei globalen Variablen mit 0 initialisiert.
    int vector2[5] = {6, -6, 2};
  • Implizite Längenbestimmung:
  • Die Größe des Feldes wird der Anzahl der Initialisierungswerte gleichgesetzt.
  • Häufigste Verwendung ist das Initialisieren von Stringkonstanten
    wie im Beispiel str.
    int vector3[] = {3, -5, 7, 2, -1};
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
7
Q

Zugriff auf Array-Elemente

A
  • Syntax: name [arrayindex];
  • arrayindex kann ein beliebiger nichtnegativer Ausdruck sein, der zur Laufzeit
    ausgewertet wird, z.B. Laufvariablen einer Schleife
  • Die Indizierung beginnt immer bei 0.
  • Beispiel:
    int a, v[] = {1,2,3};
    a = v[1]; &laquo_space;a wird zu 2
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
8
Q

Prüfung von Bereichsgrenzen

A
  • Keine Prüfung, ob arrayindex in den zugelassenen Grenzen liegt! Zugriffe auf
    beliebige Speicherinhalte möglich (Speicherorganisation)
  • Zugriff auf Werte außerhalb der Grenzen:
  • lesend: Programm arbeitet mit falschen Werten. Die Fehlerquelle schwer
    lokalisierbar, evtl. Programmabsturz durch Speicherschutz des Betriebssystems.
  • schreibend: Wenn die Abweichung groß ist, wird ggfs. Programmcode
    überschrieben. Bei Betriebssystemen ohne Speicherschutz führt dies zum
    Crash, bei UNIX-Rechnern wird der Absturz verhindert (Segmentation fault,
    eigenes Programm wird beendet, andere laufen weiter), ebenso auf
    Windows-Systemen
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
9
Q

Arrays backstage

A
  • Die Variable für den gesamten Array ist intern nichts anderes als ein Zeiger.
  • Der Zugriff auf ein Element des Arrays wird über die
    Adressarithmetik gesteuert.
  • folgende Ausdrücke sind gleichbedeutend:
    s = vektor[3];
    s = *(vektor+3);
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
10
Q

Arrays als Funktionsparameter

A

● Bei der Parameterübergabe eines Arrays wird lediglich die Startadresse des
Feldes übergeben (Zeigerübergabe).
● Änderungen der Elemente des Arrays sind daher auch in der aufrufenden
Umgebung sichtbar.
● Beispiel: Bei scanf wird nicht die Adresse des char-Arrays übergeben,
sondern die Array-Variable selbst:

char str[100];
scanf(“%s”, str);

int i;
scanf(“%d”, &i);

● Häufig soll eine Funktion mit Feldern unterschiedlicher Größe
korrekt arbeiten.
● Daher: Bei Funktionsdefinition braucht die Größe nicht angegeben werden
(für mehrdimensionale Felder stimmt dies nicht, folgt später):
● Vorsicht: Gefahr ungültiger Speicherzugriffe!
* Größe des Feldes unter Umständen in der Funktion nicht bekannt, muss dann
als separater Parameter übergeben werden

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
11
Q

Funktion zum Vergleich von Arrays

A

include <string.h></string.h>

  • Vergleich mittels der Funktion memcmp aus string.h
    (schneller als manuell)
  • Parameter: die zu vergleichenden Arrays, sowie die Anzahl von Bytes, die
    verglichen werden sollen
  • Ergebnis: 0, wenn Arrays gleich sind


int v1[3] = {1,2,3}, v2[3] = {4,5,6};
if(0 == memcmp(v1, v2, 3 * sizeof(int)))
printf(“v1 gleich v2\n”);
else
printf(“v1 nicht gleich v2\n”);

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
12
Q

Funktion zum Kopieren von Arrays

A
  • Zuweisung mittels der Funktion memcpy aus string.h
    (schneller als manuell)
  • Parameter: Ziel-Array, Quell-Array, sowie die Anzahl von Bytes,
    die zugewiesen werden sollen

beispiel:
#include <string.h>
...
int v1[3] = {1,2,3}, v2[3];
memcpy(v2, v1, 3 * sizeof(int));</string.h>

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
13
Q

Mehrdimensionale Arrays

A
  • Mehrdimensionale Arrays dienen zum Aufbau von Tabellen, Matrizen und
    ähnlichen Strukturen.
  • Syntax der Definition:
  • Datentyp Bezeichner[Anzahl 1][Anzahl 2]…;
  • Beispiel (Matrix mit 2 Zeilen und 3 Spalten):
    short int matrix[2][3];
  • Syntax des Zugriffs:
    Name[Array-Index 1][Array-Index 2]…;
  • Beispiel (Zugriff):
    x = matrix[1][2];
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
14
Q

Initialisierung von mehrdimensionalen Arrays

A
  • Initialisierung analog zu eindimensionalen Arrays.
  • Sowohl Zeilen als auch Spalten dürfen unvollständig sein.
  • Arraygröße muss nicht angegeben werden.
    int matrix[3][5] = { { 6,-4, 6, 2,-1},
    { 2, 3,-1, 9,-3},
    {-1, 4,-8, 0, 3} };
How well did you know this?
1
Not at all
2
3
4
5
Perfectly
15
Q

Mehrdimensionale Arrays als Funktionsparameter

A

● Bei Funktionsdefinition braucht die erste Dimension nicht angegeben werden,
die anderen müssen angegeben werden.
void drucke_namen(char namen[][256], int count)
● Mit Zeigern kann aber auch dies umgangen werden.

How well did you know this?
1
Not at all
2
3
4
5
Perfectly
16
Q

Deklaration von Arrays

A
  • C90 Standard
  • Breite Unterstützung, nahezu alle C Compiler
  • Größe eines Arrays muss zum Zeitpunkt der Übersetzung feststehen.
  • Folgendes Beispiel geht nach diesem Standard nicht, da die Größe erst zur
    Laufzeit bestimmt wird:
    int size;
    scanf(“%d”, &size);
    double a[size];
  • C99 Standard
  • Lokale Arrays dürfen mit Variable deklariert werden, d.h. obiges Beispiel
    wäre gültig.
17
Q

sizeof Operator bei Arrays

A

● sizeof Operator liefert auch bei Arrays den belegten Platz in Byte, dividiert
durch die Größe eines Elements erhält man so die Elementanzahl

double b[1000];
printf(“b hat %d Elemente\n”, sizeof(b) / sizeof(double));

18
Q

memcpy und memmove

A

● Funktionsdefinitionen in string.h
● Kopierfunktionen (1):
* void *memcpy(void *dest, const void *src, size_t n);
* void *memmove(void *dest, const void *src, size_t n);
* kopieren n Bytes, Speicherbereiche dürfen sich bei memcpy nicht überlappen
● Auch für andere Arrays als Strings anwendbar
● Achtung: das Stringende-Zeichen \0 wird nicht beachtet!

● Beispiel:
char text1[] = “Hamburg ist eine tolle Stadt!”;
char text2[] = “Bottrop”;
memcpy(text1, text2, 7);
printf(“%s\n”, text1);
#include <string.h></string.h>

19
Q

strcpy und strncpy Funktionen für Zeichenketten

A

● Kopierfunktionen (2):
* char *strcpy(char *dest, const char *src);
* kopiert Zeichenkette inklusive abschließendem ‘\0’
* char *strncpy(char *dest, const char *src, size_t n);
* kopiert maximal n Zeichen, ggf. wird mit Nullen aufgefüllt
* Vorsicht: hat src keine Null in den ersten n Zeichen, ist dest nicht
Nullterminiert!

char text1[100] = “C-Programmieren macht Spaß!”;
char text2[100] = “Bottrop hat eine tolle Hochschule!”;
strcpy(text2, text1);
printf(“%s\n”, text2);

20
Q

strcat und strncat Funktionen für Zeichenketten

A

● Aneinanderhängen von Zeichenketten:
* char *strcat(char *dest, const char *src);
* hängt die Zeichenkette src hinten an dest an
* char *strncat(char *dest, const char *src, size_t n);
* hängt maximal n Zeichen der Zeichenkette src hinten an dest an, fügt
\0 hinzu
* Achtung: Die Zielzeichenkette muss genügend Platz für beide Zeichenketten
und das abschließende \0 haben!

char text1[100] = “Bottrop ist eine tolle Stadt”;
char text2[] = “ und hat eine tolle Hochschule!”;
strcat(text1, text2);
printf(“%s\n”, text1);

21
Q

strcmp, strncmp, memcp Funktionen für Zeichenketten

A

Vergleichsfunktionen:
* int strcmp(const char *s1, const char *s2);
* Vergleicht zwei mit \0 terminierte Zeichenketten
* int strncmp(const char *s1, const char *s2, size_t n);
* Vergleicht zwei mit \0 terminierte Zeichenketten, maximal n Zeichen
* int memcmp(const void *s1, const void *s2, size_t n);
* Vergleicht die ersten n Zeichen von zwei beliebigen Arrays
* Rückgabewert für alle drei Funktionen:
* < 0, wenn s1 kleiner als s2 (d.h. alphabetisch s1 vor s2 kommt, wenn nur
Buchstaben A-Z verwendet werden)
* > 0, wenn s1 größer als s2 (d.h. alphabetisch s1 nach s2 kommt, wenn nur
Buchstaben A-Z verwendet werden)
* 0, wenn s1 gleicher Inhalt wie s2

char str1[101];
char str2[101];
printf(“Text 1: “);
scanf(“%100s”, str1);
printf(“Text 2: “);
scanf(“%100s”, str2);
int c = strcmp(str1, str2);
if(c > 0) {
printf(“%s kommt nach %s\n”, str1, str2);
} else if(c < 0) {
printf(“%s kommt vor %s\n”, str1, str2);
} else {
printf(“%s gleich %s\n”, str1, str2);
}

22
Q

*strchr und *strrchr und *strpbrk und *strstr Funktionen für Zeichenketten

A

● Suchfunktionen:
* char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
Rückgabewert: Zeiger auf erstes/letztes Auftreten von c in s
* char *strpbrk(const char *s, const char *accept);
Rückgabewert: Zeiger auf erstes Auftreten eines der Zeichen aus accept in s
* char *strstr(const char *haystack,
const char *needle);
Rückgabewert: Zeiger auf erstes Auftreten von needle in haystack
char str1[] = “Heute ist ein toller Tag!”;
char *str2;
str2 = strstr(str1, “ein”);
printf(str2);

23
Q

strlen und memset Funktionen für Zeichenketten

A

● Länge einer Zeichenkette:
size_t strlen(const char *s);
Rückgabewert: Länge der Zeichenkette s
● Auffüllen eines Feldes:
void *memset(void *s, int c, size_t n);
Füllt die ersten n Bytes von s mit c.
● Weitere Funktionen in string.h (siehe Literatur):
– strspn strcspn
strerror strtok
memchr

24
Q

puts gets fgets Funktionen für Zeichenketten

A

● Funktionsdefinitionen in stdio.h
● Ein-/Ausgabe von Zeichenketten:
* int puts(char *s);
* schreibt die Zeichenkette s und einen nachfolgenden Zeilenumbruch auf den Bildschirm
* char *gets(char *s);
* liest eine Zeichenkette und speichert sie in s. Das Return der Eingabe wird in \0
umgewandelt.
* Vorsicht: Wenn eingegebener Text länger ist als der Speicherplatz von s, wird über das
Ende von s hinaus in den Speicher geschrieben => Sicherheitsrisiko. Daher besser
folgende Funktion verwenden:
* char *fgets(char *s, int size, FILE *stream);
* Für stream verwende stdin, Details im Kapitel Dateioperationen
* Liest bis zum Zeilenumbruch, aber maximal size-1 Zeichen
* \n bleibt erhalten, fügt \0 am Ende an

25
Q

Formatiert in Strings schreiben, sprintf

A
  • Syntax: int sprintf(char* str, const char * format, …);
  • sprintf schreibt formatiert in den String str.
  • Syntax analog zu printf.
  • Achtung: Buffer overflow vermeiden!

int n = 12;
float f = 3.1234f;

char s[64];
sprintf(s, “%03d, %.2f”, n, f);

printf(“%s”, s);

return 0;

26
Q

Zeichenketten in Zahlen wandeln

A

Funktionsdefinitionen in stdlib.h
● Zeichenkette in Ganzzahl umwandeln
int atoi(const char *s)
long atol(const char *s)
long strtol(const char *s, char **endp, int base)
unsigned long strtoul(const char *s, char **endp, int base)
● Zeichenkette in Gleitkommazahl umwandeln
double atof(const char *s)
double strtod(const char *s, char **endp)
● Beschreibung
* wandelt Zeichenkette bis zum ersten nichtnumerischen Zeichen
* liefert 0, wenn kein numerisches Zeichen
* s: Zeichenkette
* endp: zeigt auf erstes Zeichen, das nicht konvertiert wurde
* base: Basis des Zahlsystems (2-36, 0 automatische Erkennung)

27
Q

Eigene Datentypen

A
  • C erlaubt die Definition von eigenen Datentypen.
  • Ziel: Bessere Lesbarkeit von Programmen
  • In C
  • Aufzählungstypen (enum)
  • Typdefinition (typedef)
28
Q

Aufzählungstypen

A
  • Aufzählungstypen können für Variablen definiert werden, denen nur wenige
    verschiedene Werte zugewiesen werden sollen.
  • Syntax:
  • enum TypName {Bez1, Bez2, …} [Var1, Var2, …];
  • Die Variablennamen sind optional.

enum tier {hund, katze, maus} t;
t = hund;

enum farbe {rot=5, blau};

enum farbe f;
f = blau;

  • Interne Umsetzung:
  • Aufzählungstyp ist int
  • Wenn nicht anders festgelegt, werden Bezeichner durch Werte 0, 1, …
    repräsentiert (Reihenfolge in der Definition ist wichtig!)
  • Vorteil:
  • Aussagekräftige Bezeichner machen die Programme lesbarer
    und übersichtlicher.
  • Nachteil:
  • Typfremde Zuweisungen an Aufzählungstypen werden meist vom Compiler
    nicht erkannt.
  • Nur für kleine Wertebereiche anwendbar.
29
Q

Typdefinitionen

A
  • Ein bestehender Datentyp bekommt einen neuen,
    alternativen Namen.
  • Syntax:
  • typedef Typ TypName;

enum e_farbe {rot, blau, gruen, gelb};
typedef enum e_farbe farbe;
farbe f;
f = gelb;

Wichtige Anwendungsbereiche:
* Bessere Lesbarkeit großer Programme
* Bessere Portierbarkeit eines Programms, da nur die abstrakten Datentypen an die
neue Umgebung angepasst werden müssen

30
Q

Datenstrukturen

A

Bisher: elementare Datentypen
● Jetzt: Datenstrukturen zur Speicherung logisch zusammenhängender Daten.
● Beispiel:
* Szenario: Die Verwaltung einer Firma speichert Daten wie Name, Nachname,
Geburtsdatum, Adresse usw., eines jeden Angestellten.
* Wie kann man diese Daten übersichtlich speichern?
* Für jeden Angestellten wird z.B. eine Karteikarte angelegt.
● Datenstrukturen sind Abbildungen solcher Karteikarten auf den Speicher.

31
Q

Strukturierte Datentypen in C

A

Arrays (Felder) geordnete Folge von Werten des gleichen Datentyps

Strukturen fassen Daten unterschiedlichen Typs zusammen

Bitfelder Ähnlich zu Strukturen, jedoch mit der Möglichkeit,
Speicherbedarf zu reduzieren

Unions enthalten eines von mehreren Datenelementen

32
Q

Strukturen: Ziel und Definition

A

● Beispiel: ein Kunde wird durch Namen und Adresse sowie Kundennummer
definiert.
● Ziel: Zusammenfassung der Attribute mit unterschiedlichem Datentypen in
einem neuen Datentyp.
● Syntax:
struct [Typname] {
Komponente1;
[Komponente2; …]
} [VarName1, …];

Beispiel (Typdefinition und eine Variable):
struct s_kunde {
char vorname[50];
char nachname[50];
int kundennummer;
} k1;

Beispiel (spätere Variablendeklaration):
struct s_kunde k2;

● Beispiel (struct und typedef)
typedef struct s_kunde kunde;

kunde k3;

33
Q

Operationen mit Strukturen

A
  • Zulässige Operationen
  • Übergabe an Funktionen als Parameter (call by value!)
  • Rückgabe einer Struktur aus einer Funktion
  • Zuweisungsoperator für gesamte Struktur (Kopie wird erzeugt)
  • Adress- und sizeof-Operator
  • Elementzugriffsoperator: Punkt (.)
  • Beispiel (Elementzugriff):
    kunde1.kundennummer = 1001;

printf(“Name: %s %s\n”,
kunde1.vorname,
kunde1.nachname);

Die Attribute einer Struktur können direkt bei der Deklaration gesetzt werden
struct Spieler {
char name[50];
int alter;
long punktzahl;
};

struct Spieler bob = {“Bob”, 12, 20000};

Strukturen: Ein größeres Beispiel

typedef struct s_datum {
int tag, monat, jahr;
} datum;
typedef struct s_kunde {
char vorname[50];
char nachname[50];
datum erster_einkauf;
int kundennummer;
} kunde;

kunde meine_kunden[100];

meine_kunden[42].erster_einkauf.jahr = 2002;
strcpy(meine_kunden[42].vorname, “Peter”);
strcpy(meine_kunden[42].nachname, “Kopitzke”);

anfangsbuchstabe = meine_kunden[42].nachname[0];

34
Q

Zeiger auf Strukturen / Operator ->

A
  • Der Operator -> erlaubt den Zugriff auf Inhalte von Strukturen
    über Zeiger.

typedef struct s_kunde {
char name[64];
int alter;
} kunde;
kunde k1;
kunde *zeiger = &k1;

  • Normalerweise: (*zeiger).alter = 20;
  • Besser: zeiger->alter = 20;
35
Q

Bitfelder

A
  • Bitfelder sind eine Spezialform von Strukturen.
  • Ziel: Verringerung des Speicherbedarfs und leichterer Zugriff auf
    einzelne Bits.
  • Syntax analog zu struct, hinter jedes Element wird die Anzahl der
    benötigten Bits geschrieben.
  • Beispiel für Bitfeld (1 Byte groß):

struct zeichen {
unsigned char data:7;
unsigned char parity:1;
};

  • Achtung: Das Bitfeld belegt mindestens so viel Speicher wie der größte
    enthaltene Datentyp.
36
Q

Unions: Definition

A
  • Syntax analog zu Strukturen, Schlüsselwort union statt struct
  • Es wird jedoch nur einer der Werte gespeichert.
  • Speicherbedarf der Union richtet sich nach dem größten Element.
  • Beispiel:

union typen {
int i;
double d;
} u;
u.i = 5;
u.d = 2.3; «u.i ist nun undefiniert

37
Q

Unions: Anwendungsbereiche

A

include <stdio.h></stdio.h>

● Einsparen von Speicherplatz: wenn sichergestellt ist, dass manche
Informationen nicht gleichzeitig gespeichert werden müssen.
● Maschinennahe Manipulation: Interpretation eines Speicherbereichs durch
verschiedene Datentypen (z.B. um auf Gleitkommazahlen auch
Bitmanipulationen durchführen zu können).
Achtung: Solche Programme sind i.d.R. nicht portierbar!
● Bessere Lesbarkeit

beispiel:

union floatAndInt
{
float f;
int i;
} zahl;
printf(“sizeof float: %d, int: %d\n”, sizeof(float), sizeof(int));
printf(“Zahl: “);
scanf(“%f”, &zahl.f);
int j;
int l = 8*sizeof(int);
printf(“Die interne binäre Darstellung ist: “);
for(j = l-1; j >= 0; j–) {
printf(“%d”, (zahl.i&raquo_space; j)&1);
}
printf(“\n”);

beispiel:

union vec3d {
struct { float x, y, z; };
struct { float alpha, beta, gamma; };
float value[3];
};
int main()
{
union vec3d v;

v.x = 2;
v.y = 3;
v.z = 4;
printf(“%f %f %f\n”, v.x, v.y, v.z);

// Alternative 1
v.alpha = 4;
v.beta = 5;
v.gamma = 6;
printf(“%f %f %f\n”, v.alpha, v.beta, v.gamma);
// Alternative 2
v.value[0] = 7;
v.value[1] = 8;
v.value[2] = 9;
printf(“%f %f %f\n”, v.value[0], v.value[1], v.value[2]);
return 0;
}

38
Q
A