Thread View: comp.std.c
6 messages
6 total messages
Started by Philippe Maurisset
Wed, 17 Apr 1996 15:46
Q: char **foo, char *foo[], and char foo[][] ?
Author: Philippe Maurisset
Date: Wed, 17 Apr 1996 15:46
Date: Wed, 17 Apr 1996 15:46
41 lines
1495 bytes
1495 bytes
Considering the 3 following declarations:
1 - char **foo;
2 - char *foo[];
3 - char foo[][];
I know that there is a (big !) difference in memory reservation, but I do not know
if foo IS or IS NOT of the same type in these three cases.
To summarize my question :
Is the first one securely usable for casting a variable of the third kind, when
calling a function where it is defined as the second kind ?
Follwing is a description (the 2 functions are in differents sources files) :
myexample()
{
char foo[MAX_X][MAX_Y];
...
myfunc( (char **)foo );
}
void myfunc( char *foo[MAX_X] )
{
...
}
Can anybody help me ? Is it system-dependent ?
Many thanks in advance,
Philippe.
--
+-----------------------------+-----------------------------+
| Philippe MAURISSET | |
| Lectra Systemes | Phil@RD.Lectra.fr |
| Chemin de Marticot, BP 34 | tel : +33 57.97.80.00 |
| 33611 CESTAS Cedex | direct: +33 57.97.81.13 |
| FRANCE | fax : +33 57.97.82.32 |
+-----------------------------+-----------------------------+
Re: Q: char **foo, char *foo[], and char foo[][] ?
Author: J. Kanze
Date: Thu, 18 Apr 1996 08:59
Date: Thu, 18 Apr 1996 08:59
39 lines
1737 bytes
1737 bytes
In article <4l33ok$oo2@Sherlock.lectra.fr> phil@rd.lectra.fr (Philippe
Maurisset) writes:
|> Considering the 3 following declarations:
|> 1 - char **foo;
|> 2 - char *foo[];
|> 3 - char foo[][];
|> I know that there is a (big !) difference in memory reservation, but I do not know
|> if foo IS or IS NOT of the same type in these three cases.
They are definitly not the same type, however...
|> To summarize my question :
|> Is the first one securely usable for casting a variable of the third kind, when
|> calling a function where it is defined as the second kind ?
|> Follwing is a description (the 2 functions are in differents sources files) :
|> myexample()
|> {
|> char foo[MAX_X][MAX_Y];
|> ...
|> myfunc( (char **)foo );
|> }
|> void myfunc( char *foo[MAX_X] )
^^^^^^^^^^^^^^^^
Because it appears as a function parameter, this is actually a
declaration of a char**, and not a char*[].
So in fact, you have no type incompatibility to deal with.
--
James Kanze (+33) 88 14 49 00 email: kanze@gabi-soft.fr
GABI Software, Sarl., 8 rue des Francs Bourgeois, 67000 Strasbourg, France
Conseils en informatique industrielle --
-- Beratung in industrieller Datenverarbeitung
Re: Q: char **foo, char *foo[], and char foo[][] ?
Author: James Carlson
Date: Thu, 18 Apr 1996 12:05
Date: Thu, 18 Apr 1996 12:05
93 lines
4831 bytes
4831 bytes
In article <4l33ok$oo2@Sherlock.lectra.fr>, phil@rd.lectra.fr (Philippe Maurisset) writes: |> Considering the 3 following declarations: |> |> 1 - char **foo; |> 2 - char *foo[]; |> 3 - char foo[][]; |> [...non-working example deleted...] |> Can anybody help me ? Is it system-dependent ? No, it's not system-dependent, but it is context-specific. There are some rules you can follow. When you define a simple array (all []'s, like foo[3][9]), you can refer to it in prototypes either as fully-dimensioned (all []'s with constant values, like foo[3][9]), or with the first dimension elided (all but first [] with constant, like foo[][9]), or even as a simple pointer (like *foo or foo[]), although the dimensioning will be lost and the elements will appear as a single- dimension array (27 elements in this case). You may not refer to it as "*foo[]", either as an argument declarator or in an "extern" in a separate file. When you create an array of pointers (like *foo[3][2]), you can refer to it in prototypes either as the same type of pointer (*foo[3][2] again), or with the first dimension elided (*foo[][2]), or even as a simple pointer (**foo), though, again, you drop back to single-dimension. The pattern here is that the first set of brackets ([]) translate into one level of "*" in the function argument declaration, but additional levels of brackets do NOT add "*"s to the function argument. Thus, char foo[1000] and char foo[10][10][10] are stored in exactly the same internal format, and can be referred to in a function argument list as foo[1000], foo[], foo[][10][10], foo[10][10][10], or *foo. One more wrinkle to consider is that when declaring a variable, *foo is different from (and incompatible with) foo[], but when passed as an argument, they are identical. Thus, when making "extern" statements to refer to a variable (rather than passing as an argument list), do not follow the above rules, but rather declare variable exactly as originally defined. The only exception to that rule is that you may still elide the first dimension in an extern (like foo[][9]), but, again, you cannot choose to call this "*foo" in the extern. Instead of trying to argue about the abstract types, let's instead look at a hypothetical example on an imaginary machine. char **var1; char *var2[5]; char var3[3][2]; These three declarations could produce the following assembly code for our hypothetical machine (assuming 32-bit architecture, nice, simple system): .bss var1,4 # single char** pointer, 4 bytes .bss var2,20 # five char* pointers, 20 bytes .bss var3,6 # array of 3x2 chars, 6 bytes Note that these are extremely different. The first case declares a single simple pointer, which happens to be a pointer-to-a-pointer. The second declares a contiguous array of 5 pointers, each of which happens to be a pointer-to-a-char. The last example just creates a block of 6 bytes, no pointers. Because the types are different, the compiler knows to generate different code for accessing each case. Let's carry this a little further and fetch var3[2][1], var2[2][1], and var1[2][1]. These look like (two register machine, "ptr" and "acc"): move (var3+5),acc # move offset 2*2+1 into accum. move (var2+8),ptr # move offset 2*4 into pointer move 1(ptr),acc # move offset 1 into accumul. move var3,ptr # fetch var3 (pointer) move 8(ptr),ptr # move offset 2*4 into pointer move 1(ptr),acc # move offset 1 into accumul. In the first case, the compiler uses the "var3" symbol as the location of the beginning of the array, and simply needs to offset out to the 6th location to fetch the desired character. In the second case, the compiler can locate var2[2] immediately; it's the second element in the var2 array (pointers of 4 bytes each), but then it must use the value at that location as a pointer to the actual array of characters, and then fetch offset 1 from there. In the last case, the compiler must fetch the contents of var3, treat it as a pointer to fetch the 2nd pointer value (again 4 bytes each), and then fetch offset 1 from that value. -- James Carlson <carlson@xylogics.com> Tel: +1 617 272 8140 Annex Interface Development / Xylogics, Inc. +1 800 225 3317 53 Third Avenue / Burlington MA 01803-4491 Fax: +1 617 272 2618
Re: Q: char **foo, char *foo[], and char foo[][] ?
Author: Jerry Coffin
Date: Thu, 18 Apr 1996 19:10
Date: Thu, 18 Apr 1996 19:10
16 lines
956 bytes
956 bytes
In article <4l33ok$oo2@Sherlock.lectra.fr>, phil@rd.lectra.fr says...
> Considering the 3 following declarations:
>
> 1 - char **foo;
> 2 - char *foo[];
> 3 - char foo[][];
>
> I know that there is a (big !) difference in memory reservation, but I do
> not know if foo IS or IS NOT of the same type in these three cases.
[ ... ]
In declaring a parameter to a function, any declaration of an array is treated
as a declaration of a pointer. In all other situations, the two are separate
and distinct.
Later,
Jerry.
Re: Q: char **foo, char *foo[], and char foo[][] ?
Author: James Carlson
Date: Fri, 19 Apr 1996 12:20
Date: Fri, 19 Apr 1996 12:20
39 lines
1902 bytes
1902 bytes
In article <KANZE.96Apr18105949@gabi.gabi-soft.fr>, kanze@gabi-soft.fr (J. Kanze) writes:
|> In article <4l33ok$oo2@Sherlock.lectra.fr> phil@rd.lectra.fr (Philippe
|> Maurisset) writes:
[...]
|>
|> |> myexample()
|> |> {
|> |> char foo[MAX_X][MAX_Y];
|> |> ...
|> |> myfunc( (char **)foo );
|> |> }
|>
|> |> void myfunc( char *foo[MAX_X] )
|> ^^^^^^^^^^^^^^^^
|>
|> Because it appears as a function parameter, this is actually a
|> declaration of a char**, and not a char*[].
True.
|> So in fact, you have no type incompatibility to deal with.
Not true. The original definition of foo in myexample() was as a two-
dimensional array, which, in C, is implemented in storage as a
unidimensional array of size MAX_X*MAX_Y*sizeof(char), not as an array
of pointers-to-characters. If you try to access this as a pointer-to-a-
pointer, you will be attempting to dereference character data as a
pointer. (If you've got a real operating system, then this just results
in a core fault. If you're running on a toy, the results could be far
worse.)
(Of course, the type of the formal argument is compatible with the
cast given in the call, but the cast itself is bogus.)
--
James Carlson <carlson@xylogics.com> Tel: +1 617 272 8140
Annex Interface Development / Xylogics, Inc. +1 800 225 3317
53 Third Avenue / Burlington MA 01803-4491 Fax: +1 617 272 2618
Re: Q: char **foo, char *foo[], and char foo[][] ?
Author: Larry Jones
Date: Fri, 19 Apr 1996 20:20
Date: Fri, 19 Apr 1996 20:20
37 lines
1683 bytes
1683 bytes
In article <KANZE.96Apr18105949@gabi.gabi-soft.fr>, kanze@gabi-soft.fr (J. Kanze) writes:
> In article <4l33ok$oo2@Sherlock.lectra.fr> phil@rd.lectra.fr (Philippe
> Maurisset) writes:
> |> myexample()
> |> {
> |> char foo[MAX_X][MAX_Y];
> |> ...
> |> myfunc( (char **)foo );
> |> }
>
> |> void myfunc( char *foo[MAX_X] )
> ^^^^^^^^^^^^^^^^
>
> Because it appears as a function parameter, this is actually a
> declaration of a char**, and not a char*[].
>
> So in fact, you have no type incompatibility to deal with.
Yes, you do. While the cast in the call to myfunc matches the
prototype, the cast itself is erroneous. The type of foo is actually
char (*)[MAX_Y]: a pointer to an array of characters. Converting a
pointer to an array into a pointer to a pointer is essentially
meaningless and will not generally work. The corrected example is:
myexample()
{
char foo[MAX_X][MAX_Y];
...
myfunc( foo );
}
void myfunc( char (*foo)[MAX_X] )
Even K&R I discusses this in 5.7 Multi-Dimensional Arrays.
----
Larry Jones, SDRC, 2000 Eastman Dr., Milford, OH 45150-2789 513-576-2070
larry.jones@sdrc.com
In a minute, you and I are going to settle this out of doors. -- Calvin
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads