【问题标题】:Inspecting array after memcpy在 memcpy 之后检查数组
【发布时间】:2018-10-04 13:21:01
【问题描述】:

我正在努力更好地理解 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);

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

【问题讨论】:

  • *(int*)ptr + n 周围缺少括号。我想你的意思是*(int*)(ptr + n)
  • 3*sizeof(int) ? 3次?
  • void *ptr = &dest 为什么不int* ?然后你可以删除所有(int*) 演员表。喜欢int* ptr = &dest[0]; 或干脆int* ptr = dest;
  • @4386427 我选择了 void ptr,因为我看到 memcpy 在参数中接受 void: void *memcpy(void *s1, const void *s2, size_t n);不过我看只要 s1 和 s2 是同一个类型,没关系。
  • @Maydayfluffy 这只是意味着memcpy 接受任何类型的对象指针。它们都可以隐式转换为void *

标签: c memcpy


【解决方案1】:

您对第一个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;,那么你甚至不需要投射。

【讨论】:

  • 感谢您的澄清。你可能是对的 void *ptr = &dest;但将其更改为 without & 对输出没有任何影响。不知道该怎么做...
  • @Maydayfluffy 是的,它很可能只适用于任何通用平台。我只是不确定它是否保证可以在任何地方工作。
  • 关于通过void* 进行的转换似乎是合法的......除非存在对齐问题(请参阅C99 6.3.2.3p7)。
  • @pmg 我不明白这在这里如何应用。我们从不将指针转换回int (*)[4]
  • @pmg 如果它正确对齐,你不会得到未定义的行为,但它并没有说你可以用那个指针做任何事情(除了将它转换回它的原始类型)。跨度>
【解决方案2】:

当您打印值时:

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));

【讨论】:

    猜你喜欢
    • 2014-03-10
    • 2016-02-08
    • 2016-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-20
    • 2012-10-27
    相关资源
    最近更新 更多