The size of the matrices varies: 2x2, 3x2, etc. but is always defined in the function header. I don't need all matrices simultaneously. Is it allowed to pass an array that has larger dimensions (i.e. those of the largest matrix) than specified in the function header? Currently I tried this: ============================================================ #include <stdio.h>
============================================================ Although the compiler takes it and the executable prints the desired result, it seems a bit odd to me. The function pointer seems to suppress the information of the array size. Without this intermediate step the compiler throws an error (which might be already a hint that the code is not valid). The only other way a can think of is to create a bunch of buffers and decide at each call which I have to use.
Probably the easier way to do this sort of anonymous thing is use a 1D array then access it via macro
#define M(i, j) R[i*width+j]
Where "width" is a constant that the compiler can optimize [e.g. *4 == <<2 and so on, or more importantly just access the array with known offsets if it unrolls your code or whatever].
The only other way I can think of doing this is with structs, e.g.
struct twobytwo { double M[2][2]; }
then you pass
void func(struct twobytwo *M);
Then you can have anonymous matrix functions that take (void *) and they internally cast it to a pointer of the right struct. I can't think of how you'd declare "a pointer to an array of 2 of array of 2 doubles" ...
> The size of the matrices varies: 2x2, 3x2, etc. but is always defined in > the function header.
Well, sort of. The first [2] is just decoration, the second [2] actually matters. After "decay," the parameter of getMatrix() is a pointer, whose target type is array-of-two-double.
> I don't need all matrices simultaneously. Is it > allowed to pass an array that has larger dimensions (i.e. those of the > largest matrix) than specified in the function header? Currently I tried > this: > ============================================================ > #include <stdio.h>
No good, because you get only one level of "decay." This line tries to declare fnc as a pointer to a function whose parameter is a pointer to an array of unknown size -- not a pointer to the first element of such an array, but a pointer to the entire array. Since the array's size is unknown, it's an "incomplete type."
The parameter of getMatrix() is not a pointer to an array of an unknown number of double elements, but a pointer to an array of two double elements. Thus, the type of getMatrix() disagrees with the type of function fcn is supposed to point at. You ought to get a diagnostic here.
> (*fnc)( A );
... but if the code compiled anyhow, this is undefined behavior. You're calling a function of one type through a pointer to functions of a different type, and that's a no-no.
> return 0; > } > ============================================================ > Although the compiler takes it and the executable prints the desired > result, it seems a bit odd to me.
I'd suggest getting another compiler, or cranking up the warning levels on the one you already have. gcc tells me
foo.c: In function 'main': foo.c:19: error: array type has incomplete element type foo.c:21: error: type of formal parameter 1 is incomplete
> The function pointer seems to suppress > the information of the array size. Without this intermediate step the > compiler throws an error (which might be already a hint that the code is > not valid). The only other way a can think of is to create a bunch of > buffers and decide at each call which I have to use.
C's handling of multi-dimensional arrays is a bit clumsy, and can make trouble in situations like yours. The comp.lang.c Frequently Asked Questions (FAQ) list at <http://www.c-faq.com/> may prove useful, particularly Questions 6.19 and 6.21 -- it's probably worth your while to look at all of Section 6.
> Probably the easier way to do this sort of anonymous thing is use a 1D > array then access it via macro
> #define M(i, j) R[i*width+j]
> Where "width" is a constant that the compiler can optimize [e.g. *4 == > <<2 and so on, or more importantly just access the array with known > offsets if it unrolls your code or whatever].
Thanks for your fast reply. If I got it right, you suggest to avoid the use of a 2D array and stick to 1d one. Properly I missed your point how to implement it, but does it require a change in getMatrix?
I didn't mentioned it clearly in the first posting: the "getMatrix" function is generated "somewhere else". Thus, I have no control there. I could post process the function and try to change the definitions, but i would prefer to leave these functions untouched.
> The only other way I can think of doing this is with structs, e.g.
> struct twobytwo { double M[2][2]; }
> then you pass
> void func(struct twobytwo *M);
> Then you can have anonymous matrix functions that take (void *) and > they internally cast it to a pointer of the right struct. I can't > think of how you'd declare "a pointer to an array of 2 of array of 2 > doubles" ...
>> The size of the matrices varies: 2x2, 3x2, etc. but is always defined >> in the function header.
> Well, sort of. The first [2] is just decoration, the second [2] > actually matters. After "decay," the parameter of getMatrix() is > a pointer, whose target type is array-of-two-double.
The functions I deal with are generated by an other program, which put both numbers there. Of course the "getMatrix"-thing wasn't, but just entered by hand so I could left the first one. Sorry for that but I thought it would be better to stick close to the real situation.
>> I don't need all matrices simultaneously. Is it allowed to pass an >> array that has larger dimensions (i.e. those of the largest matrix) >> than specified in the function header? Currently I tried this: >> ============================================================ >> #include <stdio.h>
> No good, because you get only one level of "decay." This line > tries to declare fnc as a pointer to a function whose parameter is > a pointer to an array of unknown size -- not a pointer to the first > element of such an array, but a pointer to the entire array. Since > the array's size is unknown, it's an "incomplete type."
> The parameter of getMatrix() is not a pointer to an array of an > unknown number of double elements, but a pointer to an array of two > double elements. Thus, the type of getMatrix() disagrees with the > type of function fcn is supposed to point at. You ought to get a > diagnostic here.
I invoked gcc with the following options: <gcc -W -Wall -pedantic -ansi testarray.c> the version is <gcc --version> --> 2.95.3 Nothing newer available (ansi added afterwards, it warns about the semicolon).
>> (*fnc)( A );
> ... but if the code compiled anyhow, this is undefined behavior. > You're calling a function of one type through a pointer to functions > of a different type, and that's a no-no.
Ok, thank you. I had that strange feeling, because without that conversion the diagnostic triggered.
> C's handling of multi-dimensional arrays is a bit clumsy, and can > make trouble in situations like yours. The comp.lang.c Frequently > Asked Questions (FAQ) list at <http://www.c-faq.com/> may prove useful, > particularly Questions 6.19 and 6.21 -- it's probably worth your while > to look at all of Section 6.
I read Q6.19 but since I would like to leave the elsewhere generated code untouched, the suggested 1D array doesn't work for me. Is keeping a bunch of arrays as buffers then the way to go (without that function pointer thing of course) or exists an other solution?
No, you don't have a function with a 2-dimensional array as a parameter, because there's no such thing in C as an array parameter.
Yes, you have something that *looks* like an array parameter, but it really isn't. The parameter declaration double M[2][2] is quietly translated to double (*M)[2] i.e., M is really a pointer to an array of 2 doubles. Typically, it will point to the first element of an array of arrays of 2 doubles. The second "2" in the parameter declaration is silently ignored.
-- Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"
> Then you can have anonymous matrix functions that take (void *) and > they internally cast it to a pointer of the right struct. I can't > think of how you'd declare "a pointer to an array of 2 of array of 2 > doubles" ...
% cdecl Type `help' or `?' for help cdecl> declare p as pointer to array 2 of array 2 of double double (*p)[2][2] cdecl> %
-- Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"
> No, you don't have a function with a 2-dimensional array as a > parameter, because there's no such thing in C as an array parameter.
> Yes, you have something that *looks* like an array parameter, > but it really isn't. The parameter declaration > double M[2][2] > is quietly translated to > double (*M)[2] > i.e., M is really a pointer to an array of 2 doubles. Typically, it > will point to the first element of an array of arrays of 2 doubles. > The second "2" in the parameter declaration is silently ignored.
The *first* "2" in the parameter declaration is silently ignored.
pete <pfil...@mindspring.com> writes: > Keith Thompson wrote: >> Michael <michaelk...@googlemail.com> writes: >>>I've a couple of (automatically) created functions that take >>>2-dimensional array as inputs, like
>>>void getMatrix( double M[2][2] ) [...]
>> No, you don't have a function with a 2-dimensional array as a >> parameter, because there's no such thing in C as an array parameter.
>> Yes, you have something that *looks* like an array parameter, >> but it really isn't. The parameter declaration >> double M[2][2] >> is quietly translated to >> double (*M)[2] >> i.e., M is really a pointer to an array of 2 doubles. Typically, it >> will point to the first element of an array of arrays of 2 doubles. >> The second "2" in the parameter declaration is silently ignored.
> The *first* "2" in the parameter declaration is silently ignored.
% cdecl Type `help' or `?' for help cdecl> declare M as array 10 of array 20 of double double M[10][20] cdecl> declare M as pointer to array 20 of double double (*M)[20] cdecl> %
-- Keith Thompson (The_Other_Keith) ks...@mib.org <http://www.ghoti.net/~kst> Nokia "We must do something. This is something. Therefore, we must do this." -- Antony Jay and Jonathan Lynn, "Yes Minister"
>> Probably the easier way to do this sort of anonymous thing is use a 1D >> array then access it via macro
>> #define M(i, j) R[i*width+j]
>> Where "width" is a constant that the compiler can optimize [e.g. *4 == >> <<2 and so on, or more importantly just access the array with known >> offsets if it unrolls your code or whatever].
> Thanks for your fast reply. If I got it right, you suggest to avoid > the use of a 2D array and stick to 1d one. Properly I missed your > point how to implement it, but does it require a change in getMatrix?
> I didn't mentioned it clearly in the first posting: the "getMatrix" > function is generated "somewhere else". Thus, I have no control > there. I could post process the function and try to change the > definitions, but i would prefer to leave these functions untouched.
Can you change the type? If so there is another way: and array of pointers -- each one points to the start of a 1D array. Access looks exactly the same so the body of the getMatrix code is the same.
The advantage is that you can access the 2x2 part of, say, a 3x3 matrix seamlessly this way (which, unless I've misread the situation is you problem). The down side is that it is more complex to allocate and free such things.
Forgive me for not saying more now, but since it may not be a solution it seems a waste of time to explain it in detail.
>>>> return 0;} >>> Probably the easier way to do this sort of anonymous thing is use a 1D >>> array then access it via macro
>>> #define M(i, j) R[i*width+j]
>>> Where "width" is a constant that the compiler can optimize [e.g. *4 == >>> <<2 and so on, or more importantly just access the array with known >>> offsets if it unrolls your code or whatever]. >> Thanks for your fast reply. If I got it right, you suggest to avoid >> the use of a 2D array and stick to 1d one. Properly I missed your >> point how to implement it, but does it require a change in getMatrix?
>> I didn't mentioned it clearly in the first posting: the "getMatrix" >> function is generated "somewhere else". Thus, I have no control >> there. I could post process the function and try to change the >> definitions, but i would prefer to leave these functions untouched.
> Can you change the type? If so there is another way: and array of > pointers -- each one points to the start of a 1D array. Access looks > exactly the same so the body of the getMatrix code is the same.
> The advantage is that you can access the 2x2 part of, say, a 3x3 > matrix seamlessly this way (which, unless I've misread the situation > is you problem). The down side is that it is more complex to allocate > and free such things.
Hi, well that sounds good to me. I cannot change the the type during the "creation" of the function, but it looks to me that I can do the change afterwards automatically. So the solution would look like this? ============================================================= #include <stdio.h> #include <stdlib.h> /*Maybe drop the 2 in next 2 lines?*/ void getMatrix( double *M[2] ); void getMatrix( double *M[2] ) { M[0][0] = 1; M[0][1] = 0; M[1][0] = 0; M[1][1] = 1;
============================================================= Well, then also Q.6.19 is on topic as Eric mentioned. So thanks there again. Since it is a 1D array can I drop the number in <<getMatrix>>? My compiler accepts it but it didn't warn about the other thing either.
> Forgive me for not saying more now, but since it may not be a solution > it seems a waste of time to explain it in detail.
I'm perfectly happy with your response. You already (like all others) spend time to help me, which I really appreciate. Thanks for support again.
Keith Thompson wrote: > pete <pfil...@mindspring.com> writes: >> Keith Thompson wrote: >>> Michael <michaelk...@googlemail.com> writes: >>>> I've a couple of (automatically) created functions that take >>>> 2-dimensional array as inputs, like
>>>> void getMatrix( double M[2][2] ) > [...] >>> No, you don't have a function with a 2-dimensional array as a >>> parameter, because there's no such thing in C as an array parameter.
>>> Yes, you have something that *looks* like an array parameter, >>> but it really isn't. The parameter declaration >>> double M[2][2] >>> is quietly translated to >>> double (*M)[2] >>> i.e., M is really a pointer to an array of 2 doubles. Typically, it >>> will point to the first element of an array of arrays of 2 doubles. >>> The second "2" in the parameter declaration is silently ignored. >> The *first* "2" in the parameter declaration is silently ignored.
> % cdecl > Type `help' or `?' for help > cdecl> declare M as array 10 of array 20 of double > double M[10][20] > cdecl> declare M as pointer to array 20 of double > double (*M)[20] > cdecl> > %
>>>>> I've a couple of (automatically) created functions that take >>>>> 2-dimensional array as inputs, like
>>>>> void getMatrix( double M[2][2] )
>> [...]
>>>> No, you don't have a function with a 2-dimensional array as a >>>> parameter, because there's no such thing in C as an array parameter.
>>>> Yes, you have something that *looks* like an array parameter, >>>> but it really isn't. The parameter declaration >>>> double M[2][2] >>>> is quietly translated to >>>> double (*M)[2] >>>> i.e., M is really a pointer to an array of 2 doubles. Typically, it >>>> will point to the first element of an array of arrays of 2 doubles. >>>> The second "2" in the parameter declaration is silently ignored.
>>> The *first* "2" in the parameter declaration is silently ignored.
>> % cdecl >> Type `help' or `?' for help >> cdecl> declare M as array 10 of array 20 of double >> double M[10][20] >> cdecl> declare M as pointer to array 20 of double >> double (*M)[20] >> cdecl> >> %
> Thanks to you two for clarifying that.
You're welcome.
For an array definition like this:
e_type array_1[A][B][C][D];
There are (A) number of elements in array_1. The size of each element is (B * C * D * sizeof e_type) bytes.
When initializing an array definition, or deriving a pointer to the first element an array, the size information for the array elements is still needed; but the number of elements in the array is not still needed.
e_type array_1[][B][C][D] = {0};
e_type (*pter_1)[B][C][D] = array_1;
That's why it's (The *first* "2") which is silently ignored, instead of the second one.
>>>>> return 0;} >>>> Probably the easier way to do this sort of anonymous thing is use a 1D >>>> array then access it via macro
>>>> #define M(i, j) R[i*width+j]
>>>> Where "width" is a constant that the compiler can optimize [e.g. *4 == >>>> <<2 and so on, or more importantly just access the array with known >>>> offsets if it unrolls your code or whatever]. >>> Thanks for your fast reply. If I got it right, you suggest to avoid >>> the use of a 2D array and stick to 1d one. Properly I missed your >>> point how to implement it, but does it require a change in getMatrix?
>>> I didn't mentioned it clearly in the first posting: the "getMatrix" >>> function is generated "somewhere else". Thus, I have no control >>> there. I could post process the function and try to change the >>> definitions, but i would prefer to leave these functions untouched.
>> Can you change the type? If so there is another way: and array of >> pointers -- each one points to the start of a 1D array. Access looks >> exactly the same so the body of the getMatrix code is the same.
>> The advantage is that you can access the 2x2 part of, say, a 3x3 >> matrix seamlessly this way (which, unless I've misread the situation >> is you problem). The down side is that it is more complex to allocate >> and free such things.
> Hi, well that sounds good to me. I cannot change the the type during > the "creation" of the function, but it looks to me that I can do the > change afterwards automatically.
I'm sorry, but I don't understand this. However, I don't really need to! If the solution works for you, then I'm happy.
> So the solution would look like this? > ============================================================= > #include <stdio.h> > #include <stdlib.h> > /*Maybe drop the 2 in next 2 lines?*/ > void getMatrix( double *M[2] ); > void getMatrix( double *M[2] )
Yes, see later. Note that there is no point in writing a prototype for a function just before a "full" definition of it (though it does no harm either). You /can/ define a function in such a way that it doesn't act as a prototype as well, but why would you?
> return 0; > } > ============================================================= > Well, then also Q.6.19 is on topic as Eric mentioned. So thanks there > again. Since it is a 1D array can I drop the number in > <<getMatrix>>?
Yup. In fact, some people prefer to write:
void getMatrix( double M[][] ) { ... }
because it makes the "arrayness" more explicit. You can also write:
which are all essentially the same. I've never been able to decide which is the best -- probably because it does not matter!
<snip>
> I'm perfectly happy with your response. You already (like all others) > spend time to help me, which I really appreciate. Thanks for support > again.
>>>>>> return 0;} >>>>> Probably the easier way to do this sort of anonymous thing is use a 1D >>>>> array then access it via macro
>>>>> #define M(i, j) R[i*width+j]
>>>>> Where "width" is a constant that the compiler can optimize [e.g. *4 == >>>>> <<2 and so on, or more importantly just access the array with known >>>>> offsets if it unrolls your code or whatever]. >>>> Thanks for your fast reply. If I got it right, you suggest to avoid >>>> the use of a 2D array and stick to 1d one. Properly I missed your >>>> point how to implement it, but does it require a change in getMatrix?
>>>> I didn't mentioned it clearly in the first posting: the "getMatrix" >>>> function is generated "somewhere else". Thus, I have no control >>>> there. I could post process the function and try to change the >>>> definitions, but i would prefer to leave these functions untouched. >>> Can you change the type? If so there is another way: and array of >>> pointers -- each one points to the start of a 1D array. Access looks >>> exactly the same so the body of the getMatrix code is the same.
>>> The advantage is that you can access the 2x2 part of, say, a 3x3 >>> matrix seamlessly this way (which, unless I've misread the situation >>> is you problem). The down side is that it is more complex to allocate >>> and free such things. >> Hi, well that sounds good to me. I cannot change the the type during >> the "creation" of the function, but it looks to me that I can do the >> change afterwards automatically.
> I'm sorry, but I don't understand this. However, I don't really need > to! If the solution works for you, then I'm happy.
oops, let me have an other try: I get a function (getMatrix like) completely as source with header file. I cannot change the way the code is created. The definition of the matrix will always be done in the M[X][Y] style. But of course I can run a script that parses the code and change "double M[X][Y]" in the parameter list to "double *M[]". Thats why I am so happy that the modification only affects one line. (I know it would be better to refactor(?) the code but i lack a good tool and this might be off topic here). -- Hmm, I'm not sure if this explains the situation better.
>> So the solution would look like this? >> ============================================================= >> #include <stdio.h> >> #include <stdlib.h> >> /*Maybe drop the 2 in next 2 lines?*/ >> void getMatrix( double *M[2] ); >> void getMatrix( double *M[2] )
> Yes, see later. Note that there is no point in writing a prototype > for a function just before a "full" definition of it (though it does > no harm either). You /can/ define a function in such a way that it > doesn't act as a prototype as well, but why would you?
Ok, point taken :-). I once copied a bunch of warnings-switches posted in this group to my makefile including "-Wmissing-prototypes". I fear i added the line just to suppress the warning.
> because it makes the "arrayness" more explicit. You can also write:
Not standardly. In C89 it *may* work; the element type must be complete (i.e. not itself array-of-unspecified), but it is not clear if that is enforced before or after the 'adjustment' of an array parameter to pointer (and pointer to array-of-unspecified is OK). I have in fact had implementations go both ways on this point.
In C99 it is now a constraint on the declarator, which strongly implies that it is illegal before the adjustment. Of course after generating the required diagnostic, the compiler can continue to give the same quite reasonable meaning that was allowed in C89.
> which are all essentially the same. I've never been able to decide > which is the best -- probably because it does not matter!
No. Both of these are actually pointer to one or more pointer(s), each to one or more double, i.e. pointer to row-pointer(s). That is a quite different thing than an actual 2D-array or array-of-array, although you can access both of them with two subscripts similarly in C. I like to call this a *2-level* (or *N-level*) array to distinguish it.
David Thompson <dave.thomps...@verizon.net> writes: > On Fri, 30 Oct 2009 13:32:08 +0000, Ben Bacarisse > <ben.use...@bsb.me.uk> wrote:
> <snip: most about passing 2D array>
>> Yup. In fact, some people prefer to write:
>> void getMatrix( double M[][] ) { ... }
>> because it makes the "arrayness" more explicit. You can also write:
> Not standardly. In C89 it *may* work; the element type must be > complete (i.e. not itself array-of-unspecified), but it is not clear > if that is enforced before or after the 'adjustment' of an array > parameter to pointer (and pointer to array-of-unspecified is OK). > I have in fact had implementations go both ways on this point.
Just so I am clear, the "both" ways you refer to are:
(a) silently accepting the parameter's type as if it have been written double (*M)[] and
(b) complaining the array element type is not complete?
> In C99 it is now a constraint on the declarator,
<ben.use...@bsb.me.uk> wrote: > David Thompson <dave.thomps...@verizon.net> writes:
> > On Fri, 30 Oct 2009 13:32:08 +0000, Ben Bacarisse > > <ben.use...@bsb.me.uk> wrote: > >> void getMatrix( double M[][] ) { ... } > > Not standardly. In C89 it *may* work; the element type must be > > complete (i.e. not itself array-of-unspecified), but it is not clear > > if that is enforced before or after the 'adjustment' of an array > > parameter to pointer (and pointer to array-of-unspecified is OK). > > I have in fact had implementations go both ways on this point.
> Just so I am clear, the "both" ways you refer to are:
> (a) silently accepting the parameter's type as if it have been > written double (*M)[] and
I won't swear to silent; there may have been a warning; I'm not religious about avoiding warnings if I satisfy myself it's not a real problem. But compiling it okay as the (adjusted) pointer type, yes.
> (b) complaining the array element type is not complete?