Home > OS >  Trying to load an array using pointers in C
Trying to load an array using pointers in C

Time:09-26

I am trying to load an array using pointers. I am assigned my x[0] the value of 2, and the desired output is 2, 4, 8, 16, 32, 64, 128.

For some reason, my loop starts at index 4 or it starts at index 2 and only prints 2, 4, 8, 16.

#include <stdio.h>
#include <math.h>

int main() {
    
    int x[7] = {}, *ip;
    ip = &(x[0]);
    
    *ip = 2;
    
    for(int i = 0; *ip < sizeof x; *ip *= 2) {
        printf("value of x: %d\n", x[i]);
    }
}

CodePudding user response:

This loop:

    for(int i = 0; *ip < sizeof x; *ip *= 2) {
        printf("value of x: %d\n", x[i]);
    }

will print x[i] till the value at memory location pointed by pointer ip is less than the size of object x in bytes. Note that i is initialised with 0 but it is nowhere altered.

Assume that size of int on your system is 4 bytes, the sizeof x will yield 28 because x is an array of 7 integers (7 * 4 = 28).

Iteration I:

i = 0          //initialized
*ip = 2,  2 < 28   ---->    true
print x[0]         ---->    2
*ip *= 2           ---->    *ip = 4   

Iteration II:

*ip = 4,  4 < 28   ---->    true
print x[0]         ---->    4
*ip *= 2           ---->    *ip = 8   

Iteration III:

*ip = 8,  8 < 28   ---->    true
print x[0]         ---->    8
*ip *= 2           ---->    *ip = 16   

Iteration IV:

*ip = 16,  16 < 28 ---->    true
print x[0]         ---->    16
*ip *= 2           ---->    *ip = 32   

Iteration V:

*ip = 32,  32 < 28 ---->    false
loop exits

Hence, you are getting output - 2, 4, 8, 16.

Correct way to get the size of an array is - sizeof (x) / sizeof (x[0]). This will result in number of elements of array x.

This

ip = &(x[0]);

can also written as

ip = x;

because when you access an array, it is converted to a pointer to first element (there are few exceptions to this rule). Moreover,

From C Standards#6.5.2.1

The definition of the subscript operator [] is that E1[E2] is identical to (*((E1) (E2)))..

by this definition

&(x[0]) -> &(*(x   0)) -> &(*(x)) -> x

You are initialising the array x with an empty initialiser:

int x[7] = {}

Empty initialiser is non-conforming in C, though some C compilers accept it. Instead, you should do:

int x[7] = {0}

Your desired output is 2, 4, 8, 16, 32, 64, 128 i.e. the first element of array should be 2 and every successive element in the array should be multiple of 2 of its previous element. Since, you want to calculate the value of every element of array using pointer pointing to that array element, one things you should know -

  • A pointer can point to one past the last element of array but dereferencing it will invoke undefined behaviour.

Putting these altogether, you can do:

#include <stdio.h>

int main (void) {
    
    int x[7] = {0}, *ip;

    ip = x;
    *ip = 2;
    
    for (size_t i = 0; i < sizeof (x) / sizeof (x[0]);   i) {
        printf ("value of x: %d\n", x[i]);

        // make pointer point to next element in array 
          ip;

        // make sure that the element that ip pointer pointing to is valid to deference
        if (ip < x   (sizeof (x)/sizeof (x[0]))) {
            // calculate the element value using the previous element value 
            *ip = *(ip - 1) * 2;
        }
    }

    return 0;
}

If you want to avoid the pointer comparison, you may do something like this:

#include <stdio.h>

int main (void) {
    
    int x[7] = {0}, *ip;

    ip = x;

    for(size_t i = 0; i < sizeof (x) / sizeof (x[0]);   i,   ip) {
        *ip = (i ? *(ip - 1) : 1) * 2;
        printf("value of x: %d\n", x[i]);
    }

    return 0;
}

CodePudding user response:

#include <stdio.h>

int main()
{
    int x[7] = {0};
    int *p, counter;

    for (p = &x[0], counter = 0; counter < 7;) {
        *p   = (1 <<   counter);
    }

    for (counter = 0; counter < 7; counter  )
        printf("%d\n", x[counter]);
}

CodePudding user response:

int x[7] = {}, *ip;
ip = &(x[0]);

In C, arrays are just pointers that you've told the proprocessor and compiler about so it can do the memory allocation on the stack for you. There's nothing special about the pointer itself with an array. In the above, ip and x are both int*, so you can just say ip = x;

*ip = 2;

x[0] now is 2

for(int i = 0; *ip < sizeof x; *ip *= 2){

Your middle condition *ip < sizeof x; in English is "until the int pointed to by ip is less than the number of bytes used by x (7 * sizeof(int); probably 7 * 4 or 28)" It's valid in that it will compile and execute, but I don't think it's what you want looking at the rest of your code. You never increment ip, so it's always changing x[0].

Assuming you just don't want ip to go past the end of x[], You could write this as i < sizeof(x)/sizeof(x[0]) which is "counter i is less than the total bytes used by x[] divided by the size in bytes of one element used by x (the number of elements in x[])" or if you want to use ip and not i for some reason ip <= &x[6] which is "ip is less than or equal to the address of the last element of x[] (because we know x is a fixed length of 7; [0...6]"

*ip *= 2

Your for incrementor is "the integer pointed to by ip is multiplied by 2". Normally you would increment your counter i here, but it's acceptable in C to do something else like you have here. However, since you never change ip, this is going to multiply the same x[0] by 2 over and over until x[0]'s value is more than sizeof(x). You probably want to increment ip or i here, so it steps through X[]. Normally the manipulation of your array would happen inside the for block and not in the for control statements.

printf("value of x: %d\n", x[i]);
    

This will always print the value of x[0], since i never changes.

Everything you've written is valid C code. Some of the things you're doing are unusual, but there are edge cases where you would want that in C, for example incrementing something other than your counter in the for loop control. However, you've got a extra code that isn't doing anything useful. I see what you want as output from your question details, but from your code I'm unsure how you want to accomplish that, so this is just a guess:

int x[7];
x[0] = 2;
printf("x[0] starts with: %d\n",x[0]);

for(int i = 1; i<sizeof(x)/sizeof(x[0]); i  ) { //i start at 1 because we already set x[0]
  x[i] = x[i-1]*2; //the current x[] = double the previous x[] 
  printf("value of x[%d]: %d\n",i,x[i]);
}

This version fills x with [2,4,8,16,32,64,128]. The int *ip isn't needed- there are times you'll want to control a loop with pointer math, but it's not needed here.

  •  Tags:  
  • c
  • Related