2013-07-30 41 views
1

所以我必须处理一些结构数据,我不得不以MPI_Send/Recv的奇怪方式进行压缩。对原始数据的指针运算

没有办法将它舒适地投射到一个指向我想要操作的已知类型的指针上,然后索引(因为我已经将结构挤压成连续数据,不能假定任何关于对齐的东西),所以我必须通过指针算术来完成它。问题是,为了与MPI保持一致,这些数据被赋予void *,void *上的指针运算是非法的。

我的问题主要是风格:有没有更好的方法来做到这一点比铸造char *,然后做我的指针算术?如何将效率考虑在一个void *中,铸造成char *,做我的东西,然后再回到void *?我无法想象这些指针会非常昂贵。

G'day和thankee很多。

回答

3

指针演员是完全免费的。做到这一点。

具有类型的指针完全是语言级别的概念。当你进入硬件级时,指针只是一个恰好用作内存地址的整数。

必须小心严格别名,铸造约三分球的时候,但char *被定义为是安全的,我想。

[好的,在某些体系结构中,有些情况下指针的特殊处理超出了“仅仅是整数”的范围,但您可能会忽略这些情况。也有一些ABI在其中不同的指针类型不同(例如FDPIC),但又是别人的问题。]

+0

啊,那很简单。非常感谢你。 –

0

您的解决方案是健全的。很多时候,我已经做了这样的事情:

void handle_raw(void* data) { 
    // Use a uint8_t so pointer arithmetic is at a byte-level. 
    uint8_t* p = data;  
    uint16_t value; 

    // Read a 2-byte value at an arbitrary offset. 
    value = *(uint16_t*)(p + 0x42); 

    // Write a 2-byte value at an arbitrary offset. 
    *(uint32_t*)(p + 0x12) = 0xDEADBEEF; 
} 

当然,你应该使用常数偏移,并执行正确的边界检查。

+0

在这种情况下,**不是**安全的。在许多体系结构中,如果指针不是2字节对齐,则代码将失败。此外,type-punning具有别名问题:使用联合。 – ams

0

为什么需要自行打包缓冲区有什么特别的理由吗?在MPI操作之前,你真的实际上压缩了连续缓冲区中的数据吗?如果是这样,你的压缩和传输时间必须低于简单的传输。如果是这样的话,那么我可以看到这是很好的理由。

如果你实际上打包在一个连续的缓冲区中,仅用于MPI操作,那么更好的解决办法是自己停止打包数据,而是使用MPI派生的数据类型

您可以使用类似“MPI派生数据类型示例”的方式进行网络搜索,并获得比我可以在此处简单写的更好的解释。

+0

问题是结构包含的东西不是数据,而是索引到我想发送的一堆值中。所以有点像指针。直接发送这些东西将毫无意义,就像发送指针一样,所以我需要以某种方式对其进行“解除引用”。仅使用派生数据类型机械来完成,这是某处棘手和不可能之间,因为此堆栈上的每个值的位移是不相对于包含其索引该结构的开始恒定。 –