Thread u.a. Adressierungsoperator (7 answers)
Opened by RPerl at 2007-10-27 19:18

murphy
 2007-10-27 21:45
#101480 #101480
User since
2004-07-19
1776 Artikel
HausmeisterIn
[Homepage]
user image
Es ist eigentlich klar, warum der Code genau das tut, was Du beschreibst: sprintf bekommt als ersten Parameter einen Puffer, nicht eine Speicherstelle wo eine neu allozierte Zeichenkette abgelegt werden soll. Und printf bekommt als Zeichenkettenargumente ebenfalls die Puffer übergeben, nicht Zeiger darauf. Du machst also zwei Fehler, die sich teilweise wieder aufheben ;-)

Mit char *str[1024]; deklarierst Du ein Feld von 1024 Zeigern auf Zeichen, dann aber sagst Du mittels sprintf(&str[0], ...); "Nimm das erste Element des Feldes str -- also den ersten Zeiger -- berechne seine Adresse, konvertiere diese Adresse implizit vom Typ Zeiger auf Zeiger auf Zeichen in den Typ Zeiger auf Zeichen und speichere dort die Zeichenkette, die sprintf berechnet". Das ist -- wegen der Typkonversion -- eine komische Anweisung, die Dein Compiler vermutlich auch angemeckert hätte, wenn Du vorsichtigerweise mit eingeschalteten Warnungen kompiliert hättest.

Bei der sprintf(&str[1], ...); Anweisung schreibst Du dann Daten ab dem zweiten Element in das Feld str, also auf einer 32bit Maschine 4 Bytes vom Anfang des Feldes entfernt. Daher erklärt sich die Überlappung der Zeichenketten um 4 Zeichen bei der Ausgabe.

Bei der Ausgabe machst Du nun konsequenterweise denselben Typisierungsfehler, weshalb das ganze -- zumindest halbwegs -- funktioniert.

Das Programm verhält sich genau so, wie es sollte, allerdings verletzt Du hier die strikte Typisierung der Zeiger, was schlechter Stil ist, und Du führst keinerlei Überprüfungen von Zeichenkettenlängen durch, um Pufferüberläufe zu verhindern, was noch viel schlechterer Stil ist.

Eigentlich meintest Du wohl viel eher so etwas wie
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
#define FMT "INSERT INTO data (v1, v2, v3, v4) VALUES ('%s', '%s', '%s', '%s')"
#define NSTMTS 3
#define BUFSIZE 1024

int i;
char stmts[NSTMTS][BUFSIZE];

for (i = 0; i < NSTMTS; i++) {
/* ... get data into the array f ... */
assert(snprintf(stmts[i], BUFSIZE, FMT, f[0], f[1], f[2], f[3]) < BUFSIZE - 1);
}

oder vielleicht mit dynamischer Allokation
Code: (dl )
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define FMT "INSERT INTO data (v1, v2, v3, v4) VALUES ('%s', '%s', '%s', '%s')"
#define NSTMTS 3

int i;
char *stmts[NSTMTS];

for (i = 0; i < NSTMTS; i++) {
size_t s;
char *p;

/* ... get data into the array f ... */
s = snprintf(NULL, 0, FMT, f[0], f[1], f[2], f[3]) + 1;
assert((p = (char *)malloc(s)) != NULL);

snprintf(p, s, FMT, f[0], f[1], f[2], f[3]);
}

/* ... do something with the statements ... */

for (i = 0; i < NSTMTS; i++)
free(stmts[i]);
When C++ is your hammer, every problem looks like your thumb.

View full thread u.a. Adressierungsoperator