#define ARRAY_SIZE 20
float DataSource[ARRAY_SIZE];
void Read(unsigned char const *Source, unsigned char *Destination, unsigned long DataSize)
{
for ( unsigned long i = 0; i < DataSize; i++)
{
*(Destination + i*DataSize) = *(Source + i*DataSize);
}
}
void fun()
{
int Index;
float Dest;
for ( Index = 0; Index < ARRAY_SIZE; Index++ )
{
Read((unsigned char *)&DataSource[Index], (unsigned char *)&Dest, sizeof(DataSource[Index]));
}
}
我遇到上述代码的问题,在调用Read()时,我的Index变量被覆盖,我确定丑陋的指针转换是罪魁祸首,但我无法理解究竟发生了什么。
unsigned char指针类型是必需的,因为上面的代码旨在模拟某些驱动程序级软件并维护相同的原型。
有人可以帮我理解这个问题吗?除了Read()原型之外,上述所有代码都是可以改变的。
答案 0 :(得分:4)
错误在于:
for ( unsigned long i = 0; i < DataSize; i++)
{
// vvvvvvvvvv vvvvvvvvvv
*(Destination + i*DataSize) = *(Source + i*DataSize);
}
i * DataSize
始终大于i
=&gt; “出界”访问。
替换为:
for ( unsigned long i = 0; i < DataSize; i++)
{
*(Destination + i) = *(Source + i);
}
答案 1 :(得分:2)
您将单个float
的地址传递给Read
(&Dest
),然后继续向连续的内存位置写入多个值。由于你正在编写随机内存,因此它不可能覆盖index
(和其他东西),因为堆栈通常会向下扩展。
答案 2 :(得分:1)
这是错误的:
*(Destination + i*DataSize) = *(Source + i*DataSize);
您希望复制DataSize
个相邻字节,而不是DataSize
个字节{总范围DataSize*DataSize
)
说完
Destination[i] = Source[i];
答案 3 :(得分:1)
一种有趣的(对我而言)C ++方式。
template<typename Data>
struct MemBlockRefHelper {
typedef Data value_type;
Data* data;
size_t size;
MemBlockRefHelper( Data* d, size_t s):data(d), size(s) {}
template<typename Target, typename Other=typename Target::value_type>
Target& Assign( MemBlockRefHelper<Other> const& other ) {
Assert(size == other.size);
for (size_t i = 0; i < size; ++i) {
if (i < other.size) {
data[i] = other.data[i];
} else {
data[i] = 0;
}
}
Target* self = static_cast<Target*>(this);
return *self;
}
};
struct MemBlockRef;
struct MemBlockCRef:MemBlockRefHelper<const unsigned char> {
MemBlockCRef( const unsigned char* d, size_t s ):MemBlockRefHelper<const unsigned char>( d, s ) {}
MemBlockCRef( const MemBlockRef& other );
};
struct MemBlockRef:MemBlockRefHelper<unsigned char> {
MemBlockRef( unsigned char* d, size_t s ):MemBlockRefHelper<unsigned char>( d, s ) {}
MemBlockRef& operator=( MemBlockRef const& other ) {
return Assign< MemBlockRef >( other );
}
MemBlockRef& operator=( MemBlockCRef const& other ) {
return Assign< MemBlockRef, const unsigned char >( other );
}
};
inline MemBlockCRef::MemBlockCRef( const MemBlockRef& other ): MemBlockRefHelper<const unsigned char>( other.data, other.size ) {}
void Read( unsigned char const* Source, unsigned char* Dest, unsigned long DataSize ) {
MemBlockCRef src( Source, DataSize );
MemBlockRef dest( Dest, DataSize );
dest = src;
}
大量过度设计,但想法是结束一定大小的POD内存块的想法,并为其内容提供引用语义(初始化是创建对相同数据的新引用,赋值做副本超过提到的数据)。
一旦你有了这样的课程,Read
的代码就成了3班。好吧,你可以在一个地方做到这一点:
MemBlockRef( Dest, DataSize ) = MemBlockCRef( Source, DataSize );
但这是不必要的。
嗯,这就是整个框架。
但我写这篇文章很有趣。
答案 4 :(得分:0)
让我们仔细看看你的Read()
:我从0变为DataSize-1;每次通过i * DataSize的偏移量访问内存时,即从0到DataSize *(DataSize-1)的偏移量。看起来不对,因为DataSize**2-DataSize
毫无意义。
与其他答案不同,我不想猜猜你想要什么。只是展示一种“维度分析”,可以帮助发现代码的最大部分,而无需阅读作者的想法。
答案 5 :(得分:0)
您将Dest
内声明的标量变量fun()
视为Read()
内的数组。似乎Dest
和您的Index
变量都放在堆栈旁边,这说明Index
在为Read()
执行i==1
内的循环时会被完全覆盖}。
所以解决方案是:将Dest
声明为数组:
float Dest[ARRAY_SIZE];