C stdio字符编码

Fer*_*eak 5 c c++ character-encoding

对于我的宠物项目,我正在尝试字符串表示,但我得到了一些令人不安的结果.首先,这是一个简短的应用程序:

#include <stdio.h>
#include <stddef.h>
#include <string.h>
void write_to_file(FILE* fp, const char* c, size_t len)
{
    void* t = (void*)c;
    fwrite(&len, sizeof(size_t), 1, fp);
    fwrite(t, len, sizeof(char), fp);
}
int main()
{
    FILE* fp = fopen("test.cod", "wb+");
    const char* ABCDE = "ABCDE";
    write_to_file(fp, ABCDE, strlen(ABCDE) );
    const char* nor = "BBøæåBB";
    write_to_file(fp, nor, strlen(nor));
    const char* hun = "AA??éáöüúBB";
    write_to_file(fp, hun, strlen(hun));
    const char* per = "CC???CC";
    write_to_file(fp, per, strlen(per));
    fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)

它没有什么特别的,只需要一个字符串,并将它的长度和字符串本身写入文件.现在,该文件在被视为十六进制时看起来像:

标准字符*输出的十六进制转储

我很满意第一个结果,5(前8个字节,我在64位机器上)如预期的那样.但是,nor我期望的变量有7个字符(因为那是我在那里看到的),但是C库认为它有0x0A(即:10个)字符(第二行,0A以及另外8个字符).字符串本身包含双字符(ø编码为C3 B8等等......).

对于hunper变量也是如此.

我用Unicode做了同样的实验,以下是应用程序:

#include <stdio.h>
#include <stddef.h>
#include <string.h>
void write_to_file(FILE* fp, const wchar_t* c, size_t len)
{
    void* t = (void*)c;
    fwrite(&len, sizeof(size_t), 1, fp);
    fwrite(t, len, sizeof(wchar_t), fp);
}

int main()
{
    FILE* fp = fopen("test.cod", "wb+");
    const wchar_t* ABCDE = L"ABCDE";
    write_to_file(fp, ABCDE, wcslen(ABCDE) );
    const wchar_t* nor = L"BBøæåBB";
    write_to_file(fp, nor, wcslen(nor));
    const wchar_t* hun = L"AA??éáöüúBB";
    write_to_file(fp, hun, wcslen(hun));
    const wchar_t* per = L"CC???CC";
    write_to_file(fp, per, wcslen(per));
    fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)

这里的结果是预期的结果.5为长度为ABCDE7的长度BBøæåBB等等,每个字符4个字节...

whcar_t*输出的十六进制转储

所以这里有一个问题:标准C库的编码是什么,以及在开发可移植应用程序时它是多么可信(即:我在平台上写的内容将在另一个上正确读回?)以及其他什么建议考虑上面提到的内容.

use*_*290 5

据我所知,标准C库根本不进行编码.我想在第一种情况下你的输入文件使用UTF-8作为编码,因此你的字符串常量最终将作为编译代码中的UTF-8字符串常量.这就是为什么你得到长度为10个字符的字符串.

fwrite将(无类型)字节数组作为参数.由于它对处理的字节一无所知,因此根本不能进行任何编码转换.

关于可移植性,你应该更加小心指针长度等事情.fwrite(&len, sizeof(size_t), 1, fp)可以在不同平台上产生不同的结果,可能导致您的文件被错误地读取.另外(特别是对于多字节编码)你必须小心平台的字节序.

对于其他任何事情,您可以确定,您的标准库会将字节精确地放入磁盘,但在将它们作为文本处理时,您必须确保在所有平台上使用相同的编码.