[comp.sys.amiga] Struggling through the "C"

LIZAK98%SNYBUFVA.BITNET@cornellc.cit.cornell.edu (A SHOW OF HANDS) (04/01/89)

This one is probably old hat for any of you C programmers out there,
but I am having a hell of a time writing this little routine.  Awhile
back I wrote a BBS program that is a C-Net look alike, however, because
the only language that I knew that I had on my Amiga was BASIC, I had to
use that.  The thing runs toooo slow for any real application other than
saying, oh it looks nice... too bad it doesnt keep up with 2400 baud...
Anyways, the output routine was written something like this (it's more
complex as it checks for control characters, etc before printing, but this
is the major part):

FOR I=1 TO LEN(A$)
  PRINT MID$(A$,I,1);
NEXT I

I posted this to a BBS and asked for a C equivlent, however, what I got was
a fragment of what I really needed... here is what was posted for me...

for(i=0;a[i]=!'\0';i++)
  printf("%c",a[i]);

no matter what I put for the declaration... it wouldnt work!  I added this
to the program to try to make it work... whats wrong with this?

main()
{
 char *a;
 int i;
 a="This is a test string...";

  ...above code....
}

   How must I declare a?  How must I define the string?

Thanks,


#####################################################################
#                                                                   #
#  Rob Lizak Jr.            Bitnet ID:  LIZAK98@SNYBUFVA            #
#                           DECNet ID:  BSCOLA::LIZAK98             #
#                                                                   #
#  "Once YOU buy a prize, it's YOURS to keep!"                      #
#                                                                   #
#####################################################################

cmcmanis%pepper@Sun.COM (Chuck McManis) (04/01/89)

In article <12000@louie.udel.EDU> (Rob Lizak Jr.) writes:
> FOR I=1 TO LEN(A$)
>   PRINT MID$(A$,I,1);
> NEXT I

C equivalent might be more syntactically written as 
	for (i=0; i < strlen(a); i++) 
		printf("%c", a[i]);
	
Get a copy of the book "Programming in C" by Stephen G. Kochan, ISBN
0-8104-6261-3, it has a good discussion of strings.

>no matter what I put for the declaration... it wouldnt work!  I added this
>to the program to try to make it work... whats wrong with this?

char	*a; /* This is a pointer to a string */
char	a[80]; /* this is a pointer to a string with 80 bytes allocated */

Outside of a function you can declare :
char	*a = "this is a test string."; /* the auto allocates space */
-or-
char	a[80];	/* Global variable */
main()
{
	char	b[80]; /* Local variable */
	/* this copies a string into your string buffer a */
	strcpy(a,"this is a test string");
	strcpy(b,a);	/* Copy string a into string b */
	
}
-----

--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"

kevin@uts.amdahl.com (Kevin Clague) (04/01/89)

In article <97113@sun.Eng.Sun.COM> cmcmanis@sun.UUCP (Chuck McManis) writes:
>In article <12000@louie.udel.EDU> (Rob Lizak Jr.) writes:
>> FOR I=1 TO LEN(A$)
>>   PRINT MID$(A$,I,1);
>> NEXT I
>
>C equivalent might be more syntactically written as 
>	for (i=0; i < strlen(a); i++) 
>		printf("%c", a[i]);
>	
>Get a copy of the book "Programming in C" by Stephen G. Kochan, ISBN
>0-8104-6261-3, it has a good discussion of strings.
>
>>no matter what I put for the declaration... it wouldnt work!  I added this
>>to the program to try to make it work... whats wrong with this?
>
>char	*a; /* This is a pointer to a string */
>char	a[80]; /* this is a pointer to a string with 80 bytes allocated */
>
>Outside of a function you can declare :
>char	*a = "this is a test string."; /* the auto allocates space */
>-or-
>char	a[80];	/* Global variable */
>main()
>{
>	char	b[80]; /* Local variable */
>	/* this copies a string into your string buffer a */
>	strcpy(a,"this is a test string");
>	strcpy(b,a);	/* Copy string a into string b */
>	
>}
>-----
>
>--Chuck McManis
>uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
>These opinions are my own and no one elses, but you knew that didn't you.
>"A most excellent barbarian ... Genghis Kahn!"

