Pass A 2-D, Statically Defined Array?

D

DarelRex

Is it possible to pass a 2-D, statically defined array?

Here's a 1-D example that won't work:

void foo() {
int myArray[MAX_SIZE] ;
bar(myArray);
}

void bar(int *arr) {
arr[5]=arr[7];
}

It won't work because myArray is statically defined. To make it work,
you can change foo's bar() call to this:

bar(&myArray[0]);

Then it works fine!

Any way to apply the same technique with a 2-D array?

void foo() {
int myArray[SIZE_A][SIZE_B] ;
bar(??myArray??);
}

void bar(int **arr) {
arr[5][3]=arr[2][4];
}

One possible workaround is to define myArray as 1-D but use it as 2-D:

void foo() {
int myArray[SIZE_A*SIZE_B] ;
bar(&myArray[0]);
}

void bar(int *arr) {
arr[5*SIZE_B+3]=arr[2*SIZE_B+4];
}

Kind-of inelegant, though.

Thanks for any advice! --Darel
(e-mail address removed)
http://alienryderflex.com
 
E

Eric Sosman

Is it possible to pass a 2-D, statically defined array?

Here's a 1-D example that won't work:

void foo() {
int myArray[MAX_SIZE] ;
bar(myArray);
}

void bar(int *arr) {
arr[5]=arr[7];
}

It won't work because myArray is statically defined.

