繁体   English   中英

将char直接放置在数组后的可靠方法

[英]Reliable way to place char directly after array

我正在使用以下代码从套接字读取:

char buf[4097];
int ret = read(fd, buf, sizeof(buf) - 1);
buf[ret] = 0x0;
std::cout << buf << "\n";

但是,我不喜欢这里需要4097sizeof(buf) - 1 这种东西很容易忘记。 所以我想知道,有什么好方法可以迫使编译器在数组之后立即将0x0直接保留在堆栈上吗?

我会喜欢的东西

char buf[4096];
char _ = 0x0;
int ret = read(fd, buf, sizeof(buf));
buf[ret] = 0x0;
std::cout << buf << "\n";

但是我不知道如何强制编译器不强制执行任何操作(afaik #pragma pack仅适用于结构,不适用于堆栈)。

我会保持简单:

ssize_t read_and_put_0(int fd, void *buf, size_t count)
{
    ssize_t ret = read(fd, buf, count - 1);
    if (ret != -1) // Or `if (ret <= 0)`
        ((char *)buf)[ret] = 0x0;
    return ret;
}

// ...

char buf[4097];
read_and_put_0(fd, buf, sizeof buf);

我不喜欢4097sizeof(buf) - 1的需求

简单就是美丽:

constexpr std::size_t size = 4096;
char buf[size + 1];
int ret = read(fd, buf, size);
buf[ret] = 0x0;

您可以精确地指定所需的大小,而无需手动添加。 而且既不需要sizeof,也不需要减去1。

在我看来,记住终止符的+ 1比记住声明一个单独的字符对象更容易-无论如何都不能将其直接放在数组之后。

就是说,与read相比, read文本文件的方式更容易出错。

未指定不同变量的值在内存中的相对位置。 实际上,某些变量可能根本不驻留在内存中。 如果要确保内存中数据的相对布局,请使用结构或类。 例如:

struct {
    char buf[4096];
    char term;
} tbuf = { { 0 }, 0 };

int ret = read(fd, tbuf.buf, sizeof(tbuf.buf));
if (ret >= 0 && ret < sizeof(tbuf.buf)) {
    tbuf.buf[ret] = '\0';
}

确保结构的成员以声明时的顺序排列在内存中,因此您可以确信,故障安全终止符tbuf.term将跟随tbuf.buf 但是,您不能确定两者之间没有填充。 此外,这只是故障保护。 如图所示,您仍然需要编写空终止符,以防短读。

此外,即使tbuf的表示tbuf肯定比其buf成员大至少一个字节,它仍会生成UB来访问tbuf.buf的边界。 总体而言,我认为您不会从中获得多少收益。

只要您拥有数组而不是指向某个数组的指针,HolyBlackCats答案的替代方法就不需要给出size参数。

template <size_t N> ssize_t read_and_put_0(int fd, char (&buf)[N]) {
    ssize_t ret = read(fd, buf, N - 1);
    if(ret != -1) // Or `if (ret <= 0)`
        buf[ret] = 0x0;
    return ret;
}

char buf[4097];
read_and_put_0(fd, buf);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM