Visual C++ 和 u8 前缀

visual C++ and u8 prefix

我在 visual studio 预览版中编写了一个 HTTP 服务器,我添加 <meta charset="utf-8"> 以使用 UTF-8 作为内容编码。

问题是当我在字符串文字上使用 u8 prefix 时,浏览器看起来有编码错误。

当我删除 u8 前缀时,浏览器会正确显示。

为什么?

并且我的文档保存为 utf-8(代码页 65001)

u8前缀的字符串

不带 u8 前缀的字符串

编辑

更新示例代码

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment (lib, "ws2_32.lib")

#define U8

#ifdef U8
typedef const char8_t c;
c str[] = u8"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<h1>\xf0\x9f\x93\x9d</h1>";
#else
typedef const char c;
c str[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<h1>\xf0\x9f\x93\x9d</h1>";
#endif

template <ULONG N>
constexpr ULONG cstrlen(c(&)[N]) {
    return N - 1;
}

int main() {
    WSADATA wsaData;
    SOCKET listener, s;
    CHAR buf[1024 * 3];
    WSABUF wsabuf{ .len = sizeof(buf), .buf = buf };
    DWORD bytes, flags = 0;
    const char* err = "?";
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
        err = "WSAStartup";
        goto Err;
    }
    {
        struct addrinfo hints = {};
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
        struct addrinfo* result;
        if (getaddrinfo(NULL, "80", &hints, &result)) {
            err = "getaddrinfo";
            goto Err;
        }
        listener = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
        if (listener == INVALID_SOCKET) {
            freeaddrinfo(result);
            err = "WSASocket";
            goto Err;
            
        }
        if (bind(listener, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
            freeaddrinfo(result);
            err = "bind";
            closesocket(listener);
            goto Err;
        }
        freeaddrinfo(result);
        if (listen(listener, SOMAXCONN) == SOCKET_ERROR) {
            err = "listen";
            closesocket(listener);
            goto Err;
        }
    }
    puts("Ready...");
    for (;;) {
        s = WSAAccept(listener, NULL, NULL, NULL, NULL);
        if (s == INVALID_SOCKET) {
            closesocket(listener);
            err = "WSAAccept";
            goto Err;
        }
        wsabuf.len = sizeof(buf);
        wsabuf.buf = buf;
        bytes = flags = 0;
        if (WSARecv(s, &wsabuf, 1, &bytes, &flags, NULL, NULL) == SOCKET_ERROR) {
            err = "WSARecv";
            goto Err;
        }
        wsabuf.buf = (char*)str;
        wsabuf.len = cstrlen(str);
        if (WSASend(s, &wsabuf, 1, &bytes, 0, NULL, NULL)) {
            err = "WSASend";
            closesocket(s);
            goto Err;
        }
        closesocket(s);
    }
    return 0;
Err:
    puts(err);
    WSACleanup();
    return 1;
}

运行 与 std=c++20

感谢@AlanBirtles,使用\u文字解决了我的问题。

u8u8 都适用于 \U0001f4dd

更新代码

#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#pragma comment (lib, "ws2_32.lib")

#define U8

#ifdef U8
typedef const char8_t c;
c str[] = u8"HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<h1>\U0001f4dd</h1>";
#else
typedef const char c;
c str[] = "HTTP/1.1 200 OK\r\nContent-Type: text/html; charset=utf-8\r\n\r\n<h1>\U0001f4dd</h1>";
#endif const char c;

template <ULONG N>
constexpr ULONG cstrlen(c(&)[N]) {
    return N - 1;
}

int main() {
    WSADATA wsaData;
    SOCKET listener, s;
    CHAR buf[1024 * 3];
    WSABUF wsabuf{ .len = sizeof(buf), .buf = buf };
    DWORD bytes, flags = 0;
    const char* err = "?";
    if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
        err = "WSAStartup";
        goto Err;
    }
    {
        struct addrinfo hints = {};
        hints.ai_family = AF_INET;
        hints.ai_socktype = SOCK_STREAM;
        hints.ai_protocol = IPPROTO_TCP;
        hints.ai_flags = AI_PASSIVE;
        struct addrinfo* result;
        if (getaddrinfo(NULL, "80", &hints, &result)) {
            err = "getaddrinfo";
            goto Err;
        }
        listener = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED | WSA_FLAG_NO_HANDLE_INHERIT);
        if (listener == INVALID_SOCKET) {
            freeaddrinfo(result);
            err = "WSASocket";
            goto Err;
        }
        if (bind(listener, result->ai_addr, (int)result->ai_addrlen) == SOCKET_ERROR) {
            freeaddrinfo(result);
            err = "bind";
            closesocket(listener);
            goto Err;
        }
        freeaddrinfo(result);
        if (listen(listener, SOMAXCONN) == SOCKET_ERROR) {
            err = "listen";
            closesocket(listener);
            goto Err;
        }
    }
    puts("Ready...");
    for (;;) {
        s = WSAAccept(listener, NULL, NULL, NULL, NULL);
        if (s == INVALID_SOCKET) {
            closesocket(listener);
            err = "WSAAccept";
            goto Err;
        }
        wsabuf.len = sizeof(buf);
        wsabuf.buf = buf;
        bytes = flags = 0;
        if (WSARecv(s, &wsabuf, 1, &bytes, &flags, NULL, NULL) == SOCKET_ERROR) {
            err = "WSARecv";
            goto Err;
        }
        wsabuf.buf = (char*)str;
        wsabuf.len = cstrlen(str);
        if (WSASend(s, &wsabuf, 1, &bytes, 0, NULL, NULL)) {
            err = "WSASend";
            closesocket(s);
            goto Err;
        }
        closesocket(s);
    }
    return 0;
Err:
    puts(err);
    WSACleanup();
    return 1;
}