C der Behandlung von Arrays ist sehr verschieden von Java, und Sie werden Ihr Denken entsprechend anpassen müssen. Arrays in C sind keine erstklassigen Objekte (dh ein Array-Ausdruck behält in den meisten Kontexten nicht seine "Array-Ness" bei). In C wird ein Ausdruck vom Typ "N-Element-Array von T
" implizit in einen Ausdruck vom Typ "Zeiger auf T
" konvertiert ("Zerfall") , es sei denn, der Array-Ausdruck ist ein Operand der sizeof
oder unären &
Operatoren oder wenn der Der Array-Ausdruck ist ein String-Literal, mit dem ein anderes Array in einer Deklaration initialisiert wird.
Dies bedeutet unter anderem, dass Sie einen Array-Ausdruck nicht an eine Funktion übergeben und als Array-Typ empfangen lassen können . Die Funktion erhält tatsächlich einen Zeigertyp:
void foo(char *a, size_t asize)
{
// do something with a
}
int bar(void)
{
char str[6] = "Hello";
foo(str, sizeof str);
}
Beim Aufruf von foo
wird der Ausdruck str
vom Typ konvertiertchar [6]
inchar *
, weshalb der erste Parameter von anstelle von foo
deklariert char *a
wird char a[6]
. In sizeof str
Da die Array - Ausdruck ein Operand ist , der sizeof
Bediener, es ist nicht auf einen Zeigertyp umgewandelt, so dass man die Anzahl der Bytes in dem Feld (6) erhalten.
Wenn Sie wirklich interessiert sind, können Sie Dennis Ritchies Die Entwicklung der C-Sprache lesen, um zu verstehen, woher diese Behandlung kommt.
Das Ergebnis ist, dass Funktionen keine Array-Typen zurückgeben können, was in Ordnung ist, da Array-Ausdrücke auch nicht das Ziel einer Zuweisung sein können.
Die sicherste Methode besteht darin, dass der Aufrufer das Array definiert und seine Adresse und Größe an die Funktion übergibt, die darauf schreiben soll:
void returnArray(const char *srcArray, size_t srcSize, char *dstArray, char dstSize)
{
...
dstArray[i] = some_value_derived_from(srcArray[i]);
...
}
int main(void)
{
char src[] = "This is a test";
char dst[sizeof src];
...
returnArray(src, sizeof src, dst, sizeof dst);
...
}
Eine andere Methode besteht darin, dass die Funktion das Array dynamisch zuweist und den Zeiger und die Größe zurückgibt:
char *returnArray(const char *srcArray, size_t srcSize, size_t *dstSize)
{
char *dstArray = malloc(srcSize);
if (dstArray)
{
*dstSize = srcSize;
...
}
return dstArray;
}
int main(void)
{
char src[] = "This is a test";
char *dst;
size_t dstSize;
dst = returnArray(src, sizeof src, &dstSize);
...
free(dst);
...
}
In diesem Fall ist der Aufrufer dafür verantwortlich, die Zuordnung des Arrays zur free
Bibliotheksfunktion aufzuheben.
Beachten Sie, dass dst
der obige Code ein einfacher char
Zeiger auf ein Array von ist char
. Die Zeiger- und Array-Semantik von C ist so, dass Sie den Indexoperator []
entweder auf einen Ausdruck vom Typ Array oder vom Zeigertyp anwenden können . beide src[i]
und dst[i]
greifen auf das i
'th Element des Arrays zu (obwohl nursrc
den Array-Typ hat).
Sie können einen Zeiger auf ein N-Element-Array von deklarieren T
und etwas Ähnliches tun:
char (*returnArray(const char *srcArr, size_t srcSize))[SOME_SIZE]
{
char (*dstArr)[SOME_SIZE] = malloc(sizeof *dstArr);
if (dstArr)
{
...
(*dstArr)[i] = ...;
...
}
return dstArr;
}
int main(void)
{
char src[] = "This is a test";
char (*dst)[SOME_SIZE];
...
dst = returnArray(src, sizeof src);
...
printf("%c", (*dst)[j]);
...
}
Mehrere Nachteile mit den oben genannten. Erstens erwarten ältere Versionen von C SOME_SIZE
eine Konstante für die Kompilierungszeit, was bedeutet, dass die Funktion immer nur mit einer Arraygröße funktioniert. Zweitens müssen Sie den Zeiger dereferenzieren, bevor Sie den Index anwenden, der den Code überfüllt. Zeiger auf Arrays funktionieren besser, wenn Sie mit mehrdimensionalen Arrays arbeiten.