【问题标题】:Copying memory of adresses with memcpy使用 memcpy 复制地址的内存
【发布时间】:2021-12-27 02:02:02
【问题描述】:

基本功能:

template <typename T>
T** shifting (T* in, int size, int dist, int pos) {
    auto out = new T* [size];
    int k = (pos-1) * size/dist;
    for (int i{0}; i < size; ++i) {
        if (i+k >= size) {
            out[i] = &in[k+i-size];
        } else {
            out[i] = &in[k+i]
        }
    }
    return out;
}

这个函数正在创建一个指针数组 out 指向数组 in 的元素,我想知道是否有更快的内存操作方法,所以我尝试了一些不同的东西。

新功能:

template <typename T>
T** stuff(T* in, int size, int dist, int pos) {
    int helper = size/dist;
    auto out = new T* [size];
    for (int i{0}; i < dist; i++) {
        if (pos + i < size) {
            memcpy(out + i - pos + dist, in+i*helper, helper * sizeof(T*));
        } else {
            memcpy(out + i - pos, in+i*helper, helper * sizeof(T*));
        }
    }
    return out;
}

但是,这不是给出地址数组,而是将地址后面的值转换为指针,因此我将元素的值作为指针获取。 仔细检查后,这种行为不应该是其他情况,但我想不出一种让它起作用的方法。

感谢您的帮助。

【问题讨论】:

    标签: c++ arrays pointers memory


    【解决方案1】:

    您的新循环体(在您编辑之前,但我的分析基本保持不变)是:

    memcpy(out + i - pos + (pos + i < size ? dist: 0), in+i*helper, helper * sizeof(T*));
    

    为了可读性而扩展它(这不会损害性能,所以你也应该这样做):

    T** dest = out + i - pos + (pos + i < size ? dist: 0);
    T* src = in + i * helper;
    memcpy(dest, src, helper * sizeof(T*));
    

    通过类型写出来,现在你可以看到类型不兼容(T** 和 T*)。您要做的是将地址复制到in 的特定位置,但您不能像这样以块的形式执行此操作,因为这些地址在内存中还不作为数字存在,您需要创建它们!

    最好的办法是坚持使用您的原始代码,这样会更清晰。如果存在性能问题,请告诉我们您正在编译的优化级别、您使用的输入大小、此函数花费的时间以及您的时间预算是多少?

    【讨论】:

    • 其实只是在开玩笑,我的数组大小是 40 和内存的东西,我试过了,因为我在设计第一个之后想出了它,但是如果有一个很好的方法来操作内存地址,告诉我!
    • 还有一件事,如果我将src 转换为int** 它也不起作用,它实际上完全一样。这是为什么呢?
    • 数组大小为 40 很明显,您根本没有性能问题。强制转换无法解决问题,因为您要放入out 的数字在内存中的任何位置都不存在,因此无法复制。它基本上是“如何使用 memcpy 用 [1, 2, 3, 4, ...] 填充数组”,答案是“你不能。”
    【解决方案2】:

    我不知道这是否正是您要查找的内容,但这会运行得更快一些,并且更易于阅读和推理。

    template <typename T>
    T** shifting (T* in, int size, int dist, int pos) {
        auto out = new T* [size];
        int k = (pos-1) * size/dist;
    
        int i, j;
        for (i = 0, j = k; i < size - k; ++i, ++j)
            out[i] = &in[j];
    
        for (j = 0; i < size; ++i, ++j)
            out[i] = &in[j];
    
        return out;
    }
    

    【讨论】:

    • 看起来很整洁,谢谢!
    • @Raumschifffan 你也许应该使用 std::rotate(),它正是这样做的。
    • 呃,这个思考过程花了我一些时间,这很难,但还是谢谢你..
    • 哦等等,我意识到我实际上需要一个指针数组,而不是旋转数组本身。
    【解决方案3】:

    我终于找到了解决办法。

    用于“简化”数据类型的结构 e。 G。 int (*) [3] -> int(注:t* (*) [n] -> t*):

    template <typename t> struct rip {
        typedef t type;
    };
    template <typename t, size_t n> struct rip <t (*) [n]> {
        typedef t type;
    };
    

    实际功能:

    template <typename pArr>
    pArr shift(pArr pa_in, size_t pos, size_t spl) {
        typedef typename rip<pArr>::type t;
    
        size_t b_in{sizeof(*pa_in)};
        size_t b_spl{b_in/spl};
        size_t n_spl{b_spl/sizeof(t)};
    
        auto pa_out{(pArr)malloc(b_in)};
        auto p_out{(t*)pa_out};
        auto p_in{(t*)pa_in};
    
        size_t i, k;
        for (i = 0, k = pos; k < spl; i++, k++)
            memcpy(p_out + i*n_spl, p_in + k*n_spl, b_spl);
        for (i = pos, k = 0; i < spl; i++, k++)
            memcpy(p_out + i*n_spl, p_in + k*n_spl, b_spl);
    
        return pa_out;
    }
    

    注意:pArr 期望类型为 t (*) [n](例如 int* (*) [10]

    【讨论】:

    • 编辑:没关系,我只是重写了我一开始不想要的功能......
    猜你喜欢
    • 2015-06-09
    • 2018-09-19
    • 1970-01-01
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多