I had a hard time understanding from the posting at what level "things didn't
work".  I presumed Rob had gotten the thing to compile, and the problem was with
"buffered I/O".  Since Rob had no newline characters in his test string (and
it was so short), the I/O buffers would not be flushed, and therefore he would
get no output.  I sent email suggesting this as a possible explanation.

To really be compatible with basic (since he had no newlines), I think he
would have to fflush(stdout) after every printf(), no?

for (i = 0; i < strlen(a); i++) {
  printf("%c",a[i]);
  fflush(stdout);
}

or the less obvious, but more efficient (but Chuck knows this):

char *b;

b = a;

while (*b) {
  printf("%b",*b++);
  fflush(stdout);
}

Kevin

-- 
UUCP:  kevin@uts.amdahl.com
  or:  {sun,decwrl,hplabs,pyramid,seismo,oliveb}!amdahl!kevin
DDD:   408-737-5481
USPS:  Amdahl Corp.  M/S 249,  1250 E. Arques Av,  Sunnyvale, CA 94086

[  Any thoughts or opinions which may or may not have been expressed  ]
[  herein are my own.  They are not necessarily those of my employer. ]

joe@dayton.UUCP (Joseph P. Larson) (04/02/89)

In article <97113@sun.Eng.Sun.COM> cmcmanis@sun.UUCP (Chuck McManis) writes:
>In article <12000@louie.udel.EDU> (Rob Lizak Jr.) writes:
>> FOR I=1 TO LEN(A$)
>>   PRINT MID$(A$,I,1);
>> NEXT I
>
>C equivalent might be more syntactically written as 
>	for (i=0; i < strlen(a); i++) 
>		printf("%c", a[i]);

Oh, but people... Don't use Chuck's code.  It appears very straightforward,
except that you can't convince C not to execute the strlen() every time.
Yes, boys and girls -- Chuck's code will execute strlen(a) strlen(a)+1 times.

So what you might want to do is:

	for (i = 0, count = strlen(a); i < count; i++)
		printf("%c", a[i]);

Now, I realize most people out there KNOW C is going to do this to them,
but as long as we're giving C lessons to begin with, we might as well make
sure the novices are aware that C executes all parts of the conditional
in a for-loop exactly one more time than the number of iterations through
the loop.  (The test is at the top of the loop, so it checks once for
each loop plus takes the time that the condition fails.)

Of course, printf("%s", a) will work, too, but that's beside the point.

-Joe
-- 
Life is a cabaret (old chum).
UUCP: rutgers!dayton!joe   (Picts 1-13 are   DHDSC - Joe Larson/MIS 1060
ATT : (612) 375-3537       now ready.)       700 on the Mall, Mpls, Mn. 55402

jms@antares.UUCP (Joe Smith) (04/02/89)

I have seen 2 follow ups to this question, neither of which addresses the
real problem.

In article <12000@louie.udel.EDU> LIZAK98%SNYBUFVA.BITNET@cornellc.cit.cornell.edu (A SHOW OF HANDS) writes:
>
>for(i=0;a[i]=!'\0';i++)
>  printf("%c",a[i]);

The above piece of code will set every character in the string "a" to
a Control-A (ASCII code 001) and will continue past the end of the sting
and wipe out your program.
  '\0' is zero
  !0 is one
  a[i] = !0 sets a[i] to one

Note that the bad code has =! instead of !=.  The correct code is
	for(i=0;a[i]!='\0';i++) {
	   a bunch of "if" statements that handle special characters
	   else printf("%c",a[i]);
	}
-- 
Joe Smith (408)922-6220 | jms@antares.Tymnet.COM or jms@opus.Tymnet.COM
McDonnell Douglas FSCO  | UUCP: ...!{ames,pyramid}!oliveb!tymix!antares!jms
PO Box 49019, MS-D21    | PDP-10:JMS@F74.Tymnet.COM  CA license plate:"POPJ P,"
San Jose, CA 95161-9019 | narrator.device: "I didn't say that, my Amiga did!"

cmcmanis%pepper@Sun.COM (Chuck McManis) (04/03/89)

[Not at Kevin, just Kevin happened to post, everyone else just sent mail :-)]

In article <13.6va2CVf1010TxC9.@amdahl.uts.amdahl.com> (Kevin Clague) writes:
> or the less obvious, but more efficient (but Chuck knows this):
>
> char *b;
>
> b = a;
>
> while (*b) {
>   printf("%b",*b++);
>   fflush(stdout);
> }
>

