我正在尝试使用 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]);
}
我也得到了数组的垃圾值
这个问题很有可能
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
,因为这将 衰减 到指向其第一个元素的指针。
浮点型为 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()
目标变量,即使源不正确,也不太可能溢出目标缓冲区。
swap(&f1,&f2,sizeof(double));
这是为什么不应该在
sizeof
中使用类型的经典示例之一。
swap(&f1,&f2,sizeof(f1));
解决任何
f1
类型的问题。
请尝试这个
#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))传递给交换函数来修复。
进行这些更正后,代码应该按预期工作,没有任何垃圾值问题。