gbadev.org forum archive

This is a read-only mirror of the content originally found on forum.gbadev.org (now offline), salvaged from Wayback machine copies. A new forum can be found here.

Coding > Passing an array by adress

#26169 - funkeejeffou - Wed Sep 08, 2004 8:55 pm

Hi,

I'm using an array that is declared like that :
Code:
int tab[10][6]

And I would like to work on it by passing it's adress like :
Code:
int **temp;
temp = tab;
temp[3][4] = 5;


But this doesn't work, and I cannot figure out how to do this in a simple manner.
Help would be appreciated ;)


Cheers, Jeff.

#26170 - poslundc - Wed Sep 08, 2004 9:47 pm

Fixed-size multidimensional arrays in C are represented internally by single pointers, not double pointers. Then to index into the array, the row index is multiplied by the width of the array before adding the column index.

Because of this, you can reference the data as follows if you want:

Code:
int tab[10][6];
int *temp = tab;
*(temp + (3 * 6) + 4) = 5;     // same as temp[3][4] = 5;


IIRC, there is a bizarre/obscure notation for declaring your variable if you want to use temp as a direct alias of tab (I think it may be something like int *[6]temp but I'm not 100% on that).

Dan.

#26171 - isildur - Wed Sep 08, 2004 9:48 pm

Edit: Ooops I posted at the same time as poslundc...

I don't know if it's possible to use a pointer with a multi-dimension array syntax but you can do something like this:

Code:


#define SECOND_DIM_SIZE     6

int tab[10][SECOND_DIM_SIZE];
int *temp;

temp = (int*)tab;

//temp[3][4] = 5;

*(temp + (3*SECOND_DIM_SIZE) + 4) = 5;



It's not pretty but if you must do it like that, it will work.


Last edited by isildur on Thu Sep 09, 2004 1:16 am; edited 2 times in total

#26172 - funkeejeffou - Wed Sep 08, 2004 9:53 pm

Yeah I knew I could do it like this, the problem is most of my lines will get even bigger, that is why I would like keeping the original syntax(tab[10][6]) and I said a simple way.

Is it the only way?

#26175 - poslundc - Wed Sep 08, 2004 10:05 pm

I googled that alternate notation for you... it is:

Code:
int (*temp)[2] = tab;


Dan.

#26176 - sajiimori - Wed Sep 08, 2004 10:10 pm

Quote:
Fixed-size multidimensional arrays in C are represented internally by single pointers, not double pointers.
Noooo! ;P Fixed-size multidimensional arrays in C are represented internally as flat arrays. They just happen to return a pointer to their starting address when referenced, and that's a C quirk that doesn't reflect the actual representation. In other words, there is no pointer!

#26180 - poslundc - Wed Sep 08, 2004 10:55 pm

Can you explain the distinction between a flat array and a pointer in terms of internal representation?

Dan.

#26183 - tepples - Thu Sep 09, 2004 12:07 am

A flat array most often has a sizeof() greater than four.
_________________
-- Where is he?
-- Who?
-- You know, the human.
-- I think he moved to Tilwick.

#26185 - sajiimori - Thu Sep 09, 2004 12:44 am

To put it another way:
Code:

a_pointer: .word who_knows_where
an_array: .space some_size

Arrays are arbitrarily-sized blocks of memory, and pointers are addresses. You'd think this is obvious, but C really makes it look like arrays are pointers. Really, there is no relationship between the two except that referring to an array by name returns a pointer to its start.

Even the fact that you can index into them with [] is not a relationship between arrays and pointers. p[i] is just short for *(p+i), and it happens to work when p is an array because referring to p returns a pointer to its start. [] really needs a pointer as its left argument.

#26186 - poslundc - Thu Sep 09, 2004 1:41 am

Okay, that's sensible enough, but in terms of how a program's code addresses the content of an array or the content of arbitrary data from a pointer, the two are virtually indistinguishable.

Dan.

#26187 - sajiimori - Thu Sep 09, 2004 1:51 am

If by "a program's code" you mean its source (and not its compiled output), then that's true enough, for the sole reason that C returns a pointer when you say an array's name.

#26189 - Marciano - Thu Sep 09, 2004 3:12 am

funkeejeffou wrote:
Hi,

I'm using an array that is declared like that :
Code:
int tab[10][6]

And I would like to work on it by passing it's adress like :
Code:
int **temp;
temp = tab;
temp[3][4] = 5;


But this doesn't work, and I cannot figure out how to do this in a simple manner.
Help would be appreciated ;)