Several people sent me messages ranging from, "how could someone like
you post such stupid C code?" to the more helpful "... didn't you know
it would be _much_ more efficient if you did it like this ..." [insert
Kevin's example here.] To keep from having to send everyone copies I've
decided to post my thinking on this matter, fortunately this is not in
c.s.a.t since it has very little technical content :

This is a _BASIC_ programmer we are talking to. Not your everyday pro ok?
He writes :
	10 FOR I = 1 TO LEN$(A$)
	20	PRINT MID$(A$, I, I)
	30 NEXT I

Now when one is teaching someone a new language, especially
someone who's been damaged by learning BASIC first, one starts
with direct equivalences. Token substitution and such. This
trains the students eyes into seeing the new syntax but keeps some
anchor points so that they don't loose sync. Once they understand
the construction of for(;;){} loops one moves on to talk about
pointers, while loops etc. The favorite example :

	char	*foo = a;
	while(*foo)
		printf("%c",*foo++);

Introduces no less than 5 totally radical ideas to the BASIC programmer.
They are 1) String Pointers, 2) Non-Boolean loop conditions, 3) While
loops, 4) Pointer arithmetic and implied assignment (++), and 5) NULL 
termination of C strings. That makes it a _lousy_ example. Your BASIC 
programmer is not only lost, he doesn't even know where to start asking 
questions!

You've gone way over his head. So as an eventual programming goal to 
shoot for this if fine. In the mean time lets not make him feel totally 
stupid shall we?


--Chuck McManis
uucp: {anywhere}!sun!cmcmanis   BIX: cmcmanis  ARPAnet: cmcmanis@sun.com
These opinions are my own and no one elses, but you knew that didn't you.
"A most excellent barbarian ... Genghis Kahn!"

hcj@lzaz.ATT.COM (HC Johnson) (04/05/89)

In article <12000@louie.udel.EDU>, LIZAK98%SNYBUFVA.BITNET@cornellc.cit.cornell.edu (A SHOW OF HANDS) writes:
> 
> FOR I=1 TO LEN(A$)
>   PRINT MID$(A$,I,1);
> NEXT I
> 
> 
> for(i=0;a[i]=!'\0';i++)
>   printf("%c",a[i]);

The C construct for not equal is !=
also useful <= and >=.

The =! has meanings you are not ready for.

Howard C. Johnson
ATT Bell Labs
att!lzaz!hcj
hcj@lzaz.att.com

dmg@ssc-vax.UUCP (David Geary) (04/06/89)

In article <97113@sun.Eng.Sun.COM>, Chuck McManis writes:

>In article <12000@louie.udel.EDU> (Rob Lizak Jr.) writes:
>> FOR I=1 TO LEN(A$)
>>   PRINT MID$(A$,I,1);
>> NEXT I
>
>> for(i=0;a[i]=!'\0';i++)
>>   printf("%c",a[i]);
>>
>>no matter what I put for the declaration... it wouldnt work!  I added this
>>to the program to try to make it work... whats wrong with this?
>
>char	*a; /* This is a pointer to a string */
>char	a[80]; /* this is a pointer to a string with 80 bytes allocated */

  No!  char a[80] is not a pointer at all.  It is an array.  Using the name
  of an array *under certain conditions* is equivalent to a pointer to 
  the first element of the array, but an array is very different from
  a pointer (one aspect of C that can be quite confusing).

Anyway, what Rob is trying to do is perfectly legal.  The problem arises in
the for loop:

	for(i=0; a[i]=!`\0`; i++)
		    ^^
This should be:

	for(i=0; a[i]!=`\0`; i++)
		     ^^

Instead of the conditional part of the loop checking to see if the next char.
is NULL, a[i] is ASSIGNED a value.  Since '\0' is equivalent to 0 on most
systems, we get a[i] =  !0.  !0 is not false, so it is true.  In C, true,
(when it's the result of logical operators) is 1.  Therefore, Rob is assigning
every character in the array the value of 1.  Not quite what was intended!

Two other notes:  Cramming everything together with no spaces is not good
style.  I would have written the for loop thusly:

	for(i = 0;  a[i] != NULL;  i++)

This is much more readable, and I suspect it would be easier to spot if
the ! and = were in the wrong order.

Secondly, this would be more appropriate for comp.lang.c

ps:  Sorry if someone else has already pointed this out, but I'm way behind
on my news reading, and there aren't many questions in this newsgroup that
I find I can answer ;-).

