相关疑难解决方法(0)

编写符合严格别名的memcpy符合条件

在询问"如何实现符合严格别名规则的memcpy函数"时,一般的答案就是这样的

void *memcpy(void *dest, const void *src, size_t n)
{
    for (size_t i = 0; i < n; i++)
        ((char*)dest)[i] = ((const char*)src)[i];
    return dest;
}
Run Code Online (Sandbox Code Playgroud)

但是,如果我理解正确的话,编译器可以自由地重新排序对memcpy的调用并访问dest,因为它可以使用任何其他指针类型的读取重新排序写入char*(严格的别名规则阻止仅对char*的读取进行重新排序)到任何其他指针类型).

这是正确的,如果是的话,有没有办法正确实现memcpy,还是我们应该依赖内置的memcpy?

请注意,这个问题不仅涉及memcpy,还涉及任何反序列化/解码功能.

c c++ strict-aliasing memcpy

8
推荐指数
2
解决办法
1387
查看次数

哪些对齐问题限制了malloc创建的内存块的使用?

我在C中编写了一个用于各种数学计算的库.其中一些需要一些"划痕"空间 - 用于中间计算的内存.所需空间取决于输入的大小,因此无法静态分配.库通常将被用于执行相同类型的具有相同大小的输入计算的多次迭代,因此我不希望mallocfree用于每个呼叫的库内; 分配足够大的块一次,重新使用它进行所有计算,然后释放它会更有效.

我的预期策略是请求void指向单个内存块的指针,可能具有附带的分配功能.说,像这样:

void *allocateScratch(size_t rows, size_t columns);
void doCalculation(size_t rows, size_t columns, double *data, void *scratch);
Run Code Online (Sandbox Code Playgroud)

这个想法是,如果用户打算进行相同大小的多次计算,他可以使用allocate函数来获取足够大的块,然后使用相同的内存块来执行每个输入的计算.分配功能并不是绝对必要的,但它简化了界面并使将来更容易更改存储要求,而库的每个用户都不需要确切知道需要多少空间.

在许多情况下,我需要的内存块只是一个很大的类型double,没有问题.但在某些情况下,我需要混合数据类型 - 比如一个双打块和一个整数块.我的代码需要是可移植的,并且应符合ANSI标准.我知道可以将void指针转换为任何其他指针类型,但如果我尝试对两种类型使用相同的块,我会关注对齐问题.

所以,具体的例子.说我需要一个3 double秒和5 int秒的块.我可以像这样实现我的功能:

void *allocateScratch(...) {
    return malloc(3 * sizeof(double) + 5 * sizeof(int));
}

void doCalculation(..., void *scratch) {
    double *dblArray = scratch;
    int *intArray = ((unsigned char*)scratch) + 3 * sizeof(double);
}
Run Code Online (Sandbox Code Playgroud)

这合法吗?在这个例子中,对齐可能工作正常,但是如果我将其切换并int首先获取double块而第二个块,那将会改变doubles 的对齐(假设64位双精度和32位整数).有一个更好的方法吗?或者我应该考虑更标准的方法?

我最大的目标如下:

  • 如果可能的话,我想使用单个块,这样用户就不必处理多个块或需要更改块数.
  • 我希望块是一个有效的块, …

c memory memory-alignment dynamic-memory-allocation

6
推荐指数
1
解决办法
1035
查看次数

如何使用C将二进制字符串转换为十六进制?

如何使用C将8位二进制字符串(例如"10010011")转换为十六进制?

c binary hex

2
推荐指数
1
解决办法
3万
查看次数