In what way does it fail to "work?" (And what do you
mean by "statically defined?" Whatever it is, it seems to
have nothing to do with the "static" keyword or with "static
storage duration.")
To make it work,
you can change foo's bar() call to this:

bar(&myArray[0]);

Then it works fine!

Very strange. Take a fragment of nothing-obviously-wrong
code, add an obvious error, and it "works fine," whatever
that means.
Any way to apply the same technique with a 2-D array?

The "technique" of taking (apparently) correct code,
adding an error, and declaring that it "works fine?"

DarelRex, I think you'd eliminate a lot of confusion
by posting some actual code instead of fragmentary paraphrases.
As things stand, I do not know what problem you are having
and cannot suggest a solution.
 
D

David T. Ashley

Is it possible to pass a 2-D, statically defined array?

It depends on whether the rightmost N-1 array subscript limits are known at
compile-time.

A multidimensional array can always be accessed as as a one-dimensional
array.

This URL may be interesting for you.

http://204.122.16.5/~scs/cclass/int/sx9a.html

Generally speaking, it is safe to assume that the compiler MIGHT be able to
somehow generate better code if you do this:

a[4][23][91][6]

rather than this:

a[(4 * LIMIT_B * LIMIT_C * LIMIT_D) + (23 * LIMIT_C * LIMIT_D) + (91 *
LIMIT_D] + (6)];

but of course this is not guaranteed.

However, it depends on how much is known at compile-time versus run-time and
how much information you can convey to the compiler. The compiler can in
general access an N-dimensional array directly so long as the N-1
least-significant limits are known.

The URL above has some examples.
 
B

Barry Schwarz

(e-mail address removed) wrote On 01/02/07 16:30,:
Is it possible to pass a 2-D, statically defined array?

Here's a 1-D example that won't work:

void foo() {
int myArray[MAX_SIZE] ;
bar(myArray);
}

void bar(int *arr) {
arr[5]=arr[7];
}

It won't work because myArray is statically defined.

In what way does it fail to "work?" (And what do you
mean by "statically defined?" Whatever it is, it seems to
have nothing to do with the "static" keyword or with "static
storage duration.")
To make it work,
you can change foo's bar() call to this:

bar(&myArray[0]);

Then it works fine!

Very strange. Take a fragment of nothing-obviously-wrong
code, add an obvious error, and it "works fine," whatever
that means.

In what way is the argument &myArray[0] any different than the
argument myArray? Both evaluate to the address of myArray[0] with
type pointer to int.


Remove del for email
 
B

Barry Schwarz

Is it possible to pass a 2-D, statically defined array?
Yes


Here's a 1-D example that won't work:

What do you mean by won't work. Do you get a compile time diagnostic?
If so, what is it?
void foo() {
int myArray[MAX_SIZE] ;
bar(myArray);
}

void bar(int *arr) {
arr[5]=arr[7];
}

It won't work because myArray is statically defined. To make it work,
you can change foo's bar() call to this:

There is nothing static about myArray. Static refers to storage
duration. myArray is an object with automatic storage duration.
bar(&myArray[0]);

This is syntactically identical to the original code. Any C compiler
is required to treat the two identically.
Then it works fine!

Define works fine since it is no different.
Any way to apply the same technique with a 2-D array?

void foo() {
int myArray[SIZE_A][SIZE_B] ;
bar(??myArray??);

Remove the '?'.
}

void bar(int **arr) {

Change the type of the parameter to int[SIZE_A][SIZE_B] or the
equivalent int(*)[SIZE_B].

arr[5][3]=arr[2][4];
}

The rule is: except when the operand of the sizeof and & operators, an
expression with type array of T will evaluate to the address of the
first element of the array with type pointer to T. Your 2-D array is
an array of SIZE_A array of SIZE_B int. Therefore, the expression
myArray evaluates to the address of myArray[0] with type pointer to
array of SIZE_B int, which is the type of the second form of the
parameter above.


Remove del for email
 
E

Eric Sosman

Barry said:
[given `int myArray[MAX_SIZE];']
In what way is the argument &myArray[0] any different than the
argument myArray? Both evaluate to the address of myArray[0] with
type pointer to int.

This is Question 6.12 in the comp.lang.c Frequently
Asked Questions (FAQ) list at http://c-faq.com/ .
 
K

Keith Thompson

Eric Sosman said:
Barry said:
[given `int myArray[MAX_SIZE];']
In what way is the argument &myArray[0] any different than the
argument myArray? Both evaluate to the address of myArray[0] with
type pointer to int.

This is Question 6.12 in the comp.lang.c Frequently
Asked Questions (FAQ) list at http://c-faq.com/ .

Not really. 6.12 talks about the difference between arr and &arr
(they differ in type). Barry was talking about the difference between
arr and &arr[0] (there is none in most contexts, including the one
being considered).
 
R

Richard Heathfield

Eric Sosman said:
Barry said:
[given `int myArray[MAX_SIZE];']
In what way is the argument &myArray[0] any different than the
argument myArray? Both evaluate to the address of myArray[0] with
type pointer to int.

This is Question 6.12 in the comp.lang.c Frequently
Asked Questions (FAQ) list at http://c-faq.com/ .

No, it isn't.
 
D

DarelRex

Wow, I didn't know a simple programming question was an invitation to
abuse! I guess some people have no other source of self-worth than
trying to belittle people who ask for help. But thanks to those who
tried to answer politely.

To clarify -- by statically defined I mean this:

int myArray[SIZE] ;

as opposed to dynamic, like so:

int *myArray=malloc(sizeof(int)*SIZE) ; (or something like that)

In the latter case, myArray can be passed to bar() no problem, but I
have had serious problems with some C compilers trying to pass myArray
in the former case. Those problems go away if I pass &myArray[0]. Can
anyone back me up on this -- has anyone had similar experiences?
(Common sense 101: If the answer is "yes", please reply, but if the
answer is "no" don't post a nasty comment.)

Thanks in advance, --Darel
(e-mail address removed)
http://alienryderflex.com
 
R

Richard Heathfield

(e-mail address removed) said:
Wow, I didn't know a simple programming question was an invitation to
abuse!

Neither did I. Who has abused whom in this thread, and how?
I guess some people have no other source of self-worth than
trying to belittle people who ask for help.

Who has belittled whom in this thread, and how?
But thanks to those who tried to answer politely.

Who has answered impolitely?
To clarify -- by statically defined I mean this:

int myArray[SIZE] ;

as opposed to dynamic, like so:

int *myArray=malloc(sizeof(int)*SIZE) ; (or something like that)

In the latter case, myArray can be passed to bar() no problem, but I
have had serious problems with some C compilers trying to pass myArray
in the former case. Those problems go away if I pass &myArray[0]. Can
anyone back me up on this -- has anyone had similar experiences?

If your description of the problem is correct, then it would appear that you
have a non-conforming compiler. Whilst I have not used all the C compilers
there are by any means, nevertheless I find it unlikely that mainstream
compilers are getting this sort of thing wrong nowadays, so I think you may
have made a mistake.

As far as C is concerned, there is no distinction between an int * that is
the result of evaluating int myArray[SIZE] and an int * that is the result
of evaluating a pointer to int. They have the same type, and either can be
passed to a function taking int * as a parameter.

The best way to find out whether your problem description is correct is to
post a small but complete program (complete in the sense that it can be
compiled directly) and which exhibits the problem.

(Common sense 101: If the answer is "yes", please reply, but if the
answer is "no" don't post a nasty comment.)

I guess all the nasty comments you've received have been filtered out by my
newsreader. Good.
 
E

Eric Sosman

Richard said:
Eric Sosman said:
Barry said:
[given `int myArray[MAX_SIZE];']
In what way is the argument &myArray[0] any different than the
argument myArray? Both evaluate to the address of myArray[0] with
type pointer to int.
This is Question 6.12 in the comp.lang.c Frequently
Asked Questions (FAQ) list at http://c-faq.com/ .

No, it isn't.

Oh, pfui. That'll teach me not to read overhastily and
write while dozing off. (More likely it won't, and I'll just
embarrass myself yet again ...)

My apologies to DarelRex: Changing from foo(myArray) to
foo(&myArray[0]) does not introduce an error, as I claimed.
On the other hand, it doesn't fix anything either: it means,
as Barry Schwarz pointed out, exactly the same thing and should
make no difference at all. So I'll repeat my earlier request:
Could we see some actual code and actual error messages, please?
Debugging fragmentary "sort-of-likes" is an uncertain business,
as I think I've demonstrated all too clearly ...
 
D

DarelRex

Richard Heathfield said:
...
I guess all the nasty comments you've received have been filtered out by my
newsreader. Good.

We must not be using the same newsreader -- your last post came through
loud and clear on mine.
 
R

Richard Heathfield

(e-mail address removed) said:
Richard Heathfield said:


We must not be using the same newsreader -- your last post came through
loud and clear on mine.

Not including this reply, I have posted twice to this thread.

In the first reply, I corrected Eric Sosman, who misread Barry Schwarz's
reply to Eric's earlier article. My correction was admittedly rather short,
but I think you'll find that Eric took it in the helpful spirit in which it
was intended. If you doubt that, ask him.

My second reply was addressed to you, and was rather longer. In it, I
pointed out that either your compiler is broken or your code is, and it's
impossible to tell which without seeing your code. I do not consider that
to be a "nasty comment", and neither do I consider it reasonable to
interpret it as one. Rather, I see it as a request for you to show code so
that we can help you more effectively. If you see attempts to help you as
"nasty comments", there isn't much we can do.
 
K

Keith Thompson

Richard Heathfield said:

We must not be using the same newsreader -- your last post came through
loud and clear on mine.

I don't recall seeing any "nasty" comments in this thread. Can you
post message-ids of any posts you consider nasty? I suspect you're
being overly sensitive, but I can't be sure of that unless I know just
what you're referring to.

In this newsgroup, we tend to point out each other's errors, and we do
so unapologetically. (Most of us are grateful for these corrections.)
Is that what you consider "nasty"?
 
D

DarelRex

OK, here's the detail on this issue. I'm using Xcode (Panther
release), which I believe uses some version of the gcc compiler, but I
don't really know. However, I distinctly remember having this same
problem with C long before there was such a thing as Xcode.

Here's my simple test case. This is actual code, that I actually
compiled and (if it compiled clean) actually ran!

void foo() {
int myArray[3][3]={{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }} ;
bar(myArray); }

void bar(int **arr) {
arr[2][1]=arr[0][2]; }

When I compile this, I get a warning: "passing arg 1 of 'bar' from
incompatible pointer type". So I changed the bar call to this:

bar((int **) myArray);

Now I get no warning, but the assignment statement inside the bar
function terminates the app with this message: "Program received
signal: 'EXC_BAD_ACCESS'" So I change the bar call to:

bar(&myArray[0]);

Then I get the warning again: "passing arg 1 of 'bar' from
incompatible pointer type". So I change the call to this:

bar((int **) &myArray[0]);

Then I get no warning, but the assignment statement inside bar
terminates again: "Program received signal: 'EXC_BAD_ACCESS'"

So now I change the bar function to receive just a pointer to int, like
so: (int *), and I change the bar call to:

bar(&myArray[0][0]);

And I have to change the assignment statement to calculate the 2-D
indices:

arr[2*3+1]=arr[0*3+2];

Once again the compiler gives me the warning ("passing arg 1 of 'bar'
from incompatible pointer type"), so I change the bar call to:

bar((int *) &myArray[0][0]);

Voila! It finally works. And I have verified that it is reading the
actual values from the array. But the assignment statement must use a
calculated 2-D address, as described above.

Now, I just ran all these tests today, so I *know* this problem is
real. Please, anyone who knows something about it, post a reply if you
have the time.

Thanks much,
Darel

(e-mail address removed)
http://alienryderflex.com
 
P

pete

void foo() {
int myArray[3][3]={{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }} ;
bar(myArray); }

void bar(int **arr) {
arr[2][1]=arr[0][2]; }

void bar(int (*arr)[3])
{
arr[2][1] = arr[0][2];
}
 
E

Eric Sosman

OK, here's the detail on this issue. I'm using Xcode (Panther
release), which I believe uses some version of the gcc compiler, but I
don't really know. However, I distinctly remember having this same
problem with C long before there was such a thing as Xcode.

Here's my simple test case. This is actual code, that I actually
compiled and (if it compiled clean) actually ran!

void foo() {
int myArray[3][3]={{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }} ;
bar(myArray); }

void bar(int **arr) {
arr[2][1]=arr[0][2]; }

When I compile this, I get a warning: "passing arg 1 of 'bar' from
incompatible pointer type". [...]

Aha! This one *is* a FAQ (in light of recent history,
I double-checked). It's Question 6.18 at http://c-faq.com/ .
 
R

Richard Heathfield

(e-mail address removed) said:
OK, here's the detail on this issue. I'm using Xcode (Panther
release), which I believe uses some version of the gcc compiler, but I
don't really know. However, I distinctly remember having this same
problem with C long before there was such a thing as Xcode.

Here's my simple test case. This is actual code, that I actually
compiled and (if it compiled clean) actually ran!

void foo() {
int myArray[3][3]={{ 0, 1, 2 }, { 3, 4, 5 }, { 6, 7, 8 }} ;
bar(myArray); }

void bar(int **arr) {
arr[2][1]=arr[0][2]; }

When I compile this, I get a warning: "passing arg 1 of 'bar' from
incompatible pointer type".

Turn up your warning level. When I compile this, I get:

foo.c:1: warning: function declaration isn't a prototype
foo.c: In function `foo':
foo.c:3: warning: implicit declaration of function `bar'
foo.c: At top level:
foo.c:5: warning: no previous prototype for `bar'
foo.c:5: warning: type mismatch with previous implicit declaration
foo.c:3: warning: previous implicit declaration of `bar'
foo.c:5: warning: `bar' was previously implicitly declared to return `int'
So I changed the bar call to this:

bar((int **) myArray);

Since myArray decays to &myArray[0] which is an int(*)[3], it would be
better to change bar() to receive int(*)[3], or change myArray to be an
array of int *, rather than an array of int[3], and point its members to
the first elements of arrays of int[3]. It's unwise to pretend that
something is an int ** when it clearly isn't.
Now I get no warning,

I do:

foo.c:1: warning: function declaration isn't a prototype
foo.c: In function `foo':
foo.c:3: warning: implicit declaration of function `bar'
foo.c: At top level:
foo.c:5: warning: no previous prototype for `bar'
foo.c:5: warning: type mismatch with previous implicit declaration
foo.c:3: warning: previous implicit declaration of `bar'
foo.c:5: warning: `bar' was previously implicitly declared to return `int'
but the assignment statement inside the bar
function terminates the app with this message: "Program received
signal: 'EXC_BAD_ACCESS'"

What app? There's no main() function!

Yet again, I would ask that you provide a complete program that exhibits
your problem, so that people can give you real, useful help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
474,150
Messages
2,570,853
Members
47,393
Latest member
silloma

Latest Threads

Top