[comp.lang.c] Novice MicroSoft C5.1 question

richardp@tekigm2.MEN.TEK.COM (Richard R Prince) (07/26/90)

  Could anyone explain the unexpected output of these two programs
to me please??  Being a beginning C person, it's entirely likely that
I have a simple syntax error or my concept of pointers is wrong.  I
am using MicroSoft C5.1 on a '386@16MHz.  I posted this once before,
but received no help; not even to tell me how stupid I am and that
such a simple question is beneath response.    As to the question:

Running this:

#include <stdio.h>
main()
{
 int x=100;
 int *y;
 y= &x;
 printf("\nx:%d  &x:%u",x,&x);
 printf("  y(add of x):%u",y);
 printf("  &y(add of y):%u",&y);
 printf("  *y(value of x):%d\n",*y);
}

produces the output I would expect:
x:100  &x:11094  y(add of x):11094  &y(add of y):11090  *y(value of x):100

But running this:

#include <stdio.h>
main()
{
 int x=100;
 int *y;
 y= &x;
 printf("\nx:%d  &x:%u",x,&x);
 printf("  y(add of x):%u  &y(add of y):%u  *y(value of x):%d\n",y,&y,*y);
}

Produces the unexpected output:
x:100  &x:11094  y(add of x):11094  &y(add of y):7647  *y(value of x):11090

I do not understand why there is a difference.  Could some nice soul explain
this in a way a novice could understand??  Thanks in advance.

richardh@hpopd.HP.COM (Richard Hancock) (07/26/90)

Far pointers (ie. segment:offset) are 32-bit quantities in Microsoft-C. Your printf format strings assume that they are represented in 16-bits (ie. %u).

The latter example doesn't work because the segment part of y is being treated as the value for the second %u, ie. y is actually 7647:11094 and &x is 7647:11090.

Whether or not pointers are considered to be far by default depends on the memory model you're compiling under.

Richard.

brianh@hpcvia.CV.HP.COM (brian_helterline) (07/26/90)

>  Could anyone explain the unexpected output of these two programs
>to me please??  Being a beginning C person, it's entirely likely that
>I have a simple syntax error or my concept of pointers is wrong.  I
>am using MicroSoft C5.1 on a '386@16MHz.  I posted this once before,
>but received no help; not even to tell me how stupid I am and that
>such a simple question is beneath response.    As to the question:

>Running this:

[ example deleted ]

>#include <stdio.h>
>main()
>{
> int x=100;
> int *y;
> y= &x;
> printf("\nx:%d  &x:%u",x,&x);
> printf("  y(add of x):%u  &y(add of y):%u  *y(value of x):%d\n",y,&y,*y);
>}
>
>Produces the unexpected output:
>x:100  &x:11094  y(add of x):11094  &y(add of y):7647  *y(value of x):11090

>I do not understand why there is a difference.  Could some nice soul explain
>this in a way a novice could understand??  Thanks in advance.
>----------

	The problem is that you are printing out an address using %u
	which expects sizeof( unsigned int ) bytes on the stack but
	you are shoving an address onto the stack.  To print out an
	address, use %p ( MSC RunTime Ref pg 459 ).  Also, it is
	important to know what memory model you are using.  The %p
	requires a far pointer.  The code below will work with any
	memory model.  (I did not test this code :)

#include <stdio.h>
main()
{
 int x=100;
 int *y;
 y= &x;
 printf("\nx:%d  &x:%p",x,(int far *)&x);
 printf("  y(add of x):%p  &y(add of y):%p  *y(value of x):%d\n",(int far *)y,
			(int far *)&y, *y);
}


Hope this helps.
-Brian

karl@haddock.ima.isc.com (Karl Heuer) (07/31/90)

In article <31530011@hpcvia.CV.HP.COM> brianh@hpcvia.CV.HP.COM (brian_helterline) writes:
>To print out an address, use %p.  Also, it is important to know what memory
>model you are using.  The %p requires a far pointer.

