在 memcpy 之后检查数组
Inspecting array after 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);
我如何从最后两个打印语句中得到不同的结果?第一个行为符合我的预期,但第二个行为不符合我的预期。
您对第一个 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;
,那么你甚至不需要施法。
打印值时:
printf("Before copy: %d, %d, %d, %d\n", *(int*)ptr, *(int*)ptr + 1, *(int*)ptr + 2, *(int*)ptr + 3);
您没有打印出您认为的样子。表达式 *(int*)ptr + 1
采用 ptr
,将其转换为 int *
,然后取消引用该指针,它为您提供第一个元素的值,然后将 1 添加到该元素的值。它不会添加到指针值,因为解引用运算符 *
的优先级高于加法运算符 +
.
您需要添加括号才能获得所需的行为:
printf("Before copy: %d, %d, %d, %d\n", *(int *)ptr, *((int *)ptr + 1), *((int *)ptr + 2), *((int *)ptr + 3));
我正在努力更好地理解 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);
我如何从最后两个打印语句中得到不同的结果?第一个行为符合我的预期,但第二个行为不符合我的预期。
您对第一个 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;
,那么你甚至不需要施法。
打印值时:
printf("Before copy: %d, %d, %d, %d\n", *(int*)ptr, *(int*)ptr + 1, *(int*)ptr + 2, *(int*)ptr + 3);
您没有打印出您认为的样子。表达式 *(int*)ptr + 1
采用 ptr
,将其转换为 int *
,然后取消引用该指针,它为您提供第一个元素的值,然后将 1 添加到该元素的值。它不会添加到指针值,因为解引用运算符 *
的优先级高于加法运算符 +
.
您需要添加括号才能获得所需的行为:
printf("Before copy: %d, %d, %d, %d\n", *(int *)ptr, *((int *)ptr + 1), *((int *)ptr + 2), *((int *)ptr + 3));