C指针(使用指针时int和char之间的差异),例如下面的示例?

时间:2018-11-01 12:26:57

标签: c pointers

我正处于C指针学习阶段,我在网上寻找一些使用指针的代码,发现一个代码,现在我完全感到困惑。

int x, y;

char *p;

printf("Enter two integers:\n");

scanf("%d%d", &x, &y);

p = (char *)x;

while(--y) 

  p = &p[x];

P是x * y(乘积)的乘积,此代码可以正常工作。但是,如果我将指针类型更改为整数(int *pp= (int *)x),则会给我一些垃圾数字。

任何人都可以向我解释为什么在这种情况下使用“ char”,为什么它可以正常工作,而不是对指针使用“ int”。以及“ p = &p[x]”处的情况(我不知道这行是如何工作的。)

1 个答案:

答案 0 :(得分:0)

此代码依赖undefined behavior进行指针算术运算,以执行简单的乘法。

仅当指针指向有效对象并且该运算的结果也指向该对象内时,指针算术才被很好地定义。

第一行:

p = (char *)x;

采用用户给出的整数值x并将其解释为指向char *的指针,无论该值很可能不是指向有效位置,因此对它的任何算术运算都不确定行为。但是暂时,让我们假设编译器将执行算术运算,就好像指向有效对象一样,并且指针由单个整数值表示。

在循环的主体中,我们有:

p = &p[x];

这里的数组索引完全等于:

p = &(*(p + x));

解引用运算符和地址运算符互相抵消,所以等效于:

p = p + x;

添加到指针时,它实际上将给定值乘以所指向类型的大小,而不是直接添加到指针值。如果类型大于单个字节,这允许我们使用简单的算术指向给定数组元素的开始,而不是给定数组元素内的某些偏移量。在这种情况下,指向的类型为char,因此x * sizeof(char)被添加到p的原始值中。而且由于sizeof(char)的定义为1,因此p = p + x只需将x添加到p的原始值中。

现在查看翻译后的正文的完整循环:

while (--y)
    p = p + x;

y的值减小,然后检查减小的值是否为零。如果不是,则正文运行,将x添加到p

假设y为1。它递减为0,并且将值0用作while循环的条件,该循环在布尔上下文中为false。因此不会输入循环,并且p的值为x。如果y为2,则循环将输入一次,而p将等于x + x。如果y为3,则循环进入两次,因此p将为x + x + x

因此,这里的效果是p在转换回整数时包含值x * y

如果将p的类型更改为int *,则得到不同值的原因是因为如前所述处理指针算法的方式。 sizeof(int)最有可能是4,所以p = p + x实际上是在x * 4的原始值上加上p,因此结果将大4倍。

不过,以上所有内容均取决于未定义的行为,因为p并未指向有效的对象。它可以在某些系统和编译器上工作,但不能保证能工作。