Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #125940 > unrolled thread
| Started by | August Karlstrom <fusionfile@gmail.com> |
|---|---|
| First post | 2018-01-29 10:40 +0100 |
| Last post | 2018-01-29 21:35 +0100 |
| Articles | 7 — 5 participants |
Back to article view | Back to comp.lang.c
Treating a multi-dimensional array as one-dimensional August Karlstrom <fusionfile@gmail.com> - 2018-01-29 10:40 +0100
Re: Treating a multi-dimensional array as one-dimensional Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-01-29 11:00 +0000
Re: Treating a multi-dimensional array as one-dimensional supercat@casperkitty.com - 2018-01-29 07:58 -0800
Re: Treating a multi-dimensional array as one-dimensional Nick Bowler <nbowler@draconx.ca> - 2018-01-29 22:38 +0000
Re: Treating a multi-dimensional array as one-dimensional Ben Bacarisse <ben.usenet@bsb.me.uk> - 2018-01-29 23:07 +0000
Re: Treating a multi-dimensional array as one-dimensional Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2018-01-29 03:29 -0800
Re: Treating a multi-dimensional array as one-dimensional August Karlstrom <fusionfile@gmail.com> - 2018-01-29 21:35 +0100
| From | August Karlstrom <fusionfile@gmail.com> |
|---|---|
| Date | 2018-01-29 10:40 +0100 |
| Subject | Treating a multi-dimensional array as one-dimensional |
| Message-ID | <p4mq61$1k5n$1@gioia.aioe.org> |
I need to define a function which can handle two-dimensional array
parameters of any size (both dimensions). The code below illustrates my
current approach.
#include <stdio.h>
#define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
static void Print(const int *A, int m, int n)
{
int i, j;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%d ", A[i * n + j]);
}
putchar('\n');
}
}
int main(void)
{
int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
Print((int *) A, LEN(A), LEN(A[0]));
return 0;
}
I posted this question on StackOverflow(*) and it was suggested that It
violates the strict aliasing rule. Is there a different way to solve
this problem?
*https://stackoverflow.com/questions/48491951/can-i-treat-a-multi-dimensional-array-as-a-one-dimensional-array
-- August
[toc] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2018-01-29 11:00 +0000 |
| Message-ID | <87inblexpp.fsf@bsb.me.uk> |
| In reply to | #125940 |
August Karlstrom <fusionfile@gmail.com> writes:
> I need to define a function which can handle two-dimensional array
> parameters of any size (both dimensions). The code below illustrates
> my current approach.
>
> #include <stdio.h>
>
> #define LEN(arr) (sizeof (arr) / sizeof (arr)[0])
>
> static void Print(const int *A, int m, int n)
> {
> int i, j;
>
> for (i = 0; i < m; i++) {
> for (j = 0; j < n; j++) {
> printf("%d ", A[i * n + j]);
> }
> putchar('\n');
> }
> }
>
> int main(void)
> {
> int A[2][3] = {{1, 2, 3}, {4, 5, 6}};
>
> Print((int *) A, LEN(A), LEN(A[0]));
> return 0;
> }
>
> I posted this question on StackOverflow(*) and it was suggested that
> It violates the strict aliasing rule. Is there a different way to
> solve this problem?
Yes. If the array size (specifically the row length) is not known at
compile time you can do this as of C99:
static void Print(int m, int n, int A[m][n])
{
int i, j;
for (i = 0; i < m; i++) {
for (j = 0; j < n; j++) {
printf("%d ", A[i][j]);
}
putchar('\n');
}
}
Note the parameter order and the deleted const. The new order is needed
but the const has gone simply to avoid a problem C has with const where
there is more than one level of indirection.
If at least the row size (3 in this case) is known at compile time you
need no "new" features: Just pass a pointer to the first array
element -- an array of 3 int:
static void Print(int (*A)[3], int m)
but the fact that you pass both m and n suggests this won't be suitable.
As for the "strict aliasing" issue, that's a red herring. The code that
treats a 2D array as a 1D array is technically undefined for reasons
that have nothing to do with aliasing. I doubt, though, that you will
come across a problem if you do it that way. There's a lot of code out
there that does that, despite the letter of the language standard.
But if you can use variably modified types (the jargon for a run-time
array size parameter) then you get simpler code as well as code that is
correct by the letter of the language standard.
Finally, if (a) you can't use C99; (b) you want to avoid any hint of
undefined behaviour and (c) the arrays sizes are known at compile time
but the function must be general-purpose you can use an union. I won't
post an example because this set of circumstances is unlikely.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | supercat@casperkitty.com |
|---|---|
| Date | 2018-01-29 07:58 -0800 |
| Message-ID | <1268df2d-54e3-4514-b8df-caa406adedde@googlegroups.com> |
| In reply to | #125942 |
On Monday, January 29, 2018 at 5:00:52 AM UTC-6, Ben Bacarisse wrote:
> As for the "strict aliasing" issue, that's a red herring. The code that
> treats a 2D array as a 1D array is technically undefined for reasons
> that have nothing to do with aliasing. I doubt, though, that you will
> come across a problem if you do it that way. There's a lot of code out
> there that does that, despite the letter of the language standard.
It has nothing to do with type-based aliasing, but has to do instead with
the question of aliasing between elements of different rows. A compiler
which knows that foo[r1][c1] cannot alias foo[r2][c2] if r1 != r2 etc. may
be able to reorder operations performed on different rows (which could e.g.
allow multiple rows to be processed simultaneously by different execution
units.
The Standard fails to make clear what a given an array-type lvalue which
is contained within a larger object, to produce a pointer that can be
indexed to access other parts of the containing object. It would be
unreasonable to say that a function like:
void output_as_hex(void *p, size_t n)
{
unsigned char *cp = p;
while(n--)
printf("%02X",*cp++);
}
should be limited to processing one row of an array at a time.
[toc] | [prev] | [next] | [standalone]
| From | Nick Bowler <nbowler@draconx.ca> |
|---|---|
| Date | 2018-01-29 22:38 +0000 |
| Message-ID | <p4o7o7$1vh$1@dont-email.me> |
| In reply to | #125942 |
On Mon, 29 Jan 2018 11:00:34 +0000, Ben Bacarisse wrote:
> Yes. If the array size (specifically the row length) is not known at
> compile time you can do this as of C99:
>
> static void Print(int m, int n, int A[m][n])
> {
[...]
> }
>
> Note the parameter order and the deleted const. The new order is needed
This order of parameters is not actually needed; other orders are
possible by using a separate prototype. For example:
static void Print(int (*)[*], int, int);
static void Print(A, m, n)
int m, n;
int (*A)[n];
{
/* ... */
}
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2018-01-29 23:07 +0000 |
| Message-ID | <87607ke02x.fsf@bsb.me.uk> |
| In reply to | #125967 |
Nick Bowler <nbowler@draconx.ca> writes:
> On Mon, 29 Jan 2018 11:00:34 +0000, Ben Bacarisse wrote:
>> Yes. If the array size (specifically the row length) is not known at
>> compile time you can do this as of C99:
>>
>> static void Print(int m, int n, int A[m][n])
>> {
> [...]
>> }
>>
>> Note the parameter order and the deleted const. The new order is needed
>
> This order of parameters is not actually needed; other orders are
> possible by using a separate prototype. For example:
>
> static void Print(int (*)[*], int, int);
> static void Print(A, m, n)
> int m, n;
> int (*A)[n];
> {
> /* ... */
> }
Blimey! A use for a pre-ANSI C function definition. That would not
have occurred to me (obviously). Thanks. In a weird way that's made my
day.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2018-01-29 03:29 -0800 |
| Message-ID | <f0e06130-3a53-466d-a813-d35ddfd4ac6a@googlegroups.com> |
| In reply to | #125940 |
On Monday, January 29, 2018 at 9:40:25 AM UTC, August Karlstrom wrote:
> I need to define a function which can handle two-dimensional array
> parameters of any size (both dimensions). The code below illustrates my
> current approach.
>
Generally the easiest answer is just to forget 2D arrays and dereference a
1D array with
array[y*width+x];
However you've got a good answer should you decide that the clarity of
having two sets of brackets instead of one is worth it.
[toc] | [prev] | [next] | [standalone]
| From | August Karlstrom <fusionfile@gmail.com> |
|---|---|
| Date | 2018-01-29 21:35 +0100 |
| Message-ID | <p4o0j7$1o4b$1@gioia.aioe.org> |
| In reply to | #125944 |
On 2018-01-29 12:29, Malcolm McLean wrote: > On Monday, January 29, 2018 at 9:40:25 AM UTC, August Karlstrom wrote: >> I need to define a function which can handle two-dimensional array >> parameters of any size (both dimensions). The code below illustrates my >> current approach. >> > Generally the easiest answer is just to forget 2D arrays and dereference a > 1D array with > > > array[y*width+x]; Yes, this seems like the best approach. -- August
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web