sprintf 原始字节到 C 中的字符串?

sprintf raw bytes to string in C?

我正在用 C(使用 HTTP)通过网络发送一些原始字节。我目前是这样做的:

// response is a large buffer
int n = 0; // response length
int x = 42; // want client to read x
int y = 43; // and y 

// write a simple HTTP response containing a 200 status code then x and y in binary format
strcpy(response, "HTTP/1.1 200\r\n\r\n");
n += 16; // status line we just wrote is 16 bytes long
memcpy(response + n, &x, sizeof(x));
n += sizeof(x);
memcpy(response + n, &y, sizeof(y));
n += sizeof(y);
write(client, response, n);

在 JavaScript 中,然后我使用如下代码读取此数据:

request = new XMLHttpRequest();
request.responseType = "arraybuffer";
request.open("GET", "/test");
request.onreadystatechange = function() { if (this.readyState === XMLHttpRequest.DONE) { console.log(new Int32Array(this.response)) } }
request.send();

它应该打印 [42, 43]

我想知道是否有更优雅的方法在服务器端执行此操作,例如

n += sprintf(response, "HTTP/1.1 200\r\n\r\n%4b%4b", &x, &y);

其中 %4b 是一个虚构的格式说明符,它只是说:将 4 个字节从该地址复制到字符串中(即“*[=26=][=26=][=26=]”)是否有格式说明符就像虚构的 %4b 做的那样?

Is there a format specifier like the fictional %4b?

没有,没有,你的方法很好。我建议使用 snprintf 并进行一些检查以避免缓冲区溢出,添加 ex。 static_assert(sizeof(int) == 4, "") 检查平台是否使用大端和类似的环境和错误处理,避免未定义的行为检查。

也就是说,您可以多次使用 %c printf 说明符,例如 "%c%c%c%c", ((char*)&x)[3], ((char*)&x)[2], ((char*)&x)[1], ((char*)&x)[0] 来打印 4 个字节。您可以将其包装在宏中并执行:

#include <stdio.h>

#define PRI_BYTES_4  "%c%c%c%c"
#define ARG_BYTES_BE_4(var) \
    ((const char*)&(var))[3], \
    ((const char*)&(var))[2], \
    ((const char*)&(var))[1], \
    ((const char*)&(var))[0]

int main() {
    int var = 
        'l' << 24 |
        'a' << 16 | 
        'm' << 8 |
        'e';
    printf("Hello, I am " PRI_BYTES_4 ".\n",
        ARG_BYTES_BE_4(var));
    // will print `Hello, I am lame.`
}

是一个XY问题,你是在问如何用sprintf()来解决你的问题,而不是简单的问如何解决你的问题。你的实际问题是如何使代码更 "elegant".

没有特别的理由在单个写入操作中发送数据 - 网络堆栈缓冲将确保数据有效地打包:

static const char header[] = "HTTP/1.1 200\r\n\r\n" ;
write( client, header, sizeof(header) - 1 ) ;
write( client, &x, sizeof(x) ) ;
write( client, &y, sizeof(y) ) ; 

请注意,X 和 Y 将以本机机器字节顺序写入,这在接收方可能不正确。更笼统的话:

static const char header[] = "HTTP/1.1 200\r\n\r\n" ;
write( client, header, sizeof(header) - 1 ) ;

uint32_t nl = htonl( x ) ;
write( client, &nl, sizeof(nl) ) ;

nl = htonl( y ) ;
write( client, &nl, sizeof(nl) ) ;