[comp.lang.c] Assigning an address to an integer

azarian@hpcc01.HP.COM (Randy Azarian) (06/01/90)

Can I assign an address of a variable to the value of a standard integer?

Like so:

{
  int a,d;

  a=&d;
  bdos(1,a,1);
}

This works, but gives me the following warning:

  warning C4047: '=' : different levels of indirection


By doing:

{
  int d;

  bdos(1,&d,1);
}

also works (and as far as I'm concerned, equivalent), but gives me 
the following two warnings:

   warning C4047: 'argument' : different levels of indirection
   warning C4024: 'bdos' : different types : parameter 2


The address should only contain the offset value (having the segment value
of the DS register), and should therefore be an integer, and should assign 
to a declared integer.  The is for PC's (Microsoft C 6.0), and I realize 
that it is probably different from other machines.

I suppose I only wish to eliminate the warning messages, because my
programs function fine.  Is there another way to achieve what I want
using pointers?

henry@utzoo.uucp (Henry Spencer) (06/02/90)

In article <1280003@hpcc01.HP.COM> azarian@hpcc01.HP.COM (Randy Azarian) writes:
>Can I assign an address of a variable to the value of a standard integer?

Any sensible compiler will reject this as a type mismatch.  The address of
a variable of type T is of type "pointer to T".  This is not an integer
type, and cannot be assigned to an integer variable.

If you know what you are doing, the correct way to accomplish this is by
casting the address to an integer type:

	i = (int) &x;

The result of this is very implementation-specific and you need to know
what your compiler is going to do about it.
-- 
As a user I'll take speed over|     Henry Spencer at U of Toronto Zoology
features any day. -A.Tanenbaum| uunet!attcan!utzoo!henry henry@zoo.toronto.edu

hollen@megatek.UUCP (Dion Hollenbeck) (06/02/90)

From article <1280003@hpcc01.HP.COM>, by azarian@hpcc01.HP.COM (Randy Azarian):
> Can I assign an address of a variable to the value of a standard integer?
> {
>   int a,d;
>   a=&d;
>   bdos(1,a,1);
> }
> This works, but gives me the following warning:
>   warning C4047: '=' : different levels of indirection


You can get rid of the problem by casting it:

   a = (int)&d ;

We do this all the time when passing addresses as "magic cookies".
We obtain them and do the cast.  They are then stored as ints and
passed around as ints.  When they finally get to the function
which needs them, they are cast back to a pointer of the proper
type.

-- 
	Dion Hollenbeck             (619) 455-5590 x2814
	Megatek Corporation, 9645 Scranton Road, San Diego, CA  92121

        uunet!megatek!hollen       or  hollen@megatek.uucp

chrisj@netcom.UUCP (Christopher T. Jewell) (06/02/90)

In article <486@tau.megatek.uucp> hollen@megatek.UUCP (Dion Hollenbeck) writes:
>From article <1280003@hpcc01.HP.COM>, by azarian@hpcc01.HP.COM (Randy Azarian):
>> Can I assign an address of a variable to the value of a standard integer?
>> {
>>   int a,d;
>>   a=&d;
>>   bdos(1,a,1);
>> }
>> This works, but gives me the following warning:
>>   warning C4047: '=' : different levels of indirection
>
>
>You can get rid of the problem by casting it:
>
>   a = (int)&d ;
>
>We do this all the time when passing addresses as "magic cookies".
>We obtain them and do the cast.  They are then stored as ints and
>passed around as ints.  When they finally get to the function
>which needs them, they are cast back to a pointer of the proper
>type.

Well, yeah, that will work on some systems.  On others, such as
ms-dos with large model, you will lose half your bits when you do
the cast, since a pointer is 32 bits and an int is 16.  (Randy's
code, containing a call to something called bdos(), looks like it
could suffer from such problems.)  It's not even defined whether
you will lose the most significant 16 bits, or the least significant,
or even all the odd-numbered bits.  <grin>  In brief, the results
are undefined.

It's much safer to pass your magic cookies around as void pointers
(or char pointers for old compilers).  (Or you could do the whole
thing in Modula-2, and just make them opaque types, but let's not
start another language-religion war.  :-) )
-- 
Chris   (Christopher T. Jewell)   chrisj@netcom.uucp   apple!netcom!chrisj

kitchin@hpavla.AVO.HP.COM (Bruce Kitchin) (06/06/90)

{
  int a,d;

  a=&d;
  bdos(1,a,1);
}

The problem is that &d is not of type int.  Others have suggested that you
say (int)&d.  This happens to make my blood boil.  I don't know how many
'portable' programs including this from GNU that I've tried to port to MSDOS
that made the assumption that sizeof(int) == sizeof(int *).  That is simply
not portable and on some machines such as 80x86 will only work in limited
cases.  According to K&R (page 210), "A pointer may be converted to any of
the integral types large enough to hold it.  Whether an int or long is
required is machine dependent."  Having wasted many hours trying to find all
of the places in 'portable' programs that this bad assumption has been made,
sizeof(int) == sizeof(int *), I have trouble with converting pointers to int's.

Having gotten that off my chest, let's look at your problem.  If I am making
the correct assumption, bdos looks like an MSDOS interface function.  The
only MSDOS functions that this can call are those that take a DS relative
address (ie., near address).  To use this function you must assure that the
program is compiled as a Small model program or that d is located in the defaultdata segment.  Unless the program is compiled for DS != SS, all stack allocated
variables are default data segment (all non-static local variables in your
functions, for example, and all function arguments).  If you are sure that
these assumptions are true then you can do something like:

  {
     int far *a;
     int d;
     a = &d
     bdos(1,FP_OFF(a),1);
   }

where FP_OFF is defined in dos.h.  Otherwise you should use the intdos function
in which you supply the segment registers as well as the ordinary registers
to the int 0x21 call.  Since this is a dos interface, you may want to see
if your compiler's library has a more specific dos call to do what you are
after.  For function 1, getche() suggests itself.  There are also a number
of functions supplied by MSC and Turbo-C for Dos specific interfaces.