用 memcpy() 交换数组时出现垃圾值

问题描述 投票:0回答:4

我正在尝试使用 C 中的 memcpy() 创建一个通用交换函数。当我尝试交换数组时,我得到了垃圾值

这是下面的代码:

#include<stdio.h>
#include<string.h>

typedef struct Student
{
    char a[10];
    int b;
    double c;
}   Student;

void swap(void* one, void* two,size_t size)

{
    char temp[size] ;
    memcpy(temp,two,size); // temp = *two;
    memcpy(two,one,size);//*two = *one;
    memcpy(one,temp,size);//*one = temp;
}

int main()
{
    int i1 = 10, i2 = 20;
    float f1 = 1.6, f2 = 8.9;
    int a1[3] = {1, 2, 3}, a2[3] = {10, 20, 30};
    Student s1 = {"Mark", 42, 5.2}, s2 = {"Bilal", 9, 3};
    swap(&i1,&i2,sizeof(int));
    printf(" i1 = %d \n i2 = %d\n",i1,i2);
    swap(&f1,&f2,sizeof(double));
    printf(" f1 = %f \n f2 = %f\n",f1,f2);
    swap(&a1,&a2,sizeof(a2));
    printf(" a1 = %d %d %d  \n a2 = %d %d %d ",a1[0],a1[1],a1[2],a2[0],a2[1],a2[2]);
  
}

输出如下:

我也得到了数组的垃圾值

arrays c swap memcpy garbage
4个回答
5
投票

这个问题很有可能

swap(&f1,&f2,sizeof(double));

变量

f1
f2
的类型为
float
,而不是
double
float
的大小通常为 4 个字节,而
double
的大小为 8 个字节。

因为您传递了错误的大小,您的

memcpy
调用将超出范围并导致 未定义的行为

使用变量的大小来代替:

swap(&f1,&f2,sizeof f1);

注意:

f2
的值被打印为零应该是一个很大的暗示,问题就在那里。


另请注意,

&a1
&a2
是错误的。这些是指向实际数组本身的指针,而您应该将指针传递给数组的第一个元素。
&a1
&a2
的类型都是
int (*)[3]
,但你应该通过
int *
。相反,通过例如
&a1[0]
,或者只是普通的
a1
,因为这将 衰减 到指向其第一个元素的指针。


2
投票

浮点型为 4 个字节,而双精度型为 8 个字节。 代码变得混乱并覆盖了内存(

memcpy()
的危险)。

见下图:

int main( void )
{
    int i1 = 10, i2 = 20; // Integers
    swap( &i1, &i2, sizeof i1 );
    printf(" i1 = %d \n i2 = %d\n",i1,i2);

    float f1 = 1.6, f2 = 8.9; // Floats
    swap( &f1, &f2, sizeof f1 ); // NOT sizeof "double"!!
    printf(" f1 = %f \n f2 = %f\n",f1,f2);

    int a1[3] = {1, 2, 3}, a2[3] = {10, 20, 30}; // arrays
    swap( a1, a2, sizeof a1 );
    printf(" a1 = %d %d %d  \n a2 = %d %d %d ",a1[0],a1[1],a1[2],a2[0],a2[1],a2[2]);

    Student s1 = {"Mark", 42, 5.2}, s2 = {"Bilal", 9, 3};
    // and so on...
}

问问自己为什么要纠缠所有定义而不打印代码中出现的每个定义。

此外,通过使用

sizeof()
目标变量,即使源不正确,也不太可能溢出目标缓冲区。


0
投票
swap(&f1,&f2,sizeof(double));

这是为什么不应该在

sizeof
中使用类型的经典示例之一。

swap(&f1,&f2,sizeof(f1));

解决任何

f1
类型的问题。


-3
投票

请尝试这个

#include <stdio.h>
#include <string.h>

typedef struct Student {
char a[10];
int b;
double c;
} Student;

void swap(void* one, void* two, size_t size) {
char temp[size];
memcpy(temp, one, size);
memcpy(one, two, size);
memcpy(two, temp, size);
}

int main() {
int i1 = 10, i2 = 20;
float f1 = 1.6, f2 = 8.9;
int a1[3] = {1, 2, 3}, a2[3] = {10, 20, 30};
Student s1 = {"Mark", 42, 5.2}, s2 = {"Bilal", 9, 3};

swap(&i1, &i2, sizeof(int));
printf("i1 = %d\ni2 = %d\n", i1, i2);

swap(&f1, &f2, sizeof(float));
printf("f1 = %f\nf2 = %f\n", f1, f2);

for (int i = 0; i < 3; i++)
    swap(&a1[i], &a2[i], sizeof(int));

printf("a1 = %d %d %d\na2 = %d %d %d\n", a1[0], a1[1], a1[2], 
a2[0], 
a2[1], a2[2]);

return 0;
}

说明:

交换功能保持不变。我们仍然使用 memcpy 来交换两个变量的内存,但现在它与它们各自的数据类型正确对齐。

通过将正确的浮点大小(使用 sizeof(float))传递给交换函数来解决浮点值的问题。

循环内的数组交换也可以通过将正确的 int 大小(使用 sizeof(int))传递给交换函数来修复。

进行这些更正后,代码应该按预期工作,没有任何垃圾值问题。

© www.soinside.com 2019 - 2024. All rights reserved.