Cheers, Jeff.

If you're passing to a function you can just do:
Code:

void
foo(int p[10][6])
{
    p[3][4] = 5;
}

void
main()
{
    int tab[10][6];

    foo(tab);
}

If you have an extern array, and you want to use a pointer, you can:
Code:

int tab[10][6];

void
func()
{
    int (*p)[10][6] = (int (*)[10][6])tab;

    (*p)[3][4] = 5;
}

#26196 - poslundc - Thu Sep 09, 2004 12:29 pm

sajiimori wrote:
If by "a program's code" you mean its source (and not its compiled output), then that's true enough, for the sole reason that C returns a pointer when you say an array's name.


I'm also referring to the ASM implementation... since a local array will be placed on the stack, its contents will be referenced by a pointer. Same with a global array, since it usually can't be referenced by a PC-relative address. IOW, the an_array: .space some_size you mentioned earlier will almost always be accompanied by the a_pointer: .word an_array version somewhere in the code.

Dan.

#26199 - keldon - Thu Sep 09, 2004 1:55 pm

Code:
MyArray [10][8]

When you refer to MyArray[x][y], you will be returned data held at [x][y].

When you refer to MyArray (by itself), you will be returned a pointer to the first byte of data in the array. So in assembler you can only have a pointer to the first byte of data, or one of the arrays values.

So if you are creating an assembler function that handles variable array sizes, simply include a parameter for the arrays dimensions.

#26215 - sajiimori - Thu Sep 09, 2004 6:21 pm

Quote:
I'm also referring to the ASM implementation... since a local array will be placed on the stack, its contents will be referenced by a pointer. Same with a global array, since it usually can't be referenced by a PC-relative address. IOW, the an_array: .space some_size you mentioned earlier will almost always be accompanied by the a_pointer: .word an_array version somewhere in the code.
Understood. Now let me explain why you're still wrong.

Let's take the global scenario. Like you said, you almost always refer to an array via a pointer in the pool. Dereferencing that pointer will get you the address of the start of the array, which is an arbitrarily-sized block of memory.

What if you were accessing a global pointer? It would presumably still not be accessible via a PC offset, so a pointer would be in the pool. Dereferencing that pointer will get you the address of the global pointer, which is exactly the size of an address, and not at all array-like. If that global pointer points to an array, then you can dereference the global pointer to get the start of the array, and then add to that to get the element.

Accessing an array via a pointer involves an extra dereference (and 4 more bytes of memory), and so the implementation is different.

In case you missed the key: you need a pointer to be in the pool either way. When you're accessing an array directly, that's the only pointer needed. When you're accessing an array via a global pointer, then there are 2 pointers.

In the local array situation, you're kind of stretching it by saying that it has to be accessed via a pointer. There is no pointer in memory, and the pointer in question is merely sp. In that case, you have to access all local variables via a pointer, including local pointers. So again, there would be 1 dereference when accessing an array directly, or 2 dereferences when accessing an array via a pointer.

I hope this will put the whole thing to rest.

#26219 - poslundc - Thu Sep 09, 2004 7:14 pm

sajiimori wrote:
Let's take the global scenario. Like you said, you almost always refer to an array via a pointer in the pool. Dereferencing that pointer will get you the address of the start of the array, which is an arbitrarily-sized block of memory.

What if you were accessing a global pointer? It would presumably still not be accessible via a PC offset, so a pointer would be in the pool. Dereferencing that pointer will get you the address of the global pointer, which is exactly the size of an address, and not at all array-like. If that global pointer points to an array, then you can dereference the global pointer to get the start of the array, and then add to that to get the element.