David Geary



-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace,               ~ 
~ #define    Seattle     RAIN                  ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

deven@pawl.rpi.edu (Deven Corzine) (04/07/89)

In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
[...]
>Since '\0' is equivalent to 0 on most systems,
[...]

Excuse me?  Name ONE system where '\0' is NOT zero???

Deven
--
------- shadow@pawl.rpi.edu ------- Deven Thomas Corzine ---------------------
Cogito  shadow@acm.rpi.edu          2346 15th Street            Pi-Rho America
ergo    userfxb6@rpitsmts.bitnet    Troy, NY 12180-2306         (518) 272-5847
sum...     In the immortal words of Socrates:  "I drank what?"     ...I think.

hans@nlgvax.UUCP (Hans Zuidam) (04/07/89)

>In article <97113@sun.Eng.Sun.COM>, Chuck McManis writes:
>>char	*a; /* This is a pointer to a string */
>>char	a[80]; /* this is a pointer to a string with 80 bytes allocated */

In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>  No!  char a[80] is not a pointer at all.  It is an array...

Please check your K&R before responding:

	K&R 7.1, pg. 185:
    An identifier is a primary expression, provided it has been
    suitably declared as discussed below. If the type of the identifier
    is "array of ...", then the value of the identifier-expression is a
    pointer to the first object in the array, and the type of the
    expression is "pointer to ...".

and

    K&R 7.1, pg. 186:
    The expression E1[E2] is identical (by definition) to *((E1)+(E2)).
    
This is from:
    "The C programming language",
    Kernighan, Brian W., Ritchie, Dennis M.
    Prentice-Hall Software series, 1978.

So:
    'char *a' is *identical* to 'char a[80]' *except* for the
    fact that in the second definition 'a' is a *constant*
    pointer. That is: you cannot assign a value to 'a'.

Ponder these:
    c = "ABCDEF"[i]
    a[i] and i[a] and *(a + i)

    /* The function */
    f(a, b)
    char a[], b[];

    /* Called by */
    char *c, *d;
    f(c, d)

And so on.

A useful cosequence of this is that one can construct flexible
arrays:

     int *p, i;
     p = (int *) malloc(NrOfElements * sizeof(int));
     for (i = 0; i < NrOfElements; i++) p[i] =0;
     p = (int *) realloc(p, NewNrOfElements * sizeof(int));
     /* and so on... */

						Hans
-- 
Hans Zuidam                                    E-Mail: hans@pcg.philips.nl
Philips Telecommunications and Data Systems,   Tel: +31 40 892288
Project Centre Geldrop, Building XR
Willem Alexanderlaan 7B, 5664 AN Geldrop       The Netherlands

kevin@cbmvax.UUCP (Kevin Klop) (04/08/89)

In article <231@nlgvax.UUCP> hans@nlgvax.UUCP (Hans Zuidam) writes:
>>In article <97113@sun.Eng.Sun.COM>, Chuck McManis writes:
>>>char	*a; /* This is a pointer to a string */
>>>char	a[80]; /* this is a pointer to a string with 80 bytes allocated */
>
>In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
>>  No!  char a[80] is not a pointer at all.  It is an array...
>

[Several K&R quotations deleted]

>So:
>    'char *a' is *identical* to 'char a[80]' *except* for the
>    fact that in the second definition 'a' is a *constant*
>    pointer. That is: you cannot assign a value to 'a'.

Actually, there is a difference between 'a' in the following two
declarations:

char a[80];
char *a;

To demonstrate, though, let us look at the following statement:

       *a = '\3';

in assembly code, this would translate to (I have made the assumption that both
declarations are GLOBAL in scope rather than allocated on the local stack):

; For the declaration "char a[80];"

         move.b #3,a     ; move a byte into location referenced by 'a'

; For the declaration "char *a;"

         movea.l a,A0    ; get the pointer from memory
         move.b  #3,(A0) ; and place a 3 into where it points

you will notice that for the declaration "char *a;" we have to do the
equivalent of a store indirect through a, whereas in the declaration
"char a[80];" we store to the location "a".

