osdir.com


[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Lies in education [was Re: The "loop and a half"]


On 2017-10-12 15:16, Ben Bacarisse wrote:
> Gregory Ewing <greg.ewing at canterbury.ac.nz> writes:
> 
>> Ben Bacarisse wrote:
>>> That's a different type.  I think you mean that a human writing C
>>> (rather than bartc's code generator) would probably design the code to
>>> use tokenrec ** then I agree, but the latter is not just a different way
>>> to write the former.
>>
>> Yes, I was translating his English description of the type
>> into C, using C's meaning of the word "array". It seems that
>> arrays in the original language (Algol? One of Bart's
>> inventions?) are somewhat richer things.
> 
> Probably, but you can have pointers to array types in C which is what
> the posted type used.  Humans pass arrays in C by passing a pointer to
> the first element.  Pointers to arrays therefore crop up when passing 2D
> (or higher) arrays, even when the code is hand written by a person.
> 

No, actually. Multi-dimensional arrays in C are not arrays of arrays.
They look very similar, but when the dimensions of the array are known
at compile time, arrays of any rank are a continuous region of memory
with the data, and a pointer to the start.

Casting int[3][3] to int** will not do what you want it to do.

If, say, you have variables of the types:

int a[M][N], **b;

then a[i][j] is equivalent to *(a+(i*M)+j), while b[i][j] is equivalent
to *(*(b+i)+j).

Observe:

---------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char **argv)
{
    int i,j;
    /* multi-dimensional array: the compiler knows the dimensions! */
    short multi_array[3][3] = {
        {1, 0, 0},
        {0, 1, 0},
        {0, 0, 1}
    };
    short *array_array[3];

    /* fill array_array elements of multi_array */
    for(i=0; i<3; ++i) {
        array_array[i] = calloc(3, sizeof(short));
        /* This works because C arrays are row-major */
        memcpy(array_array[i], &multi_array[i][0], 3*sizeof(short));
    }

    /* print out the arrays */
    puts("multi_array:");
    for (i=0; i<3; ++i) {
        for (j=0; j<3; ++j) {
            printf("%d ", multi_array[i][j]);
        }
        puts("");
    }

    puts("array_array:");
    for (i=0; i<3; ++i) {
        for (j=0; j<3; ++j) {
            printf("%d ", array_array[i][j]);
        }
        puts("");
    }

    printf("&multi_array = 0x%llX\n", (long long)&multi_array);
    printf("*multi_array = 0x%llX\n", (long long)(*(short**)multi_array));
    printf("&array_array = 0x%llX\n", (long long)&array_array);
    printf("*array_array = 0x%llX\n", (long long)(*(short**)array_array));


    /* clean up */
    for (i=0; i<3; ++i) {
        free(array_array[i]);
    }

    return 0;
}

---------------------------------------------------------------------------

[OUTPUT]

multi_array:
1 0 0
0 1 0
0 0 1
array_array:
1 0 0
0 1 0
0 0 1
&multi_array = 0x7FFE0E736470
*multi_array = 0x1
&array_array = 0x7FFE0E736450
*array_array = 0x1A42010