Okay, I'll buy that if you're comparing a global array to a global pointer variable. But that's only the case if you're comparing it to a global pointer. If you're comparing either a global array or an array that is passed into a function to the internal representation of a local pointer variable or a pointer that is passed into a function (both much more common uses of pointers than global pointer variables) then they behave the same way.

Quote:
In the local array situation, you're kind of stretching it by saying that it has to be accessed via a pointer. There is no pointer in memory, and the pointer in question is merely sp. In that case, you have to access all local variables via a pointer, including local pointers. So again, there would be 1 dereference when accessing an array directly, or 2 dereferences when accessing an array via a pointer.


It seems to me that a compiler would treat a local array the same way as it would a pointer to a local variable: either as a direct offset to SP or as a register storing an SP-related offset. One dereference to access an element of the array; one dereference to access the data contained in the pointer.

Quote:
Understood. Now let me explain why you're still wrong.

...

I hope this will put the whole thing to rest.


I'm sorry if my questions offend your sense of incontrovertible correctness.

Sheesh, what crawled up your ass and died?

Dan.

#26220 - sajiimori - Thu Sep 09, 2004 7:33 pm

Something's different about you recently, Dan. I hope everything is ok. :(

#26221 - poslundc - Thu Sep 09, 2004 8:09 pm

I am fine. I just don't fathom why you take offence at my desire for more persuasion on this matter. I am not yet convinced that the compiler treats flat arrays differently from pointers in the majority of cases. Statements like "let me explain why you're still wrong" and "I hope this puts the whole thing to rest" seem geared towards putting me in my place rather than providing a compelling explanation.

I have nothing to prove or win by disputing your claim, but I have always treated arrays and pointers as practically interchangeable. If there's a better reason than "sajimori says so" that I shouldn't be doing it or espousing that point of view to others, then I'd like to know it. That's why I asked.

Dan.

#26226 - sajiimori - Thu Sep 09, 2004 8:55 pm

I don't know what you mean by "majority of cases", but yes, when you type this:
Code:
int array[10]; f(array);
a pointer gets passed, for obvious reasons. f accepts a pointer, and it doesn't care where the pointer comes from, even if the pointer happened to be the address of the start of an array. Any work that f does with its argument will involve all the normal operations that are associated with pointer manipulation.

So, f isn't really an example of working directly with arrays, and the issue is whether there is an implementation difference between working directly with arrays and working with pointers to arrays.

f will always be working with a pointer (because C can't pass arrays), but the caller can work directly with the array, which is implemented differently, and that is the entirety of my point. Maybe you could clarify which part you disagree with.

#26244 - poslundc - Fri Sep 10, 2004 2:01 am

sajiimori wrote:
f will always be working with a pointer (because C can't pass arrays), but the caller can work directly with the array, which is implemented differently, and that is the entirety of my point. Maybe you could clarify which part you disagree with.


OK, I can see that when looking exclusively from the caller's perspective. I think the only other thing is that while pointer assigning isn't implemented the same as arrays, pointer creation through the referencing operator is. ie.

Code:
int a[10];
int *b;

int main(void)
{
     int *pa = a;
     int *pb = b;
}


In this example, pb will take an extra dereferencing to obtain its value as opposed to pa. It is my understanding that this is the main reason you claim that arrays and pointers aren't so closely related implementation-wise. On the other hand,

Code:
int a[10];
int b;

int main(void)
{
     int *pa = a;
     int *pb = &b;
}


... the two lines are functionally identical.

I guess the distinction is talking about pointers and pointer variables... you've convinced me that pointer variables are different from arrays, but I still think it's correct to say that arrays operate the same way as pointers (if not necessarily pointer variables) do.

Dan.

#26245 - sajiimori - Fri Sep 10, 2004 2:51 am

Quote:
I guess the distinction is talking about pointers and pointer variables... you've convinced me that pointer variables are different from arrays, but I still think it's correct to say that arrays operate the same way as pointers (if not necessarily pointer variables) do.
Yes, arrays must be accessed by their addresses, just like all in-memory variables.