Note that this is hand coded assembly equivalences, and your compiler
mileage may vary... :^)

Thus, there is a very real difference between the two declarations.  Usually
there is no problem treating the two of them identically since the compiler
takes care of it for you.  However, since the identifier "a" has to be
referenced differently for the two declarations, the following scenario can
cause one many problems:

Module 1:

char a[80]

main()
{
      /* I don't know, put some of your favorite code here...*/
}

Module 2:

extern char *a;

anotherfunction()
{
     *a = '\0';
     /* Insure a 0 length string */
       .
       .
       .
}

the code generated in Module 2, "anotherfunction" is going to incorrectly
reference the array.  In fact, what it is going to do is concatenate the
first four entried from the array, form those into a pointer, and store
a byte length 0 whereever the concatenation points to.  This is a BAD thing
to do, in general.

[More deleted here]

>-- 
>Hans Zuidam                                    E-Mail: hans@pcg.philips.nl

           -- Kevin --

Kevin Klop		{uunet|rutgers|amiga}!cbmvax!kevin
Commodore-Amiga, Inc.

The number, 111-111-1111 has been changed.  The new number is:
134-253-2452-243556-678893-3567875645434-4456789432576-385972

peter@sugar.hackercorp.com (Peter da Silva) (04/09/89)

In article <DEVEN.89Apr7055409@daniel.pawl.rpi.edu>, deven@pawl.rpi.edu (Deven Corzine) writes:
> In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
> [...]
> >Since '\0' is equivalent to 0 on most systems,
> [...]

> Excuse me?  Name ONE system where '\0' is NOT zero???

I don't know if a 'C' compiler exists for the CDC 6400, but in their 6-bit
character set ' ' has the ascii value '\00'. The only unused value, I think,
is '\77'.
-- 
Peter "Have you hugged your wolf today" da Silva      `-_-'
...texbell!sugar!peter, or peter@sugar.hackercorp.com  'U`

dinsdale%liaison@Sun.COM (Tom van Peer) (04/11/89)

Could you guys please move this discussion to comp.lang.c or to your local
bar.  I don't think this discussion fits this newsgroup anymore.
Thanks.

Tom van Peer.

tom@pcg.philips.nl or
dinsdale@liaison.sun.com (whichever is closer to you)

fred@maccs.McMaster.CA (Fred Whiteside) (04/11/89)

In article <3697@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:
<In article <DEVEN.89Apr7055409@daniel.pawl.rpi.edu>, deven@pawl.rpi.edu (Deven Corzine) writes:
<> In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
<> [...]
<> >Since '\0' is equivalent to 0 on most systems,
<> [...]
<
<> Excuse me?  Name ONE system where '\0' is NOT zero???
<
<I don't know if a 'C' compiler exists for the CDC 6400, but in their 6-bit
<character set ' ' has the ascii value '\00'. The only unused value, I think,
<is '\77'.
<-- 
<Peter "Have you hugged your wolf today" da Silva      `-_-'
<...texbell!sugar!peter, or peter@sugar.hackercorp.com  'U`

    Gee, Peter, On our old CDC it was the colon ':' that had a six bit value
  of zero. Space ' ' was 55 (octal). Remember that good old =xzfn routine?
  I never did figure out how that one worked ... Ah the fun of printing
  ":D" to a users terminal ... (Sorry about the non-amiga stuff)

   BTW has anyone plugged an ASDG 8M for the 1000 into a SupraDrive 4x4
 before? I thought that I had read that there was a problem with the memory
 not being real close to the machine ie. first in line. Actually, I mean
 plugging a mini-rack C into the Supra; the 8M is just a card ....

-fred whiteside
 uunet!utai!utgpu!maccs!fred     fred@maccs.McMaster.CA    fred@130.113.1.9

kevinh@pnet51.cts.com (Kevin Herrboldt) (04/11/89)

peter@sugar.hackercorp.com (Peter da Silva) writes:
>I don't know if a 'C' compiler exists for the CDC 6400, but in their 6-bit
>character set ' ' has the ascii value '\00'. The only unused value, I think,
                           ^^^^^^^^^^
