Thomas Jollans <t...@tjol.eu> writes: > On 2017-10-12 15:16, Ben Bacarisse wrote: >> Gregory Ewing <greg.ew...@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.
That's exactly what they are (in their simplest form). Other structures using pointers can be accessed in the same way so some people call those multi-dimensional arrays, but that can be a bit confusing. > 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. Exactly. This is why I raised this as an example where you get a pointer to an array type. int ** is something else altogether. When you pass an int[3][3] to a function, it pops up in the function as an int (*)[3]. You can (due to another of C's odd rules) write the parameter as int a[][3], or int a[3][3], but the first array in the declarator is replaced by a pointer (and the size is ignored). > If, say, you have variables of the types: > > int a[M][N], **b; > > then a[i][j] is equivalent to *(a+(i*M)+j), No it isn't. That expression does not even have type int. In fact you will be surprised to learn that a[i][j] it is equivalent to *(*(a+i)+j). > while b[i][j] is equivalent to *(*(b+i)+j). That much is true. The fact that the genuine 2D array access (a[i][j]) is equivalent an expression of the same form as the pointer to pointer access (b[i][j]) looks odd because, as you know, they are doing different things. But they do different things because the types are different. > Observe: <snip> > short multi_array[3][3] = { > {1, 0, 0}, > {0, 1, 0}, > {0, 0, 1} > }; > short *array_array[3]; I would not have used that name. This is an array of pointers. > /* 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)); Some people would find array_array[i] = malloc(sizeof multi_array[i]); memcpy(array_array[i], multi_array[i], sizeof multi_array[i]); to be clearer and more maintainable. You don't repeat the element type and there's no need to reference the (possibly arbitrary) size 3. It makes it very clear that enough space is being allocated for what is being copied. > } > > /* 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]); Try *(multi_array+(i*3)+j) here to see what happens (that's your re-write with 'a' and 'M' substituted). > } > puts(""); > } <snip> -- Ben. -- https://mail.python.org/mailman/listinfo/python-list