[comp.sys.mac.programmer] Seemingly equivalent code fragments in C

s170@tank.uchicago.edu (harmon g washington) (08/08/89)

In programming the Macintosh apple menu I tried to create the Apple symbol usingthe following code:
	void MenuInits()
{
	int *bittenApple;
	
	*bittenApple = 0x0114;  	/* create Pascal string 1 byte long */
	AppleMenu = NewMenu(ApplID, bittenApple);
	.
	.
} /* menuinits() */

THIS CODE DID NOT WORK!  Instead of the Apple logo I got a random string of junkIt seemed it should have work: defining a pointer to an int; and then defining the item it points to.  Now the following fragment of code DID work:
	void MenuInits()
{
	int *bittenApple, xx;
	xx = 0x0114;
	bittenApple = &xx;
	AppleMenu = NewMenu(ApplID, bittenApple);
	.
	.
} /* menuinits() */

the following code also worked:
void MenuInits()
{
	int bittenApple;

	bittenApple = 0x0114;
	ApplMenu = NewMenu(ApplID, &bittenApple);
	.
	.
} /* menuinits() */
where #define ApplID 1
and MenuHandle ApplMenu;
I would thind the three code fragments are equivalent ways of doing the same thing in C.  Why did not the first code fragment work?
	--- Harmon Washington

levin@bbn.com (Joel B Levin) (08/08/89)

In article <4882@tank.uchicago.edu> s170@tank.uchicago.edu (harmon g washington) writes:

I'm no C wiz but at least here is one I know...

|In programming the Macintosh apple menu I tried to create the Apple symbol usingthe following code:
|	void MenuInits()
|{
|	int *bittenApple;

 You have defined a pointer to an int.
|	
|	*bittenApple = 0x0114;  	/* create Pascal string 1 byte long */

You have placed 0x0114 into the location pointed to by bittenApple,
but you have not initialized bittenApple; so you have changed the
contents of some random loaction.

|THIS CODE DID NOT WORK! . . . 

=
UUCP:     levin@bbn.com (new) or {backbone}!bbn!levin (old)
INTERNET: levin@bbn.com       		POTS: (617) 873-3463
   "The night was"

minow@mountn.dec.com (Martin Minow) (08/08/89)

In article <4882@tank.uchicago.edu> s170@tank.uchicago.edu
(harmon g washington) tries to create a Pascal string:
>	int *bittenApple;
>	
>	*bittenApple = 0x0114;  	/* create Pascal string 1 byte long */
>	AppleMenu = NewMenu(ApplID, bittenApple);
>THIS CODE DID NOT WORK!  Instead of the Apple logo I got a random string of junkIt seemed it should have work: defining a pointer to an int; and then defining the item it points to.  Now the following fragment of code DID work:

This code sequence has the following meaning:
	int *bittenApple;
		This is a pointer to a default-sized integer.  (It will
		point to a 16-bit integer on Think-C, but you cannot
		count on that.)

	*bittenApple = 0x0114;
		The current value of bittenApple (whatever it is) is the
		address of an integer.  Store 0x0114 in that location.
		This writes 0x0114 in a random location in memory.
	... NewMenu(ApplID, bittenApple);
		Pass the random location in bittenApple to NewMenu.

Note that bittenApple was never initialized and a garbage value was
passed to NewMenu (This could be the address of ROM, or a location
on the stack that is overwritten).  The second example corrects this:
>	int *bittenApple, xx;
>	xx = 0x0114;
		Store 0x0114 in xx.
>	bittenApple = &xx;
		Store the address of xx in bittenApple
>	AppleMenu = NewMenu(ApplID, bittenApple);

There is one further, in some ways more serious, problem: an integer
containing the value 0x0114 is *not* necessarily equivalent to a string.
(There are a number of subtle C-language points here that would be
better explained in a C textbook.)  A better way to perform the function
in Think C would be:
	AppleMenu = NewMenu(ApplID, "\p\024");
Here "\p" introduces a Pascal format string.  (This is not compatible
with other C's) and \024 is the octal equivalent of \x14.  A more
compatible method would be:
	char bittenApple[] = { 0x01, 0x14 };
	AppleMenu = NewMenu(ApplID, &bittenApple[0]);

The last example should work anywhere.

Hope this clarifies the problem.

Martin Minow
minow%thundr.dec@decwrl.dec.com

amanda@intercon.uu.net (Amanda Walker) (08/08/89)

In article <4882@tank.uchicago.edu>, s170@tank.uchicago.edu (harmon g
washington) writes:
[three code fragments]
> I would thind the three code fragments are equivalent ways of doing the
> same thing in C.  Why did not the first code fragment work?
> 	--- Harmon Washington
[first fragment:]
> 	void MenuInits()
> {
> 	int *bittenApple;
> 	
> 	*bittenApple = 0x0114;  	/* create Pascal string 1 byte long */
> 	AppleMenu = NewMenu(ApplID, bittenApple);
> 	.
> 	.
> } /* menuinits() */

Well, it looks like you're pretty new to programming in C.  It may take a
while to get the hang of using pointer variables, but here's why this
doesn't work:

"bittenApple" is a pointer to an integer.  The space for the integer itself
is assumed to be allocated in some other way.  Since it's a local variable,
it will start out with an undefined (random) initial value.  The assignment
statement will then take this random value, treat it as a memory address,
and stuff 0x0114 into it.  Depending on what happens to be in memory, this
will either crash your Mac or something else unpredictable.

An easier way to handle the problem of creating an Apple symbol in a string
is to take advantage of the extended string literal syntax that is available
in most Macintosh C compilers.  Try "\p\x14" or "\p\024".  This says "make
a Pascal string whose first character is 0x14 (or octal 024, which is
equivalent), and allocates space initialized to that value.  An even easier
way is to put your menus into resources...

Hope this helps,

--
Amanda Walker
InterCon Systems Corporation
--
amanda@intercon.uu.net    |    ...!uunet!intercon!amanda

nick@lfcs.ed.ac.uk (Nick Rothwell) (08/08/89)

In article <4882@tank.uchicago.edu>, s170@tank (harmon g washington) writes:
>In programming the Macintosh apple menu I tried to create the Apple symbol usingthe following code:
>	void MenuInits()
>{
>	int *bittenApple;
>	
>	*bittenApple = 0x0114;  	/* create Pascal string 1 byte long */
>	AppleMenu = NewMenu(ApplID, bittenApple);
>	.
>	.
>} /* menuinits() */
>
>THIS CODE DID NOT WORK!

...because it's faulty. You're declaring a pointer to integers
(bittenApple) without pointing it at anything. You're then assigning
the thing the pointer points at (viz. nothing) with 0x0114.  Judging
from my own personal experiences, you're probably done something like
shooting the Menu Manager through the head.

>	--- Harmon Washington

		Nick.
--
Nick Rothwell,	Laboratory for Foundations of Computer Science, Edinburgh.
		nick@lfcs.ed.ac.uk    <Atlantic Ocean>!mcvax!ukc!lfcs!nick
~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~ ~~
               Fais que ton reve soit plus long que la nuit.