ded@aplvax.UUCP (Don E. Davis) (05/13/85)
Here is a problem which cropped up recently. I had two two dimensional arrays of pointers to character strings (as represented by Cwords and Pwords below). I wanted to point to either Cwords or Pwords and be able to flip back and forth between two lists of strings by indexing. For example, if Words pointed to Cwords, then Words[0][0] would point to "hello" and Words[1][0] would point to "goodbye". If Words pointed to Pwords the two choices would be "foo" and "foobar". The only problem is, I had a hard time getting this to work. What I needed was something to put in the place of CASTING EXPRESSION below. Apparently there is no way to perform this kind of cast (the array's second dimension is the problem). Of course, I could have used pointer arithmetic (e.g., printf("%s\n",*(Words+i*4+j)), but wound up using a typedef instead since the WORD[][] format made my code a lot cleaner. What do you say, gang, is there some CASTING EXPRESSION I could have used? /*-----------------------------------------------------------------------*/ char *Cwords[2][4] = { {"hello","go","here","see"}, {"goodbye","come","there","hear"} }; char *Pwords[2][4] = { {"foo","foo","foo","foo"}, {"foobar","foobar","foobar","foobar"} }; char *Words; main() { int i,j; Words = (char *)Cwords; for (i=0; i<2; i++) for (j=0; j<2; j++) printf("%s\n",(CASTING EXPRESSION)Words[i][j]); Words = (char *)Pwords; for (i=0; i<2; i++) for (j=0; j<2; j++) printf("%s\n",(CASTING EXPRESSION)Words[i][j]); } /*-------------------------------------------------------------------------*/ Here is a solution which works. I find it hard to believe this can't be done without a typedef (or explicit pointer arithmetic), but haven't been able to find a way yet. typedef char *SYNTAX[4]; SYNTAX Cwords[2] = { {"hello","bye","go","come"}, {"say","can","you","see"} }; SYNTAX Pwords[2] = { {"foo","foo","foo","foo"}, {"foo","foo","foo","foo"} }; SYNTAX *Words; main() { int i,j; Words = (SYNTAX *)Cwords; for (i=0; i<2; i++) for (j=0; j<2; j++) printf("%s\n",Words[i][j]); Words = (SYNTAX *)Pwords; for (i=0; i<2; i++) for (j=0; j<2; j++) printf("%s\n",Words[i][j]); } -- Don Davis JHU/APL ...decvax!harpo!seismo!umcp-cs!aplvax!ded ...rlgvax!cvl!umcp-cs!aplvax!ded
chris@umcp-cs.UUCP (Chris Torek) (05/14/85)
Your second example works because Words is (correctly) a pointer to
an array 4 of pointer to char (in cdecl syntax). You don't even need
the casts in the assignment statements.
If you want to do it without typedefs, try
char *Cwords[2][4] = {{"1", "2", "3", "4"}, {"a", "b", "c", "d"}};
char *Pwords[2][4] = {{"w", "x", "y", "z"}, {"9", "8", "7", "6"}};
char *(*Words)[4];
main()
{
register int i, j;
Words = Cwords;
for (i = 0; i < 2; i++)
for (j = 0; j < 4; j++)
printf("%s\n", Words[i][j]);
Words = Pwords;
for (i = 0; i < 2; i++)
for (j = 0; j < 4; j++)
printf("%s\n", Words[i][j]);
}
--
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 4251)
UUCP: seismo!umcp-cs!chris
CSNet: chris@umcp-cs ARPA: chris@maryland
gwyn@brl-tgr.ARPA (Doug Gwyn <gwyn>) (05/14/85)
> char *Cwords[2][4] = { > {"hello","go","here","see"}, > {"goodbye","come","there","hear"} > }; > char *Pwords[2][4] = { > {"foo","foo","foo","foo"}, > {"foobar","foobar","foobar","foobar"} > }; > char *Words; char *(*Words)[4]; /* after all, you want Words[i][j] to be a (char *) */ > > main() > { > int i,j; > > Words = (char *)Cwords; Words = Cwords; > for (i=0; i<2; i++) > for (j=0; j<2; j++) > printf("%s\n",(CASTING EXPRESSION)Words[i][j]); printf("%s\n",Words[i][j]); > Words = (char *)Pwords; Words = Pwords; > for (i=0; i<2; i++) > for (j=0; j<2; j++) > printf("%s\n",(CASTING EXPRESSION)Words[i][j]); printf("%s\n",Words[i][j]); > }
g-frank@gumby.UUCP (05/14/85)
> Here is a solution which works. I find it hard to believe this > can't be done without a typedef (or explicit pointer arithmetic), but > haven't been able to find a way yet. > See, Don? C is so powerful, you can do anything in it! You can't read it or understand it, but who cares? -- Dan Frank Q: What's the difference between an Apple MacIntosh and an Etch-A-Sketch? A: You don't have to shake the Mac to clear the screen.
john@x.UUCP (John Woods) (05/15/85)
> /*-----------------------------------------------------------------------*/ > > char *Cwords[2][4] = { > {"hello","go","here","see"}, > {"goodbye","come","there","hear"} > }; > char *Pwords[2][4] = { > {"foo","foo","foo","foo"}, > {"foobar","foobar","foobar","foobar"} > }; > char *Words; > Words = Cwords; dot dot dot > printf("%s\n",(CASTING EXPRESSION)Words[i][j]); > > Here is a solution which works. I find it hard to believe this > can't be done without a typedef (or explicit pointer arithmetic), but > haven't been able to find a way yet. > > typedef char *SYNTAX[4]; > SYNTAX Cwords[2] = { > SYNTAX Pwords[2] = { > SYNTAX *Words; Well, I personally prefer the typedef style, but you didn't have to use it. The basic problem in the first example is that Words should not be of type char *; if Words were declared as a pointer to an array of four char pointers, e.g. char *(*Words)[4]; then you could use Words[i][k] without any casting required. I *THINK* I have the parentheses in the right place, and some quick cc -S experiments seem to make me believe I am right. However, that is the very reason that I prefer the typedef: with typedef, you can express these things quickly and easily. Reminds me of the old puzzle about casting the number 7 into a pointer to a function returning a pointer to a pointer to a function returning...... The answer took up about 70 characters on a single line, and looked like the output from crypt(1). The puzzle, of course, forbade the use of typedef, which made it much too easy!-) -- John Woods, Charles River Data Systems, Framingham MA, (617) 626-1101 ...!decvax!frog!john, ...!mit-eddie!jfw, jfw%mit-ccc@MIT-XX.ARPA "MU" said the Sacred Chao...