在memcpy之后检查数组

时间:2018-10-04 13:21:01

标签: c memcpy

我试图更好地理解memcpy。这是我正在尝试的示例:

int arr[] = {10, 20, 30, 40};
int dest[] = {1, 2, 3, 4};

void *ptr = &dest;

printf("Before copy: %d, %d, %d, %d\n", *(int*)ptr, *(int*)ptr + 1, *(int*)ptr + 2, *(int*)ptr + 3);

memcpy(dest, arr, 3*sizeof(int));

printf("After copy: %d, %d, %d, %d\n", dest[0], dest[1], dest[2], dest[3]);
printf("After copy: %d, %d, %d, %d\n", *(int*)ptr, *(int*)ptr + 1, *(int*)ptr + 2, *(int*)ptr + 3);

我如何从最后两个打印语句中得到不同的结果?第一个行为符合我的预期,但第二个行为却不符合预期。

2 个答案:

答案 0 :(得分:4)

仅因为printf用连续的整数初始化,所以您对第一个dest感到困惑。试试

int dest[] = { 4, 72, 0, -5 };

相反。

您真正的问题是运算符优先级:*a + b解析为(*a) + b,而不是*(a + b)(后者等效于a[b])。


顺便说一句,我不相信

void *ptr = &dest;
*(int *)ptr

是合法的。该标准说,任何(对象)指针都可以转换为void *并返回,而不会丢失信息,但是在这里,您是从类型A转换为void *到类型B(其中A!= B)。

具体来说:&dest的类型为int (*)[4](指向4个整数的数组的指针),而不是int *。要解决此问题,

void *ptr = dest;

相反。或者只是int *ptr = dest;,那么您甚至不需要进行投射。

答案 1 :(得分:1)

打印值时:

printf("Before copy: %d, %d, %d, %d\n", *(int*)ptr, *(int*)ptr + 1, *(int*)ptr + 2, *(int*)ptr + 3);

您没有打印出您认为的样子。表达式*(int*)ptr + 1ptr,将其转换为int *,然后取消对该指针的引用,该指针为您提供第一个元素的值,然后在该元素的值上加1。它不会添加到指针值,因为取消引用运算符*的优先级高于加法运算符+

您需要添加括号以获取所需的行为:

printf("Before copy: %d, %d, %d, %d\n", *(int *)ptr, *((int *)ptr + 1), *((int *)ptr + 2), *((int *)ptr + 3));