程序如下:
#include <stdio.h>
#include<stdlib.h>
int *glob_var;
int* copy(void *a,int size)
{
int *t=(int *)calloc(1,sizeof(int));
int i;
int *glob_var=(int *)calloc(size,sizeof(int));
printf("glob_var=%pn",glob_var);
printf("a=%pn",a);
t=glob_var;
for(i=0;i<size;i++)
{
*glob_var=*(int *)a;
glob_var++;
(int *)a++;
// printf("a=%pn",a);
}
glob_var=t;
for(i=0;i<10;i++)
{
printf("%dt",*glob_var);
glob_var++;
}
glob_var=t;
printf("n%pn",glob_var);
return t;
}
int main() {
// Write C code here
int a=0x123456,i;
int *var=(int *)calloc(10,sizeof(int));
int *temp;
temp=var;
for(i=0;i<10;i++)
{
*var=i;
var++;
}
var=temp;
for(i=0;i<10;i++)
{
printf("%dn",*var);
var++;
}
var=temp;
printf("var=%pn",var);
glob_var=copy(var,10);
printf("%pn",glob_var);
for(i=0;i<10;i++)
{
printf("%dt",*glob_var);
glob_var++;
}
return 0;
}
然而,我得到的输出是:
0 16777216 65536 256 1 33554432 131072 512 2 50331648
I was expected:0 1 2 3 4 5 6 7 8 9
.
但是,在copy()
函数中,如果我用a=(int *)a+1;
代替(int *)a++;
,它是工作的。
我的问题是:当前的程序有什么问题?
在C1中不允许对指向void的指针(void*
)进行算术操作,编译器应该在下面的行中(至少)警告您:
(int *)a++;
当我编译你的代码时(使用Visual Studio中的clang-cl编译器),我确实得到了两个警告:
警告:指向void指针的算术是GNU扩展[-Wpointer-arith]
警告:表达式结果未使用[-Wunused-value]
第一个解决了我在开头提到的问题(并在脚注中讨论过),但第二个应该敲响警钟。这表明强制转换没有按预期工作——它实际上应用于a++
操作的结果,因为强制转换的优先级低于后自增操作。
然而,当您使用a = (int *)a + 1;
时,则一切都按预期工作,因为a
指针被强制转换为之前的int*
执行算术运算(然后隐式地将赋值转换回void*
)。
glob_var
,以及在几个printf
调用中使用非void指针作为%p
格式说明符的参数,但这些与你报告的问题无关。另外,这是值得一读的:我是否强制转换malloc的结果?)
1一些C编译器,如GCC,允许对void*
指针进行算术运算,但我不知道这种操作的"基本单元大小"是多少。您必须阅读GCC手册才能确定这一点,但最好只使用1
,而不是您的程序所需的sizeof(int)
。实际上,如果这个假设是正确的,并且sizeof(int)
在您的平台上是4
,那么它将解释三个"垃圾值"。在输出中连续的"真实"数据之间。