So wissen wir alle, dass das Dateisystem auf Mac OS diese verrückte Eigenschaft hat, vollständig zerlegt UTF-8 zu verwenden. Wenn Sie beispielsweise POSIX-APIs wie realpath()
aufrufen, erhalten Sie eine solche vollständig zerlegte UTF-8-Zeichenfolge von Mac OS zurück. Bei Verwendung von APIs wie scheint es jedoch auch möglich zu sein, vorkompostiertes UTF-8 zu übergeben.Warum erlaubt die C-Laufzeit unter Mac OS sowohl vorkomposiertes als auch zerlegtes UTF-8?
Hier ist ein kleines Demo-Programm, das versucht, eine Datei mit dem Namen ä
zu öffnen. Der erste Aufruf an übergibt eine vorkompilierte UTF-8-Zeichenfolge, der zweite Aufruf übergibt eine zerlegte UTF-8-Zeichenfolge und zu meiner Überraschung funktionieren beide. Ich würde erwarten, dass nur der zweite funktioniert, aber auch vorkomposiertes UTF-8 funktioniert.
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *fp, *fp2;
fp = fopen("\xc3\xa4", "rb"); // ä as precomposed UTF-8
fp2 = fopen("\x61\xcc\x88", "rb"); // ä as decomposed UTF-8
printf("CHECK: %p %p\n", fp, fp2);
if(fp) fclose(fp);
if(fp2) fclose(fp2);
return 0;
}
Nun zu meinen Fragen:
Ist das definierte Verhalten? d. h. ist es erlaubt, vorkompostierte UTF-8 an POSIX-APIs weiterzugeben oder sollte ich immer zerlegtes UTF-8 passieren?
Wie können Funktionen wie sogar wissen, ob die übergebene Datei vorkomposiertes oder zerlegtes UTF-8 enthält? Könnte dies nicht sogar zu allen möglichen Problemen führen, z.B. falsche Dateien geöffnet werden, weil die übergebene Zeichenfolge auf zwei verschiedene Arten interpretiert werden kann und somit möglicherweise auf zwei verschiedene Dateien verweist? Das verwirrt mich etwas.
EDIT
die Verwirrung komplett zu machen, dieses seltsame Verhalten scheint nicht einmal E/A-Datei beschränkt. Werfen Sie einen Blick auf diesen Code:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("\xc3\xa4\n");
printf("\x61\xcc\x88\n");
return 0;
}
Beide printf
Anrufe tun genau das gleiche, das heißt, sie beide drucken den Charakter ä
, der erste Anruf mit vorverfasstes UTF-8 und die zweite mit zerlegten UTF-8. Es ist wirklich komisch.
Ich nehme an, * dass der Pfad immer auf der Dateisystemebene HFS + zerlegt ist, also ist es egal, was Sie übergeben. –
Das Dateisystem ist auch case insensitive, nicht wahr? Dies wäre dasselbe wie die falschen Buchstaben an "fopen" zu übergeben. Der interne Mechanismus zur Suche nach einem Dateinamen behandelt wahrscheinlich beide Fälle auf die gleiche Weise. –
Aber was kam 'readdir' zurück? –