[alt.msdos.programmer] Turbo C far pointers

elrond@titan.tsd.arlut.utexas.edu (Brad Hlista) (10/28/89)

I am having a problem of getting an allocated block of far memory
to return float values.  Here is how variables are declared and dereferenced:

far *ptr;

main()
{
int i;

	ptr=(float *) farmalloc(100000);

	f(i=0;i<1000;i++)
		*(ptr+i)=3.1415927;

	for(i=0;i<10;i++)
		printf(" %f", (float) *(ptr+i) ) ;  /* is yielding 3.00000 */
}

Can someone please help me understand what is going on?
Thanks.

Brad
elrond@titan.tsd.arlut.utexas.edu
   

jwright@atanasoff.cs.iastate.edu (Jim Wright) (10/29/89)

In a recent posting elrond@titan.tsd.arlut.utexas.edu (Brad Hlista) writes:
| I am having a problem of getting an allocated block of far memory
| to return float values.  Here is how variables are declared and dereferenced:

| far *ptr;

I think this is the big part.  An int pointer is not the same as a float
pointer.  The following program works for me (MSC).

#include <stdio.h>
#include <malloc.h>
int main(void);

int main()
{
    int i;
    float far *start;
    float far *p;

    start = (float far *) _fmalloc(1000*sizeof(float));

    if (start != NULL) {
        printf("Good.\n");
        for (p=start,i=0 ; i<1000 ; i++)
            *(p++) = 3.1415927;
        for (p=start,i=0 ; i<10 ; i++)
            printf("%f\n", *(p++));
    }
    else
        printf("Oh shit.\n");
    return(0);
}

-- 
Jim Wright
jwright@atanasoff.cs.iastate.edu

bdb@becker.UUCP (Bruce Becker) (10/29/89)

In article <565@titan.tsd.arlut.utexas.edu> elrond@titan.tsd.arlut.utexas.edu (Brad Hlista) writes:
|I am having a problem of getting an allocated block of far memory
|to return float values.  Here is how variables are declared and dereferenced:
|
|far *ptr;
|
|main()
|{
|int i;
|
|	ptr=(float *) farmalloc(100000);
|
|	f(i=0;i<1000;i++)
|		*(ptr+i)=3.1415927;

Should be:	*((float *)(ptr+i)) = 3.1415927;

	Otherwise the "far" declaration of "ptr"
	will force a type conversion to the default
	of type "int". The way you have it the
	contents of of *(ptr+i)" contains an int
	value which is coerced back to float
	in the printf statement.

|	for(i=0;i<10;i++)
|		printf(" %f", (float) *(ptr+i) ) ;  /* is yielding 3.00000 */

Should be	printf(" %f", *((float *)(ptr+i)) ) ;  /* is yielding 3.1415927 */

|}
|
|Can someone please help me understand what is going on?
|Thanks.

	You need to ensure that either by default
	or by explicit declaration that
	sizeof(far) == sizeof(float); is there a
	"far long" type? Better yet, a "far float"?

	I didn't actually try this so if your compiler
	barfs on "*((float *)ptr)" where "ptr" is a
	"far *" declaration, well... you could try
	"far float * ptr;", etc...

Cheers,
-- 
  .::.	 Bruce Becker	Toronto, Ont.
