将指针强制转换为int和字符之间有什么区别吗?在C ++中

时间:2019-03-15 09:51:03

标签: c++ memory-management allocation reinterpret-cast

#include <iostream>

char** make2D(const int dim1, const int dim2)
{
    char* toAlloc;
    const int size = (dim1 * dim2) + dim2;
    toAlloc = new char[size];

    for(int i = 0; i < dim2; i++)
    {
        toAlloc[i] = reinterpret_cast<char>(&toAlloc[(dim2 + (dim1 * i))]);
    }

    return reinterpret_cast<char**>(toAlloc);
}

int main(void)
{
    int dim1 = 8;
    int dim2 = 10;
    char** array2D = make2D(dim1, dim2);

    for (int i = 0; i < dim2; ++i)
    {
        array2D[i][i % dim1] = i + 100; // << Crash
    }

    return 0;
}

我试图通过一次分配来分配二维数组。 因此,我的算法是,前10个(在此代码中为dim2)具有指向每行第一项的指针。

当我尝试通过指向“ int”的指针进行尝试时,

int** make2D(const int dim1, const int dim2)
{
    int* toAlloc;
    const int size = (dim1 * dim2) + dim2;
    toAlloc = new int[size];

    for(int i = 0; i < dim2; i++)
    {
        toAlloc[i] = reinterpret_cast<int>(&toAlloc[(dim2 + (dim1 * i))]);
    }

    return reinterpret_cast<int**>(toAlloc);
}

int main(void)
{
    int dim1 = 8;
    int dim2 = 10;

    int** array2D = make2D(dim1, dim2);

    for (int i = 0; i < dim2; ++i)
    {
        array2D[i][i % dim1] = i + 100;
    }

    return 0;
}

它工作正常,但是当我在char中执行此操作时,它在上面的代码的注释行中崩溃。

我想到崩溃的原因是当我执行reinterpret_cast时,由于指针(8字节)和char(1字节)之间的内存大小差异而发生了某些事情。 听起来像是荒谬的...将指针(8byte)更改为int(4byte)很好,但是当我进行更显着的转换(8byte至1byte)时,会引起一些问题...

我不知道为什么char不起作用而int起作用。 您能否提出一些建议使字符案例有效?

2 个答案:

答案 0 :(得分:0)

要回答这个问题,是的,有一个很大的区别,在许多平台上,指针可能适合一个int,而在很少的平台上,它将适合一个char。在现代的64位PC上,没有一种存储指针的安全方法。

如果大小是静态的,请使用诸如vectorarray之类的容器。 尝试类似的东西:

array<array<T, dim2>, dim1> variable{};

如果您实际上想要类型T的二维数组;由于您似乎需要一个指针数组,因此请尝试以下操作:

array<array<T *, dim2>, dim1> variable{};

这将确保为您的平台创建一个适当类型的数组以存储指针,无论实际上有多大指针,显然,您都应该用要指向的数据的适当类型替换T,这将确保为您正确完成指针数学运算。 数组类型的大小将在编译时计算,如果需要动态大小,则应在向量和所有子向量的分配调用resize之后使用向量,以确保您分配所有内存的次数尽可能少可能。

也请不要使用reinterpret_cast或C样式强制转换,除非您非常了解自己在做什么,否则这是灾难的秘诀。

不知道您正在读什么书或谁在教您C ++,但请更改您的知识来源。

不鼓励使用原始拥有的指针,并且您使用它们的方式在很多方面都是错误的。 除指针类型外,切勿将指针存储在其他任何东西中。即使在普通C语言中,如果需要完全转换,也应至少转换为void *。

如果您真的想直接存储/传递指针,请阅读有关unique_ptrshared_ptr的信息。

如果您坚持对容器使用原始指针,请尝试使用诸如地址清理器,内存清理器(至少clang和gcc支持这些清理器,如今可能还会有更多的编译器)之类的清理器来构建代码。

答案 1 :(得分:0)

问题是对象大小的“不兼容”:

  • sizeof(char)1
  • sizeof(int)通常是48(但至少是2)。
  • sizeof(T*)(通常为48std::uintp_t可以保存void*的值,而对于int则不必这样(甚至更少,char)。

您不能将void*安全地存储到charint中。碰巧它可以为您int使用,但它不可移植。

reinterpret_cast通常是错误的工具。

更简单的方法是创建一个class Matrix,并使用std::vector<T>和访问器来修复索引。 (您甚至可以使用代理来允许m[2][3]语法)。

拥有原始指针后,您需要新的展示位置,并提供正确的删除器...