简体   繁体   English

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

[英]C pointers (difference between int and char when using pointers), example below?

I am in the C pointers learning phase, I was looking online for some codes using pointers and found one code and I am totally confused now.我正处于 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 is the product of x*y (multiplication) and this codes works fine. P 是 x*y(乘法)的乘积,这个代码工作正常。 But if I change the pointer type to integer ( int *p and p= (int *)x) , it gives me some garbage number.但是如果我将指针类型更改为整数( int *pp= (int *)x) ,它会给我一些垃圾数字。

Can anyone explain me why the " char " is used in this case and why it works fine and not " int " for pointer.谁能解释一下为什么在这种情况下使用“ char ”以及为什么它可以正常工作而不是“ int ”作为指针。 And what's going on at " p = &p[x] " (I have no clue how this line works). p = &p[x] ”发生了什么(我不知道这条线是如何工作的)。

This code is relying on undefined behavior regarding pointer arithmetic to perform a simple multiplication.此代码依赖于有关指针算术的未定义行为来执行简单的乘法。

Pointer arithmetic is only well defined if a pointer points to a valid object and the result of the arithmetic also points within that object.指针运算只有在指针指向有效对象并且运算结果也指向该对象内时才被明确定义。

This first line:第一行:

p = (char *)x;

Takes the integer value x given by the user and interprets is as a pointer to char * Whatever this value is most likely doesn't point to a valid location, so any arithmetic on it is undefined behavior.获取用户给出的整数值x并将其解释为指向char *的指针char *无论这个值是什么,很可能都没有指向有效的位置,因此对它的任何算术都是未定义的行为。 But for the moment, let's assume the compiler will perform the arithmetic as if it were pointing to a valid object and that a pointer is represented by a single integer value.但目前,让我们假设编译器将执行算术,就好像它指向一个有效对象并且指针由单个整数值表示。

In the body of the loop we have:在循环体中,我们有:

p = &p[x];

The array indexing here is exactly equivalent to:这里的数组索引完全等同于:

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

The dereference operator and address-of operator cancel each other out, so this is equivalent to:解引用运算符和 address-of 运算符相互抵消,所以这等效于:

p = p + x;

When adding to a pointer, it actually adds the given value times the size of the type pointed to rather than directly adding to the pointer value.添加到指针时,它实际上将给定值乘以指向的类型的大小,而不是直接添加到指针值。 That allows us to use simple arithmetic to point to the start of a given array element as opposed to some offset within a given array element if the type is larger than a single byte.这允许我们使用简单的算术来指向给定数组元素的开始,而不是在给定数组元素内的某个偏移量(如果类型大于单个字节)。 In this case the pointed-to type is char , so x * sizeof(char) is added to the raw value of p .在这种情况下,指向的类型是char ,因此x * sizeof(char)被添加到p的原始值。 And since sizeof(char) is by definition 1, p = p + x simply adds x to the raw value of p .由于sizeof(char)根据定义为 1,因此p = p + x只需将x添加到p的原始值。

Now looking at the full loop with the translated body:现在查看带有翻译体的完整循环:

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

The value of y is decremented, and the decremented value is checked to see if it is zero. y的值递减,并检查递减后的值是否为零。 If not, then the body runs which adds x to p .如果不是,则主体运行将x添加到p

Suppose y is 1. It is decremented to 0, and the value of 0 is used as the conditional of the while loop, which in a boolean context is false.假设y为 1。它递减到 0,并且 0 的值用作while循环的条件,在布尔上下文中为 false。 So the loop is not entered and p has the value of x .所以没有进入循环, p的值为x If y is 2, the loop will be entered once and p will equal x + x .如果y为 2,则循环将进入一次并且p将等于x + x If y is 3, the loop is entered twice so p will be x + x + x .如果y为 3,则循环进入两次,因此p将为x + x + x

So the effect here is that p , when converted back to an integer, contains the value x * y .所以这里的效果是p在转换回整数时包含值x * y

The reason that you get a different value if you change the type of p to int * is because of the way pointer arithmetic is handled as previously mentioned.如果将p的类型更改为int *会得到不同的值,这是因为如前所述处理指针算术的方式。 sizeof(int) is most likely 4, so p = p + x is actually adding x * 4 to the raw value of p , so the result will be 4 times larger. sizeof(int)最有可能是 4,所以p = p + x实际上是将x * 4添加到p的原始值,所以结果会大 4 倍。

To reiterate however, all of the above depends on undefined behavior because p is not pointing to a valid object.然而,重申一下,以上所有内容都取决于未定义的行为,因为p未指向有效对象。 It may work on some systems and compilers, but it is not guaranteed to work.可能某些系统和编译器上工作,但不能保证工作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM