#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2

    Displaying difference of bytes between two pointers


    I wanted to confirm that the value of "pointer + 1" depends on the data type the pointer points to.
    My hypothesis was that the address stored in a "pointer" and "pointer + 1" was different by the size of the data type.
    So for a int * pointer, the difference would be 4 bytes, whereas a chat * pointer would differ by 1 byte with an adjacent pointer.
    I made a program for this purpose, but I have trouble displaying the difference.

    Here's what I got:
    char int double
    7FFDF000 005C0032 0033006D
    7FFDF001 005C0036 00330075
    00000001 00000001 00000001
    and here's what I want:
    char int double
    7FFDF000 005C0032 0033006D
    7FFDF001 005C0036 00330075
    00000001 00000004 00000004
    I've tried casting, parenthesizing, and changing placeholders but had no luck.

    How can I get the output I want?
  2. #2
  3. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    Show us your code, please.
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2
    Forgot to do that, my bad.
    Code:
    #include<stdio.h>
    
    int main()
    {
        char *cp; int *ip; double *dp;
        printf("%-15s%-15s%-15s\n", "char", "int", "double");
        printf("%-15p%-15p%-15p\n", cp, ip, dp);
        printf("%-15p%-15p%-15p\n", cp + 1, ip + 1, dp + 1);
        printf("%-15p%-15p%-15p\n", (cp + 1) - cp, (ip + 1) - ip, (dp + 1) - dp);
    
    }
  6. #4
  7. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    If you ever end up working in supply (in the reserves, I was once in a supply unit that did warehousing work), you will need to learn the concept of unit of issue along with quantity. Each of those quantities of one have different units of issue, so they are accurately reporting the differences to be one char, one int, and one double. At least that's how I'm interpreting it.

    I played around with your code a bit. For one thing, you have warnings for the printf that you use to display the difference between pointers, because that difference is not a pointer.

    Here's what I changed it to:
    Code:
    #include<stdio.h>
    
    int main()
    {
        // using real addresses so as to not be using uninitialized pointers
        //      (unintialized pointers shouldn't cause any real problem here,
        //       but it just plain feels wrong!)
        char ch;
        int  n;
        double d;
        char *cp = &ch; 
        int *ip = &n; 
        double *dp = &d;
        
        printf("%-15s%-15s%-15s\n", "char", "int", "double");
        printf("%-15p%-15p%-15p\n", cp, ip, dp);
        printf("%-15p%-15p%-15p\n", cp + 1, ip + 1, dp + 1);
        
        // changed format flags to get rid of the warning
    //    printf("%-15p%-15p%-15p\n", (cp + 1) - cp, (ip + 1) - ip, (dp + 1) - dp);
        printf("%-15d%-15d%-15d\n", (cp + 1) - cp, (ip + 1) - ip, (dp + 1) - dp);
        
        // added this line, typecasting the pointers to char* in order to the 
        //  difference in bytes
        printf("%-15d%-15d%-15d\n", (char*)(cp + 1) - (char*)cp, 
                                    (char*)(ip + 1) - (char*)ip, 
                                    (char*)(dp + 1) - (char*)dp);
    
        return 0;
    }
    Here is the output (using code tags to preserve column spacing):
    Code:
    C:TEST\046>a
    char           int            double
    0022FF7F       0022FF78       0022FF70
    0022FF80       0022FF7C       0022FF78
    1              1              1
    1              4              8
    
    C:TEST\046>
    I don't know if my "unit of issue" interpretation of line 3 is correct, but line 4 seems to support it. Somebody who knows better than I should comment.
    Last edited by dwise1_aol; July 8th, 2013 at 03:34 PM.
  8. #5
  9. Banned ;)
    Devshed Supreme Being (6500+ posts)

    Join Date
    Nov 2001
    Location
    Woodland Hills, Los Angeles County, California, USA
    Posts
    9,638
    Rep Power
    4247
    Originally Posted by dwise1_aol
    I played around with your code a bit. For one thing, you have warnings for the printf that you use to display the difference between pointers, because that difference is not a pointer.
    Technically, per the C standards, the pointer arithmetic return type is ptrdiff_t. To display a ptrdiff_t, one would use the format string "%td".

    <sidenote>I'm actually impressed that 046 used "%p" to print the pointer addresses :). A lot of C programmers don't know that format string.</sidenote>
    Up the Irons
    What Would Jimi Do? Smash amps. Burn guitar. Take the groupies home.
    "Death Before Dishonour, my Friends!!" - Bruce D ickinson, Iron Maiden Aug 20, 2005 @ OzzFest
    Down with Sharon Osbourne

    "I wouldn't hire a butcher to fix my car. I also wouldn't hire a marketing firm to build my website." - Nilpo
  10. #6
  11. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2
    you have warnings for the printf that you use to display the difference between pointers, because that difference is not a pointer.
    Somehow my compiler didn't return any warnings.


    // added this line, typecasting the pointers to char* in order to the
    // difference in bytes
    So you take advantage of the fact that the size of a char data is exactly one byte.
    The difference
    (ip + 1) - ip
    is is one int unit, which is four bytes, which is four char units.

    Technically, per the C standards, the pointer arithmetic return type is ptrdiff_t. To display a ptrdiff_t, one would use the format string "%td".
    Wow, there's a type for pointer differences?
    However, when I replaced my placeholders with td, my compiler didn't seem to recognize td as one: it printed "tdtdtd".
  12. #7
  13. Contributed User
    Devshed Specialist (4000 - 4499 posts)

    Join Date
    Jun 2005
    Posts
    4,392
    Rep Power
    1871
    You need a C99 compiler to get the additional formats like %td and %zd.

    Also, you might consider this particular identity.
    If you have
    p = &a[i]; // a pointer to the i'th element of a
    You can also write this as
    p = a+i; // a pointer to the i'th element of a

    Now, turn it around, and subtract a from both sides (this is just algebra)
    i = p - a;
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper
  14. #8
  15. Contributing User
    Devshed Supreme Being (6500+ posts)

    Join Date
    Jan 2003
    Location
    USA
    Posts
    7,172
    Rep Power
    2222
    OK, so first I hit you with SK knowledge (OK, so now it's LS; Storekeepers became Logistics Specialists a few years ago as a few US Navy ratings merged together) and now it's physics.

    In physics, you express relationships algebraically. But the interesting part is that the units of measurement are also treated as if they were algebraic factors. For example:

    60 miles per hours is 60 mi/hr
    1mi = 1609.344 meters
    1 hr = 3600 sec
    60 mi/hr = 60 mi*1*1 = 60 mi/hr * 1609.344 m/1 mi * 1 hr / 3600 sec
    60 mi/hr = 60 * 1609.344 / 3600 * m/sec * 1mi / 1mi * 1hr / 1hr
    60 mi/hr = 60 * 1609.344 / 3600 * m/sec * 1 * 1
    60 mi/hr = 26.8224 m/sec

    At my first professional software job, we had all kinds of unit conversions to work with. Everybody would come to me for the answers. It was all so very simple.

    Each pointer comes with its own units of measurement. Rather than assume one particular unit of measurement to be universal (ie, 1 byte), perhaps we should use something like this:
    Code:
    printf("%-15d%-15d%-15d\n", ((cp + 1) - cp)*sizeof(char), 
                                    ((ip + 1) - ip)*sizeof(int), 
                                    ((dp + 1) - dp)*sizeof(double));
    Makes no assumptions.
    Last edited by dwise1_aol; July 9th, 2013 at 01:43 PM. Reason: Corrected the calculation
  16. #9
  17. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Jun 2013
    Posts
    142
    Rep Power
    2
    [quote = salem]
    You need a C99 compiler to get the additional formats like %td and %zd.[/quote]
    I see, thanks.
    Originally Posted by dwise1_aol

    Each pointer comes with its own units of measurement. Rather than assume one particular unit of measurement to be universal (ie, 1 byte), perhaps we should use something like this:
    Code:
    printf("%-15d%-15d%-15d\n", ((cp + 1) - cp)*sizeof(char), 
                                    ((ip + 1) - ip)*sizeof(int), 
                                    ((dp + 1) - dp)*sizeof(double));
    Makes no assumptions.
    So for example, (ip + 1) - ip is one integer units, which is four bytes.
    This concept of "unit of measurement" (with bytes acting like the metric system) is quite interesting.
    (and also intuitive thanks to your example)

IMN logo majestic logo threadwatch logo seochat tools logo