2

EDIT: Thank you very much for your responses. I understand this properly now!

I am trying to learn more on C pointers. Tinkering around, I am questioning the difference between two actions I am using.

This code seems to work at first glance, but I am not sure of what's the difference, and if any of these two approaches is wrong in some way.

I'd like to know what's the difference between the two pieces of code, when I should I pass the adress, and when a pointer to an array?

Is any of the pieces wrong? If so, what would be the proper way?

having a simple struct grid pretty much like struct grid { int val; } (for demonstration purposes)

First piece of code. Passing address of the pointer to the array.

    void set (mygrid *grid, int foo){
        grid->bar = foo; //should this be '*grid->bar?' But this seems to work properly.
    }

    void main(){
        int i;
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);

        for(i = 0; i < max; i++){
            set(&array[i], 0);
        }
    }

Second piece of code. I am not entirely sure why this works, but the compiler doesn't output any warning. I am supposed to be passing the pointer to the start of the array like this?

    void set(mygrid *grid, int foo){
        int i; int max = 24; //so this example code compiles :P

        for(i = 0; i < max; i++){
            grid[i].bar = foo;
        }
    }

    void main(){
        int* array;
        int max = 24;

        array = malloc(sizeof(grid) * max);
        set(array, 0); //Why not &array?
    }
roger_rales
  • 191
  • 1
  • 2
  • 7
  • Beware the argument of that malloc. It should read `malloc(sizeof(mygrid)*max)`. I know it works because `mygrid` is exactly one int long, but it "smells" and feels bad :) – Gustavo Giráldez Aug 04 '11 at 02:12
  • Whoops! Good eyesight. I was wanting to do an array of ints at first, but then I remembered the specific example used an array of structs. Just in case it made a difference. And then I forgot to edit that malloc back :P – roger_rales Aug 04 '11 at 02:30

4 Answers4

2

Passing an array decays into a pointer that points to the first member of the array, just like &array[0].

alex
  • 479,566
  • 201
  • 878
  • 984
1

In your second example, array is just a pointer, and the return value from malloc is just the address of the start of the block of memory you get.

It doesn't have to be used for an array; it could be used for storage of an arbitrary sizeof(int) * max bytes of data. An array (in C) is really just a nice way of thinking about & working with a solid block of memory divided up into equal size portions.

Secondly, you should understand how my_array[i] works. All it does is take the address of where your block of array data starts (which is the actual value of my_array), and then look at what value is stored at a particular offset from there. Specifically, if my_array is of a (made up) type of WhatEver, then it will access the data from my_array + i*sizeof(WhatEver) to my_array + (i+1)*sizeof(WhatEver).

On a related note (since you're learning C), it's highly recommended to check that the return from malloc is not NULL before doing anything with it.

I'm no C guru but am also trying to improve my understanding so if this is incorrect, please leave a comment or edit my answer so I can learn from my mistakes :)

Caspar
  • 7,039
  • 4
  • 29
  • 41
  • Ah. I had a vague understanding of how that worked, but that makes it pretty clear. I was mostly confused about syntax and possible errors from wrong syntax. – roger_rales Aug 04 '11 at 02:36
  • Also good advice on the NULL pointers. Although, considering I am writing a small-ish app with no critical functions, the possibilities of it running out of memory should be small. Is it really worth checking for them unless it's a critical part? – roger_rales Aug 04 '11 at 02:42
  • I've always heard that it's essential to always check, because you can't predict what's going on under the covers to get you that memory (and it's supposed to be a good habit). [Wikipedia seems to agree](http://en.wikipedia.org/wiki/Malloc#Allocation_failure). On the other hand, [answers to this question](http://stackoverflow.com/questions/1941323/always-check-malloced-memory) seem to indicate it's not so clear cut, in that it may not be directly useful, but it isn't going to hurt. I suppose that if you want to fail fast or get into good habits then check it, otherwise consider the platform. – Caspar Aug 04 '11 at 03:21
  • Well, I happen to agree with many of the posters there. If we reached the point were the system cannot reserve a space for a small array of integers, the system is already unstable or under load, or even failing. Definitely not the environment to use my app into. Since my app is a mere on-demand tool, I'd better force quit when such a situation arises. There is no need to make it fight a low memory situation. I'll add checks in the functions that malloc and quit when NULL is found where it shouldn't. – roger_rales Aug 04 '11 at 13:03
0

In your first piece of code

grid->bar is same as (*grid).bar

. and using name of an array refers to its base address. so writing array is equivalent &array[0]

&array[i] is equivalent to array+i
array[i] is equivalent to *(array +i)

In you second piece of code i dont understand why there is no error because in your function set you do not declare max and i dont see a global max variable too. also in your second piece of code you use set(array,0) because array is already an integer pointer(see the declaration int * array).As far as i understand the mygrid is not a struct but is an array of structs in the second example

lovesh
  • 5,235
  • 9
  • 62
  • 93
  • Whoops, my bad, I wrote it as pseudocode with my focus being the pointer usage, sorry about that! So because array is pointing to int, passing the pointer is the same as passing the starting address, right? – roger_rales Aug 04 '11 at 02:41
  • @roger_rales yes passing the pointer is the same as passing the starting address of the int – lovesh Aug 04 '11 at 02:44
-1

In C, an array is pretty much the same as a pointer. For me this isn't so amazing, since it is one of the earlier programming languages I learned, but if you're coming from a high level language where an array is a different type of object, then it might come across as strange.

ThomasW
  • 16,981
  • 4
  • 79
  • 106
  • I asked because in the first example, I read I must do something like a(int* a){ *a = 3; }. However, trying to make my above example *grid->bar = foo instead of without the * sign, it causes this error: invalid type argument of unary ‘*’ (have ‘int’) – roger_rales Aug 04 '11 at 02:34