Mit strncpy() kopieren const char *
Ich bin sehr neu in C, ich bin stecken mit der strncpy-Funktion.\
Hier ist ein Beispiel was, mit dem ich arbeite:
int main()
{
const char *s = "how";
struct test {
char *name;
};
struct test *t1 = malloc(sizeof(struct test));
strncpy(t1->name, s, sizeof(*s));
t1->name[NAMESIZE] = '\0';
printf("%s\n", t1->name);
}
Ich habe ein const char *, ich brauche, um die "name" - Wert test, um den const char. Ich habe eine wirklich harte Zeit, herauszufinden dieses heraus. Ist das überhaupt der richtige Ansatz?
Vielen Dank!
- Wo soll man beginnen...
- Sehr gut gesagt 😀
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gut, Sie ordnen die Struktur, nicht aber die Zeichenfolge innen der Struktur. Sie müssen das tun, bevor Sie kopieren, um es. Auch wenn Sie tun, werden Sie wahrscheinlich überschreiben nicht zugewiesenen Arbeitsspeicher, wenn Sie versuchen, die string-terminator.
Und durch eine hohe Zufuhr ow Wein, ich habe gerade bemerkt, dass Sie eigentlich nur kopieren ein Zeichen, aber es ist immer noch Undefiniertes Verhalten.
sizeof(*s)
1 ist, so ist es das gleiche wiesizeof(char)
die angegeben ist in der C-Spezifikation gleich eins ist. Sie sollten wahrscheinlich verwenden Siestrlen(s) + 1
.malloc(sizeof(struct test))
ordnet die Struktur, einschließlich der char* drin, aber es hat nicht den Speicher, wo der char* wird sich zeigen. Wenn Sie möchten, verwenden Sie die Zeichenfolge selbst (im Gegensatz zu den Zeiger darauf), die Sie benötigen, um alloc neuen Speicher.strncpy(t1->name, s, sizeof(*s));
nur kopieren ein Zeichen?char
, dereferenzierens
(was*s
tut), gibt Sie einen einzelnenchar
, und die Größe einer einzelnenchar
ist immer1
.strlen(s)*sizeof(char)
?strlen
ist genug, es gibt Sie die Anzahl der Zeichen in der Zeichenfolge.sizeof(har)
definiert wird, in der C-Spezifikation zurück1
immer.Nehmen wir diesen einen Schritt zu einem Zeitpunkt:
diese reserviert Speicherplatz für einen
struct test
; genug Platz für die Zeigername
, aber nicht alle Speicher für den pointer zu Punkt zu. Zumindest, werden Sie wollen, um Folgendes zu tun:Wenn dies erledigt ist, können Sie fortfahren, um kopieren Sie die Zeichenfolge. Jedoch, Sie bereits berechnete die Länge der Schnur einmal um den Speicher, es gibt keinen Sinn, es zu tun, wieder implizit durch den Aufruf
strncpy
. Führen Sie stattdessen folgende Schritte:In der Regel versuchen, verwenden Sie dieses basic pattern; berechnen Sie die Länge der Zeichenfolgen einmal, wenn Sie kommen in Ihre code -, aber dann verwenden Sie die explizite dimensionierten Pufferspeicher und die
mem*
Operationen statt implizite-Länge-Zeichenfolgen mitstr*
Operationen. Es ist mindestens so sicher (und oft auch sicherer) und effizienter, wenn es richtig gemacht.Könnten Sie
strncpy
wennt1->name
wurde ein array fester Größe statt (obwohl viele Menschen es vorziehen, zu verwendenstrlcpy
). Das würde wie folgt Aussehen:Beachten Sie, dass die
size
argumentstrncpy
sollte immer der Größe der Ziel, nicht die Quelle, zu vermeiden, schreiben die außerhalb der Grenzen des Ziel-Puffer.MAXSIZE - 1
imstrncpy
"Optimierung jenseits aller Vernunft"? 🙂Ohne jeden Versuch, die Vollständigkeit oder die pädagogische Leitung, hier ist eine version des Codes, die funktionieren sollte. Sie können das Spiel "finde den Unterschied" und Suche nach einer Erklärung für jedes separat auf dieser Website.
strlen
, um die Berechnung der Größe eines solchen strings.test::name
dynamisch, siehe Stephen ' s beantworten, aber vergessen Sie nicht, sauber, getrennt.strncpy() ist immer falsch
Statt, Sie kann verwenden, memcpy() oder strcpy (oder in deinem Fall sogar strdup() )
memcpy
müsstest du erstmal das über die ganze Länge der (möglichst großen) string. Mitstrncpy
zahlen Sie eventuell ein paar zusätzliche unnötige Nullen, aber nie mehr als die (kurze) Ziel Länge.snprintf(dest, dest_size, "%s", src);
ist ein standard und macht-was-Sie-erwarten-Ersatz fürstrncpy
.