9

How can I know the distance in bytes between 2 pointers? For example: Distance between p1 and p2

I would like to know how many bytes there are between p2 and p1 ( in this case 3) because to reach p2 with p1 I have to do 3 steps...
step1 p1 is in B
step2 p1 is in C
step3 p1 is in D

so i need that return to me 3
I'm asking this type of question because I'm implementing the lz77 algorithm

Al Lelopath
  • 6,448
  • 13
  • 82
  • 139
Giovanni Far
  • 1,623
  • 6
  • 23
  • 37
  • 2
    Just do `(const char *)p2 - (const char *)p1`? – Drew McGowen Aug 11 '14 at 16:14
  • Related: http://stackoverflow.com/q/17584416/694576 – alk Aug 11 '14 at 16:35
  • 2
    @DrewMcGowen: Why `const`? – Keith Thompson Aug 11 '14 at 17:15
  • @KeithThompson just the most general case (in case `p1` and/or `p2` are `const` pointers) – Drew McGowen Aug 11 '14 at 17:20
  • 1
    it doesnt work p1 and p2 are 2 FILE* pointers – Giovanni Far Aug 11 '14 at 17:22
  • 1
    @DrewMcGowen: The `const` certainly doesn't hurt, but it's not necessary even if `p1` and `p2` are `const` pointers. – Keith Thompson Aug 11 '14 at 17:24
  • @GiovanniFar: How doesn't it work? Are you trying to determine the difference between their positions *in a file*? Are the two `FILE*` pointers opened on the same file? Your question gives no clue of that; you actually asked about the difference between two locations *in memory*. Since this question has already gotten several decent answers, I suggest you post a new one. You may be able to do what you want with `ftell()`, but there are going to be a lot of details on top of that. – Keith Thompson Aug 11 '14 at 17:27
  • 2
    @GiovanniFar: It's likely what you're doing doesn't even make sense; I don't know why you'd have two `FILE*`s open on the same file at the same time (if that's what you're doing). – Keith Thompson Aug 11 '14 at 17:27
  • because im doing a lz77 algorithm and i need 3 pointers on the same file where each one use a different offset... in this way if i can know the distance between these pointers i can have a correct output – Giovanni Far Aug 11 '14 at 17:32
  • @GiovanniFar This makes no sense to me, why don`t you simply open the file, read it in a buffer and then subtract the pointers? – Marco Aug 11 '14 at 17:45
  • because the oput of the lz77 give three number everystep something like (A,B,C) where A=how many steps go back to te current position B=lenght occurency, C=next character if i want to know how many step i have to go back from the current position i have to use a loop... and this take time and efficiency. but if i know the position of the 2 pointers i can see how much is the distance of them... in this way i dont have do a loop everytime... do you know what i mean? – Giovanni Far Aug 11 '14 at 17:50
  • 4
    The question that you posted, and that several people have answered, has nothing to do with files. Please post a new question. (It would be unfair to edit this one after several people have gotten well-deserved upvotes for answering the question you actually asked rather than the one you meant to ask.) A "pointer" points to a location *in memory*. A location in a file is not a pointer; the C standard calls it a "file position indicator". – Keith Thompson Aug 11 '14 at 17:57

2 Answers2

18

You could try with:

ptrdiff_t bytes = ((char *)p2) - ((char *)p1);

But this only works as expected if the pointers you subtract point to the same single piece of memory or within it. For example:

This will not work as expected:

char *p1 = malloc(3); // "ABC", piece 1
char *p2 = malloc(3); // "DEF", piece 2
char *p3 = malloc(3); // "GHI", piece 3

ptrdiff_t bytes = p3 - p1; // ABC ... DEF ... GHI
                           // ^               ^
                           // p1              p3
                           // Or:
                           // GHI ... ABC ... DEF
                           // ^       ^
                           // p1      p3

// Gives on my machine 32
printf("%td\n", bytes);

Because:

  • The malloc implementation could allocate some additional bytes for internal purposes (e.g. memory barrier). This would effect the outcome bytes.
  • It is not guaranteed that p1 < p2 < p3. So your result could be negative.

However this will work:

char *p1 = malloc(9);  // "ABCDEFGHI", one piece of memory
char *p2 = p1 + 3;     // this is within the same piece as above
char *p3 = p2 + 3;     // this too

ptrdiff_t bytes = p3 - p1; // ABC DEF GHI
                           // ^       ^
                           // p1      p3



// Gives the expected 6
printf("%td\n", bytes);

Because:

  • The allocated 9 Bytes will always be in one piece of memory. Therefore this will always be true: p1 < p2 < p3 and since the padding/additional bytes are on the start/end of the piece subtraction will work.
Marco
  • 7,007
  • 2
  • 19
  • 49
  • 2
    Should be correct if both pointers point to same valid buffer, such as `p1="foo"; p2=strchr(p1, 'x');` (with that diff is 3). Otherwise, Undefined Behavior. – hyde Aug 11 '14 at 16:28
  • *hyde*'s comment applys to any arithmetic operation involving two pointers. – alk Aug 11 '14 at 16:37
  • @GiovanniFar Can I briefly see the code you are using? – Marco Aug 11 '14 at 17:37
  • im doing the compression and im in the begin (at the moment everything is in my mind) but i didnt write code lines. sooo i thought: if i can know the distance between 2 pointers (i think) i can write the compression in a easy way – Giovanni Far Aug 11 '14 at 17:41
8

Another way:

(p2-p1)*sizeof(*p1)

This works only when p1 and p2 point to memory locations that were allocated in one call to malloc family of functions.

This is valid:

int* p1 = malloc(sizeof(int)*20);
int* p2 = p1+10;

int  sizeInBytes = (p2-p1)*sizeof(*p1);

This is not valid:

int* p1 = malloc(sizeof(int)*20);
int* p2 = malloc(sizeof(int)*10);

int  sizeInBytes = (p2-p1)*sizeof(*p1); // Undefined behavior

Update, in response to comment by @chux

According to draft the C Standard (ISO/IEC 9899:201x):

6.5.6 Additive operators

...

9 When two pointers are subtracted, both shall point to elements of the same array object, or one past the last element of the array object; the result is the difference of the subscripts of the two array elements.

Community
  • 1
  • 1
R Sahu
  • 204,454
  • 14
  • 159
  • 270
  • :) It can also be (p2-p1)*sizeof(*p2) – shashank Aug 11 '14 at 16:55
  • Downvote, `p2 - p1` gives `((char *)p2 - (char *)p1) * sizeof(* p1)` if both pointers are the same type. – Marco Aug 11 '14 at 17:17
  • 3
    @d3l, that is not true. `p2-p1` is the number of elements of type `*p1` between `p1` and `p2`. Running code: http://ideone.com/zHI5aP – R Sahu Aug 11 '14 at 17:26
  • Yeah you are right, `*` should be replaced with `/`. Then its correct. – Marco Aug 11 '14 at 17:33
  • @d3l. Are you saying the correct answer is `(p2-p1)/sizeof(*p1)`? – R Sahu Aug 11 '14 at 17:37
  • @RSahu No, its just an overhead. `p2 - p1` is the same as `((char *)p2 - (char *)p1) / sizeof(* p1)` so -> `((char *)p2 - (char *)p1) / sizeof(* p1) * sizeof(* p1)` simplified: **((char *)p2 - (char *)p1)** and this **also** works if the pointers are not the same type, the other does **not**. – Marco Aug 11 '14 at 17:41
  • 1
    @d3l, since my answer is not wrong, I hope you will remove the downvote. – R Sahu Aug 11 '14 at 17:45
  • @GiovanniFar, using arithmetic operations on `FILE*` does not seem like the right thing to do. Please see my updated answer. – R Sahu Aug 11 '14 at 17:46
  • Please expand why `int sizeInBytes = (p2-p1)*sizeof(*p1);` is Undefined behavior. – chux - Reinstate Monica Aug 11 '14 at 22:44
  • 4
    @chux, added an update. I couldn't find anything else more substantial. However, from a common sense point of view, if `p1` and `p2` are results of two calls to `malloc`, there is no way we can expect a predictable value of `p2-p1`. – R Sahu Aug 12 '14 at 03:14