That's not right. 8)
(Back in the stone age when all we had to use were Cybers, we referred to
CDC's 6-bit character set as POOPSII.)

UUCP: {rosevax, crash}!orbit!pnet51!kevinh
ARPA: crash!orbit!pnet51!kevinh@nosc.mil
INET: kevinh@pnet51.cts.com

ejkst@cisunx.UUCP (Eric J. Kennedy) (04/12/89)

In article <6542@cbmvax.UUCP> kevin@cbmvax.UUCP (Kevin Klop) writes:
>Actually, there is a difference between 'a' in the following two
>declarations:
>
>char a[80];
>char *a;

[explanation and demonstration deleted]

I've always thought that there was another difference besides what you
described--one with more important and practical consequences.  I've
often had trouble with this stuff, being an inexperienced C programmer,
so somebody please tell me if this isn't right!  I just didn't see
anything like this addressed in Kevin's article.

It has been my understanding that "char *a;" gives you a pointer,
(pointing to some arbitrary place), while "char a[80];" actually
allocates 80 bytes of memory, and gives you a pointer to it, one that
you can't (or shouldn't) change.

Thus,

char a[80];
main()
{
  strcpy(a,"hello");
}

is okay, while

char *a;
main()
{
  strcpy(a,"hello");
}

will cause real problems, like overwriting your program or another task
with the word "hello".  You'd have to do a malloc() or AllocMem() or
something to have a safe place to put the "hello".

So, is this right, or is my feeling of confusion justified?

-- 
Eric Kennedy
ejkst@cisunx.UUCP

peter@sugar.hackercorp.com (Peter da Silva) (04/12/89)

In article <2393@maccs.McMaster.CA>, fred@maccs.McMaster.CA (Fred Whiteside) writes:
> In article <3697@sugar.hackercorp.com> peter@sugar.hackercorp.com (Peter da Silva) writes:
> <I don't know if a 'C' compiler exists for the CDC 6400, but in their 6-bit
> <character set ' ' has the ascii value '\00'. The only unused value, I think,
> <is '\77'.

You know, Peter, that's really amazingly stupid phrasing. "ascii value" indeed.

>     Gee, Peter, On our old CDC it was the colon ':' that had a six bit value
>   of zero. Space ' ' was 55 (octal).

Hmm. There were at least two character sets (one with 64 characters and one
with 63... with '\77' unused).

>   Remember that good old =xzfn routine?

Nope.
-- 
Peter "Have you hugged your wolf today" da Silva      `-_-'
...texbell!sugar!peter, or peter@sugar.hackercorp.com  'U`

kevin@cbmvax.UUCP (Kevin Klop) (04/13/89)

In article <17491@cisunx.UUCP> ejkst@unix.cis.pittsburgh.edu (Eric J. Kennedy) writes:
>It has been my understanding that "char *a;" gives you a pointer,
>(pointing to some arbitrary place), while "char a[80];" actually
>allocates 80 bytes of memory, and gives you a pointer to it, one that
>you can't (or shouldn't) change.
>
>Thus,
>
>char a[80];
>main()
>{
>  strcpy(a,"hello");
>}
>
>is okay, while
>
>char *a;
>main()
>{
>  strcpy(a,"hello");
>}
>
>will cause real problems, like overwriting your program or another task
>with the word "hello".  You'd have to do a malloc() or AllocMem() or
>something to have a safe place to put the "hello".
>
>So, is this right, or is my feeling of confusion justified?
>
>-- 
>Eric Kennedy
>ejkst@cisunx.UUCP


You are correct in your statements.  However, the I was addressing
the common practice of thinking of the symbol 'a' in the following
code:

char a[80]

as a pointer to the array, and using it as such.  While this works
most of the time, it is not 100% correct.

For example, in most instances, the following code will have
the same effect:

function1()
{
    char array[80];
    char *a;

    a = array;
    strcpy (a,"Hello");
}

and

function2()
{
    char array[80];

    strcpy(array,"Hello");
}

In both instances, "hello" will be placed into array[];
However, look at the definition of strcpy.  It requires
a char * for both its arguments.  the identifier 'array'
is not truly a char *, but can be used as such in this instance.

This common practice is fine normally, but there are a few times
that it can bite you.

