简体   繁体   中英

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.

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. But if I change the pointer type to integer ( int *p and p= (int *)x) , it gives me some garbage number.

Can anyone explain me why the " char " is used in this case and why it works fine and not " int " for pointer. And what's going on at " p = &p[x] " (I have no clue how this line works).

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. 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:

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 . And since sizeof(char) is by definition 1, p = p + x simply adds x to the raw value of 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. If not, then the body runs which adds x to 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. So the loop is not entered and p has the value of x . If y is 2, the loop will be entered once and p will equal x + x . If y is 3, the loop is entered twice so p will be x + x + x .

So the effect here is that p , when converted back to an integer, contains the value 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. 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.

To reiterate however, all of the above depends on undefined behavior because p is not pointing to a valid object. It may work on some systems and compilers, but it is not guaranteed to work.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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