For portable usage, you should cast the pointer to (void *); it's not always
true that `int *' and `void *' have the same representation.  Apparently MSC
requires you to also use the `far' keyword in some memory models, but if they
claim to be standard conforming, that's a bug%.

Karl W. Z. Heuer (karl@kelp.ima.isc.com or ima!kelp!karl), The Walking Lint
________
% The very existence of a `far' keyword is non-Standard, but that's not what
  I'm talking about.  X3J11 says that `%p' matches `void *'.  If `void far *'
  has a different representation, there should be a different format specifier
  (e.g. `%Fp') to print it, so as to avoid breaking strictly conforming code
  that doesn't use `far'.

kdq@demott.COM (Kevin D. Quitt) (08/02/90)

In article <17179@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>
>For portable usage, you should cast the pointer to (void *); it's not always
>true that `int *' and `void *' have the same representation.  Apparently MSC
>requires you to also use the `far' keyword in some memory models, but if they
>claim to be standard conforming, that's a bug%.

   MSC's %p prints the pointer in the format SSSS:OOOO (segment/offset), with
%Np printing only the OOOO portion.  Both forms expect a 32 bit pointer,
so non-32 bit pointers must be coerced by using the far keyword.

-- 
 _
Kevin D. Quitt         demott!kdq   kdq@demott.com
DeMott Electronics Co. 14707 Keswick St.   Van Nuys, CA 91405-1266
VOICE (818) 988-4975   FAX (818) 997-1190  MODEM (818) 997-4496 PEP last

                96.37% of all statistics are made up.

scs@adam.mit.edu (Steve Summit) (08/03/90)

In article <17179@haddock.ima.isc.com> karl@haddock.ima.isc.com (Karl Heuer) writes:
>
>For portable usage, you should cast the pointer to (void *); it's not always
>true that `int *' and `void *' have the same representation.  Apparently MSC
>requires you to also use the `far' keyword in some memory models, but if they
>claim to be standard conforming, that's a bug%.

In article <440@demott.COM> kdq@demott.COM (Kevin D. Quitt) writes:
>   MSC's %p prints the pointer in the format SSSS:OOOO (segment/offset), with
>%Np printing only the OOOO portion.  Both forms expect a 32 bit pointer,
>so non-32 bit pointers must be coerced by using the far keyword.

The Standard does not say anything about near and far pointers.
The Standard says that if you pass a void * to %p, the pointer
will be printed in some machine-dependent way.  Karl is correct;
the Microsoft compilers are not ANSI-compliant in this regard.
It's not an academic question, either; the correct and portable
code

	int *ip;
	...
	printf("%p\n", (void *)ip);

will not function as intended under MSC if a small-data memory
model is used, while the "Microsoft compliant" code

	printf("%p\n", (void far *)ip);

is obviously not portable to compilers without a nonstandard far
keyword.  %p can be quite useful, if only when debugging; it's a
miserable pain to have to surround usages of it with #ifdef MSC
or the like when Microsoft compilers are in use.

It has been observed that other segmented architecture/language
combinations than 80*86/C do not make the existence of segments
so manifestly visible at the HLL source level.  Why should a C
programmer be intimately concerned with segments and offsets and
near and far pointers?  (The answer, of course, is obvious:
transparency would most easily be implemented by having "large
model" the default, which would clearly be far "too inefficient.")
Microsoft C v6.0 makes the problem worse, not better: programmers
are encouraged to make use of the new "based pointers" to
"control placement of data in segments and generate better code
for far-pointer manipulation" (this according to the marketing
hype in the compiler documentation).  It looks to me like based
pointers are merely less portable and more confusing.  (I
shouldn't have gone off on this tangent; now the Intel and
Microsoft apologetics will rush to the defense and I'll have
started a flame war...)

                                            Steve Summit
                                            scs@adam.mit.edu

johnb@srchtec.UUCP (John Baldwin) (08/08/90)

In article <440@demott.COM> kdq@demott.COM (Kevin D. Quitt) writes:
[referring to printf() formatting in Microsoft C ver 5.10]
>   MSC's %p prints the pointer in the format SSSS:OOOO (segment/offset), with
>%Np printing only the OOOO portion.  Both forms expect a 32 bit pointer,
>so non-32 bit pointers must be coerced by using the far keyword.

A good way to make your code a little more portable (note the use of the
relative term as opposed to the absolute) is to encapsulate the pointer
type...

If you have some oft-included header file (call it <generic.h>), insert a
typedef such as
     typedef void far *     genptr;

Choose the identifier to suit yourself and your coding style... then you can
write
      printf("Address of foob is [%p] \n", (genptr)&foob);

If you move to another implementation, you only have to change the typedef.
  [Obviously, in this instance, you'll have to do more than that,
   since there's not a '%p' format specifier in the ANSI printf()!!!
   Sorry.  :-/ ]

-- 
John T. Baldwin                      |  johnb@srchtec.uucp
Search Technology, Inc.              |  johnb%srchtec.uucp@mathcs.emory.edu
standard disclaimer:                 |  ...uunet!samsung!emory!stiatl!srchtec..
opinions and mistakes purely my own. |  ...mailrus!gatech!stiatl!srchtec...

karl@haddock.ima.isc.com (Karl Heuer) (08/09/90)

In article <165@srchtec.UUCP> johnb@srchtec.UUCP (John Baldwin) writes:
>there's not a '%p' format specifier in the ANSI printf()!!!

Is too.

diamond@tkou02.enet.dec.com (diamond@tkovoa) (08/09/90)

In article <165@srchtec.UUCP> johnb@srchtec.UUCP (John Baldwin) writes:

>      printf("Address of foob is [%p] \n", (genptr)&foob);
>If you move to another implementation, you only have to change the typedef.
>  [Obviously, in this instance, you'll have to do more than that,
>   since there's not a '%p' format specifier in the ANSI printf()!!!

Well, the last draft did define %P instead of %p, but that appears to be
a typo.  Aside from the place where it's defined, they refer to it as %p.
-- 
Norman Diamond, Nihon DEC     diamond@tkou02.enet.dec.com
This is me speaking.  If you want to hear the company speak, you need DECtalk.

johnb@srchtec.UUCP (John Baldwin) (08/09/90)

In article <1906@tkou02.enet.dec.com> diamond@tkou02.enet.dec.com
(diamond@tkovoa) writes:
>
>Well, the last draft did define %P instead of %p, but that appears to be
>a typo.  Aside from the place where it's defined, they refer to it as %p.

Okay, it can happen to the best of us (and I am NOT the best of us :) :) :)).
I missed the fact that they *DID* put the pointer-format representation
into the ANSI printf().  In fact, Michael Meissner at OSF (the guy who got
X3J11 to include '%p') was kind enough to point this out.

THIS solves a lot of problems for portability, and I for one am very glad
I was wrong (I've been grumbling all this time about not being able to
portably print pointers).
    [p'p'p'-- say THAT 5 times fast!]

-- 
John T. Baldwin                      |  johnb@srchtec.uucp
Search Technology, Inc.              |  johnb%srchtec.uucp@mathcs.emory.edu
standard disclaimer:                 |  ...uunet!samsung!emory!stiatl!srchtec..
opinions and mistakes purely my own. |  ...mailrus!gatech!stiatl!srchtec...

colin@array.UUCP (Colin Plumb) (08/09/90)

In article <165@srchtec.UUCP> johnb@srchtec.UUCP (John Baldwin) writes:
>  [Obviously, in this instance, you'll have to do more than that,
>   since there's not a '%p' format specifier in the ANSI printf()!!!
>   Sorry.  :-/ ]

Yes, there is!  %p prints the value of a (void *) pointer in an
implementation-defined manner.  %Np and %Fp are Microsoft inventions,
but the first I heard about %p was when reading the ANSI spec.

(Ref: 4.10.something)
-- 
	-Colin