I think (but don't know for sure), that the technical definition
of "array" in the above examples is really "&array[0]".

     -- Kevin --

Kevin Klop		{uunet|rutgers|amiga}!cbmvax!kevin
Commodore-Amiga, Inc.

The number, 111-111-1111 has been changed.  The new number is:
134-253-2452-243556-678893-3567875645434-4456789432576-385972

Disclaimer: _I_ don't know what I said, much less my employer.

nsw@cord.UUCP (Neil Weinstock) (04/13/89)

In article <6597@cbmvax.UUCP> kevin@cbmvax.UUCP (Kevin Klop) writes:
>In article <17491@cisunx.UUCP> ejkst@unix.cis.pittsburgh.edu (Eric J. Kennedy) writes:
[ stuff about pointers vs. arrays deleted ]


There is a good discussion of this stuff in Chapter 3 of Andrew Koenig's
"C Traps and Pitfalls."  I would recommend the book to anyone trying to
figure out some of the subtle nuances in C.

	Koenig, Andrew, "C Traps and Pitfalls," Addison-Wesley, 1989,
	ISBN 0-201-17928-8.

 /.- -- .. --. .- .-. ..- .-.. . ... .- -- .. --. .- .-. ..- .-.. . ...\
/ Neil Weinstock   / att!cord!nsw \ "Actually, it's still 256K, and we  \
| AT&T Bell Labs  /       or       \  fit MultiFinder in there, too."   |
\ Liberty Corner / nsw@cord.att.com \          - jimm, re: Amiga ROMs   /
 \.- -- .. --. .- .-. ..- .-.. . ... .- -- .. --. .- .-. ..- .-.. . .../

darin@nova.laic.uucp (Darin Johnson) (04/13/89)

As an example of the difference between "char *a", and "char a[100]", here
is a piece of code that bit me recently:

  put_args(xdr_wrapstring, &str)

Where I had assumed str was a "char *", but instead, was really an
array.  The routine needed the ADDRESS of the string pointer, not the
pointer.  As such, the compiler gave me a rude warning - "thou shalt not
take the address of an array!".  This was on UNIX.  I was surprised since
I do this sort of stuff in VMS, where a temporary variable is created
automatically (I can pass variables of the sort "&0", etc.).
The fix was simple:

  register char *sp;
  ... intervening code ...
  sp = str;	/* or instead, s = &str[0] */
  put_args(xdr_wrapstring, &sp);

Of course, if you pass an array or pointer as an argument to a routine,
then inside the routine, you don't have a problem, since you can always
take the address of the parameter - which is on the stack or in a temporary.

Darin Johnson (leadsv!laic!darin@pyramid.pyramid.com)
	Can you "Spot the Looney"?

jimm@amiga.UUCP (Jim Mackraz) (04/14/89)

)>In article <97113@sun.Eng.Sun.COM>, Chuck McManis writes:
)>>char	*a; /* This is a pointer to a string */
)>>char	a[80]; /* this is a pointer to a string with 80 bytes allocated */

)In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
)>  No!  char a[80] is not a pointer at all.  It is an array...


In article <231@nlgvax.UUCP> hans@nlgvax.UUCP (Hans Zuidam) writes:
)Please check your K&R before responding:
)
)	K&R 7.1, pg. 185:
)    An identifier is a primary expression, provided it has been
)    suitably declared as discussed below. If the type of the identifier
)    is "array of ...", then the value of the identifier-expression is a
)    pointer to the first object in the array, and the type of the
)    expression is "pointer to ...".

)So:
)    'char *a' is *identical* to 'char a[80]' *except* for the
)    fact that in the second definition 'a' is a *constant*
)    pointer. That is: you cannot assign a value to 'a'.

A fine reading of K&R, but if you declare

char	a[80];   in one file, and
extern char	*a; in another,

your code won't run, regardless of how you interpret K&R.

For the former, the symbol 'a' resolves to the address of 80 bytes of
storage, for the latter, 'a' resolves to an address which may contain
the address of some storage.  They differ by one level of indirection.

As a convenience, the syntax rules for using arrays and pointers are
interchangable.

In the case of function parameters, the parameter is a pointer in either
case (the address of storage, either the constant or the *contents* of a pointer)
is pushed on the stack in either case.)  When evaluating the argument, the
stack location *contains* the address of some storage.  So, K&R stress that
the declarations themselves (not just the usage syntax) are interchangable.