w \@@/	 Internet: bdb@becker.UUCP, bruce@gpu.utcs.toronto.edu
 `/c/-e	 BitNet:   BECKER@HUMBER.BITNET
_/  \_	 In the future the term "wife" will have no gender significance

CMH117@PSUVM.BITNET (Charles Hannum) (10/29/89)

Two suggestions:

  1)  Your main problem is that you need to use the declaration:

      far float *ptr;

      I won't even try to explain what happens otherwise.

  2)  You really should use "ptr[i]" rather than "*(ptr+i)".  It effectively
      does the same thing, but it makes for much cleaner and much more
      readable code.

hp0p+@andrew.cmu.edu (Hokkun Pang) (10/31/89)

>  2)  You really should use "ptr[i]" rather than "*(ptr+i)".  It effectively
>      does the same thing, but it makes for much cleaner and much more
>      readable code.

I read from a book that "ptr[i]" will be converted to "*(ptr+i)" by the
compiler, so the "*(ptr+1)" is faster than "ptr[1]". Is that right?

spolsky-joel@CS.YALE.EDU (Joel Spolsky) (10/31/89)

In article <wZHEDrW00VoH479lIM@andrew.cmu.edu> hp0p+@andrew.cmu.edu (Hokkun Pang) writes:
>>  2)  You really should use "ptr[i]" rather than "*(ptr+i)".  It effectively
>>      does the same thing, but it makes for much cleaner and much more
>>      readable code.
>
>I read from a book that "ptr[i]" will be converted to "*(ptr+i)" by the
>compiler, so the "*(ptr+1)" is faster than "ptr[1]". Is that right?


That's ridiculous. *(A+1), A[1], and 1[A] all produce exactly the same
code. There is no reason to believe that the compiler prefers one over
the other, or that the compiler implements A[1] by first expanding
that to *(A+1). For all you know it does the opposite. 

And even if it did make a difference, it would be so small as to be
imperceivable even on the worlds slowest C compiler running on an
HP-41C. 

+----------------+----------------------------------------------------------+
|  Joel Spolsky  | bitnet: spolsky@yalecs.bitnet     uucp: ...!yale!spolsky |
|                | internet: spolsky@cs.yale.edu     voicenet: 203-436-1538 |
+----------------+----------------------------------------------------------+
                                                      #include <disclaimer.h>

levitte@garbo.bion.kth.se (Tommy Levitte) (10/31/89)

In article <990@becker.UUCP> bdb@becker.UUCP (Bruce Becker) writes:
Bruce> Xref: sics.se alt.msdos.programmer:153 comp.sys.ibm.pc:29919

Bruce> In article <565@titan.tsd.arlut.utexas.edu> elrond@titan.tsd.arlut.utexas.edu (Brad Hlista) writes:

Bruce> |far *ptr;

Bruce> |main()

[... unimportant things deleted ...]

Bruce> |	f(i=0;i<1000;i++)
Bruce> |		*(ptr+i)=3.1415927;

Bruce> Should be:	*((float *)(ptr+i)) = 3.1415927;

(* GAACK *) This means you should use the i'th INTEGER location, not float!
Wow. The effect when printing out would be quite a sight...

No, the correct syntax would be : *((float *)ptr + i)

This way, you tell the compiler that ptr really is a float pointer, then
offset the whole thing with i.

In your solution, the offset would be 2*i bytes (2 = sizeof(int)). In mine,
the offset would be 4*i bytes (4=sizeof(float)) !!!!

Bruce> |	for(i=0;i<10;i++)
Bruce> |		printf(" %f", (float) *(ptr+i) ) ;  /* is yielding 3.00000 */

Bruce> Should be	printf(" %f", *((float *)(ptr+i)) ) ;  /* is yielding 3.1415927 */

Likewise here. Use *((float)ptr + i) instead !

Bruce> 	sizeof(far) == sizeof(float); is there a
Bruce> 	"far long" type? Better yet, a "far float"?

Wow. sizeof(far) ! Never seen that before. This would mean 'far int', which is
not (as far as I know) permitted in TC.
far is only applied on pointer and functions, to tell the compiler you need a
4-byte adress to get those objects. Thus, far is a modifier, not a type.
Now, about int. int is the same as short in TC, a 2-byte integer. float is a
4-byte float.

One IMPORTANT rule when you program in C: NEVER assume anything about the size
of differnet types. NEVER !!!!!

Bruce> 	I didn't actually try this so if your compiler
Bruce> 	barfs on "*((float *)ptr)" where "ptr" is a
Bruce> 	"far *" declaration, well... you could try
Bruce> 	"far float * ptr;", etc...

Quite surprising. I just tried it with Turbo C v 2.0, writing 
*((float *)ptr+i), and it worked just nice. writing *((float *)(ptr+i)) gave
me 0.000000 when I tried it...


--
Tommy Levitte 
	gizmo@nada.kth.se
	gizmo@kicki.stacken.kth.se
	gizmo@ttt.kth.se

hollen@eta.megatek.uucp (Dion Hollenbeck) (11/01/89)

From article <990@becker.UUCP>, by bdb@becker.UUCP (Bruce Becker):
> In article <565@titan.tsd.arlut.utexas.edu> elrond@titan.tsd.arlut.utexas.edu (Brad Hlista) writes:
> |I am having a problem of getting an allocated block of far memory
> |to return float values.  Here is how variables are declared and dereferenced:
> |
> |far *ptr;
> |
> |main()
> |{
> |int i;
> |
> |	ptr=(float *) farmalloc(100000);
> |
> |	f(i=0;i<1000;i++)
> |		*(ptr+i)=3.1415927;
> 
> Should be:	*((float *)(ptr+i)) = 3.1415927;
> 
> 	Otherwise the "far" declaration of "ptr"
> 	will force a type conversion to the default
> 	of type "int".

If the pointer is declared to be of type "float far *" then the
statement  "ptr + i" says "ptr + sizeof(type of ptr)*i" even
though i is an int.  If this does not occur, then the compiler
is broken.  The program could be written thusly:

main()
{
	float far *ptr;

	ptr = (float *) farmalloc(100000);

	f(i=0;i<1000;i++)
		*(ptr+i)=3.1415927;

}

The key is to declare the pointer to be a far ptr to a type of float
and incrementation and pointer arithmetic will work.

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

        uunet!megatek!hollen       or  hollen@megatek.uucp

dbin@norsat.UUCP (Dave Binette) (11/01/89)

In article <wZHEDrW00VoH479lIM@andrew.cmu.edu> hp0p+@andrew.cmu.edu (Hokkun Pang) writes:
>I read from a book that "ptr[i]" will be converted to "*(ptr+i)" by the
>compiler, so the "*(ptr+1)" is faster than "ptr[1]". Is that right?

Its possible but not alwyays determinable.  In fact it may depend on the
compiler and the native CPU.

Some CPU's handle array indexing more efficiently than pointers so in either
case your kind of at the mercy of those who ported the compiler to your
machine.
-- 
OS2... The nightmare continues.
uucp:  {uunet,ubc-cs}!van-bc!norsat!dbin | 302-12886 78th Ave
bbs:   (604)597-4361     24/12/PEP/3     | Surrey BC CANADA
voice: (604)597-6298     (Dave Binette)  | V3W 8E7

johnl@esegue.segue.boston.ma.us (John R. Levine) (11/02/89)

In article <150@norsat.UUCP> dbin@norsat.UUCP (Dave Binette) writes:
>In article <wZHEDrW00VoH479lIM@andrew.cmu.edu> hp0p+@andrew.cmu.edu (Hokkun Pang) writes:
>>I read from a book that "ptr[i]" will be converted to "*(ptr+i)" by the
>>compiler, so the "*(ptr+1)" is faster than "ptr[1]". Is that right?
>...
>Some CPU's handle array indexing more efficiently than pointers so in either
>case your [sic] kind of at the mercy of those who ported the compiler to your
>machine.

Sheesh.  The two expressions are defined by the language to mean exactly the
same thing.  Anywhere you can use one of them, you can use the other and get
exactly the same result.  A C compiler should generate exactly the same code
for both.

In practice, every C compiler that I have seen converts ptr[i] to *(ptr+i) at
compile time, and then generates the code.  (Well, actually, I once did see a
compiler that generated different code, but it turned out to be a mutant PL/I
compiler rather than a C compiler.) I suppose there might be some microscopic
difference in compile speed between the two, but the runtime performance that
most people worry about will be identical.

This is one of the most frequently misunderstood parts of the C language.  If
you still aren't sure why the two expressions are equivalent, this would be a
good time to go back and reread your C books.
-- 
John R. Levine, Segue Software, POB 349, Cambridge MA 02238, +1 617 864 9650
johnl@esegue.segue.boston.ma.us, {ima|lotus|spdcc}!esegue!johnl
Massachusetts has over 100,000 unlicensed drivers.  -The Globe