Thursday, March 24, 2011

difference between far and huge pointers

as we know by default the pointers are near for example int *p is a near pointer... size of near pointer is 2 bytes in case of 16 bit compiler........ n we already know very well size varies compiler to compiler...... They only store the offset of the address the pointer is referencing. . An address consisting of only an offset has a range of 0 - 64K bytes.... i think there is no need to discuss near pointers anymore.... so come to the main point..... that is far and huge pointers......

far and huge pointers:
Far and huge pointers have a size of 4 bytes. They store both the segment and the offset of the address the pointer is referencing. thn what is the difference between them ...........

Limitation of far pointer:

We cannot change or modify the segment address of given far address by applying any arithmetic operation on it. That is by using arithmetic operator we cannot jump from one segment to other segment. If you will increment the far address beyond the maximum value of its offset address instead of incrementing segment address it will repeat its offset address in cyclic order. this is also called wrapping.....i.e. if offset is 0xffff and we add 1 then it is 0x0000 and similarly if we decrease 0x0000 by 1 then it is 0xffff and remember there is no change in the segment....

Now i am going to compare huge and far pointers..........

1.
When a far pointer is incremented or decremented ONLY the offset of the pointer is actually incremented or decremented but in case of huge pointer both segment and offset value will change.....
like if we have

int main()
{
char far* f=(char far*)0x0000ffff;
printf("%Fp",f+0x1);
return 0;
}

then the output is:
0000:0000

as we see there is no change in segment value.......

and in case of huge........

int main()
{
char huge* h=(char huge*)0x0000000f;
printf("%Fp",h+0x1);
return 0;
}

then the o/p is:
0001:0000

it shows bcoz of increment operation not only offset value but segment value also change.......... that means segment will not change in case of far pointers but in case of huge it can move from one segment to another ......

2.
When relational operators are used on far pointers only the offsets are compared.In other words relational operators will only work on far pointers if the segment values of the pointers being compared are the same. and in case of huge this will not happen, actually comparison of absolute addresses takes place...... lets understand with the help of an example...
in far...............................

int main()
{
char far * p=(char far*)0x12340001;
char far* p1=(char far*)0x12300041;
if(p==p1)
printf("same");
else
printf("different");
return 0;
}

Output:
different

in huge.......................

int main()
{
char huge * p=(char huge*)0x12340001;
char huge* p1=(char huge*)0x12300041;
if(p==p1)
printf("same");
else
printf("different");
return 0;
}

Output:
same

Explanation:
as we see the absolute address for both p and p1 is 12341 (1234*10+1 or 1230*10+41) but they are not considered equal in 1st case becoz in case of far pointers only offsets are compared i.e. it will check whether 0001==0041.... that we know is false.... and know see what will happen in case of huge.....the comparison operation is performed on absolute addresses that are equal as i already told......

3.
A far pointer is never noramlized but a huge pointer is normalized . A normalized pointer is one that has as much of the address as possible in the segment, meaning that the offset is never larger than 15.
suppose if we have 0x1234:1234 then the normalized form of it is 0x1357:0004(absolute address is 13574).......
A huge pointer is normalized only when some arithmetic operation is performed on it ... and not noramlized during assignment....

int main()
{
char huge* h=(char huge*)0x12341234;
char huge* h1=(char huge*)0x12341234;
printf("h=%Fp\nh1=%Fp",h,h1+0x1);
return 0;
}

Output:
h=1234:1234
h1=1357:0005

Explanation:
as i said above huge is not normalized in case of assignment......but if an arithmetic operation is performed on it ..... it will be normalized.... so h is 1234:1234 and h1 is 1357:0005..........that is normalized.......

4.
The offset of huge pointer is less than 16 because of normalization and not so in case of far pointers...................

lets take an example to understand what i want to say.....
int main()
{
char far* f=(char far*)0x0000000f;
printf("%Fp",f+0x1);
return 0;
}

Output:
0000:0010

in case of huge
int main()
{
char huge* h=(char huge*)0x0000000f;
printf("%Fp",h+0x1);
return 0;
}

Output:
0001:0000

Explanation:
as we increment far pointer by 1 it will be 0000:0010...... and as we increment huge pointer by 1 thn it will be 0001:0000 bcoz its offset cant be greater than 15 in other words it will be normalized............

i tried my best to explain this...... if any query and suggestion plz comment here.........

5 comments:

  1. in case 3 -compiled in Turbo C
    o/p is different

    #include
    #include
    int main()
    {
    char huge* h=(char huge*)0x12341234;
    char huge* h1=(char huge*)0x12341234;
    printf("h=%Fp\nh1=%Fp",h,h1+0x1);
    return 0;
    }





    output is Output:
    h=1234:1234
    h1=1234:1235

    ReplyDelete
  2. very nicely explained !

    can you please explain the output of

    #include

    int main()
    {
    char huge *near *far *ptr1;
    char near *far *huge *ptr2;
    char far *huge *near *ptr3;
    printf("%d, %d, %d\n", sizeof(**ptr1), sizeof(ptr2), sizeof(*ptr3));
    return 0;
    }

    http://www.indiabix.com/c-programming/complicated-declarations/discussion-627

    ReplyDelete
  3. Very good and useful tutorial ..
    very specific and to the point

    within few minutes my ideas about far pointer and huge pointer got clear .

    ReplyDelete
  4. really good..... gained a lot from this info....

    ReplyDelete

Feel free to comment......