But, what they do NOT stress, is that in GENERAL (i.e., for globals) the 
declarations are NOT interchangable, and no compiler will help you, no
debugger will help you, and you will be dead.  Only lint will help you,
or the benefit of being killed in a previous life ...

	jimm
-- 
Jim Mackraz, I and I Computing	   	"He's hidden now, but you can see
{cbmvax,well,oliveb}!amiga!jimm          The holes where he breathes."
							- Shriekback
Opinions are my own.  Comments are not to be taken as Commodore official policy.

dmg@ssc-vax.UUCP (David Geary) (04/15/89)

In article <231@nlgvax.UUCP>, Hans Zuidam writes:

||In article <97113@sun.Eng.Sun.COM>, Chuck McManis writes:
|||char	*a; /* This is a pointer to a string */
|||char	a[80]; /* this is a pointer to a string with 80 bytes allocated */
|
|In article <2570@ssc-vax.UUCP> dmg@ssc-vax.UUCP (David Geary) writes:
||  No!  char a[80] is not a pointer at all.  It is an array...
|
|Please check your K&R before responding:
|
|	K&R 7.1, pg. 185:
|    An identifier is a primary expression, provided it has been
|    suitably declared as discussed below. If the type of the identifier
|    is "array of ...", then the value of the identifier-expression is a
                                 ^^^^^^^^

  Please *understand* your K&R before responding ;-)

  Of course, this is true - the *value* of the identifier-expression is a
pointer to the first object in the array.  What this means is:

main()
{
  char a[80];	/* an ARRAY - NOT a pointer */

  DoSomething(a);  /* here, the value of a is equivalent to &a[0], which
		      is a pointer to the first object in the array a.
		      This means we could have written:
		      DoSomething(&a[0]); and gotten the same result. */
}

|    pointer to the first object in the array, and the type of the
|    expression is "pointer to ...".
|
|and
|
|    K&R 7.1, pg. 186:
|    The expression E1[E2] is identical (by definition) to *((E1)+(E2)).

  Yes, this is true.

|
|So:
|    'char *a' is *identical* to 'char a[80]' *except* for the
|    fact that in the second definition 'a' is a *constant*
|    pointer. That is: you cannot assign a value to 'a'.

  No! (no no no ;-) - This is a common misconception that many of my
students in my introductory C class make.  char *a is NOT identical
to char a[80];  While it's true that in char a[80], the *value*
of a is a constant pointer, and in char *a, a is a variable pointer, 
there is more difference than that:

char *a;

  This gives you a pointer, period.  a can hold the address where
a char sits in memory:

---------
|       |----------->
---------

char a[80];

  This gives you an actual array of characters, there is no pointer
involved:

---------
| a[0]  |
---------
| a[1]  |
---------
| a[2]  |
---------
   .
   .
   .

  If you think that char *a and char a[80] are *identical* , *except*
for the fact that the second definition...(as stated above), try this:

main()
{
  char a[80], *p;

  strcpy(a, "I can fit in array a, because there is memory allocated for me");
  strcpy(p, "This is nothing but trouble");
}

Notice that the second strcpy is going to cause you severe headaches
(especially on an Amiga).

-- 
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
~ David Geary, Boeing Aerospace, Seattle                 ~ 
~ "I wish I lived where it *only* rains 364 days a year" ~
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

donw@zehntel.zehntel.com (Don White) (04/15/89)

In article <522@lzaz.ATT.COM> hcj@lzaz.ATT.COM (HC Johnson) writes:
>In article <12000@louie.udel.EDU>, LIZAK98%SNYBUFVA.BITNET@cornellc.cit.cornell.edu (A SHOW OF HANDS) writes:
>> for(i=0;a[i]=!'\0';i++)
>The =! has meanings you are not ready for.
>Howard C. Johnson

     Sorry about this but, ... I HATE being told I'm not ready for something!
  Just in case (A SHOW OF HANDS) feels the same way ...

     Using =! instead of !=  in this case means that you are ASSIGNING the 
  logical negation of '\0'.  And '\0' equals 0. And !0 equals 1. So, a[i]
  is being set equal to 1. Since the value of the assignment is one (i.e.
  it is TRUE) and the phrase "a[i]=!'\0'" is the conditional part of a for 
  loop, the loop would never exit.

     There now. Isn't that special?                           :-)

     Don White
     zehntel!donw
     Box 271177 Concord, CA. 94527-1177