1

I need to know the memory distance between two substructures

(&my_type.a - &my_tape.b.c)

What is the type of the result? I need to cast it to (signed int), so obviously it's something else.

PeeHaa
  • 66,697
  • 53
  • 182
  • 254
  • Please tag the question with the appropriate language. Is this D, Go, or C#? – Kerrek SB Nov 12 '13 at 09:52
  • If you are interested in, same question in fortran with iso_c_bindings: http://stackoverflow.com/questions/19926504/diffptr-t-fortran-with-iso-c-bindings – user2885778 Nov 12 '13 at 10:28

3 Answers3

6

According to the C11 standard, §6.5.6/9,

When two pointers are subtracted… The size of the result is implementation-defined, and its type (a signed integer type) is ptrdiff_t defined in the <stddef.h> header.

Potatoswatter
  • 126,977
  • 21
  • 238
  • 404
  • I think the really confusing issue here, which the OP may discover later after the product is shipped, is that her original expression computes the *number of elements* in the range, not the number of *bytes*. – Kerrek SB Nov 12 '13 at 11:07
  • In any case, this one here is the correct answer to the question, and not the one that was accepted. – Jens Gustedt Nov 12 '13 at 12:38
  • How it could be "the number of elements in the range" when it concerns two different structures (of two different types)? – user2885778 Nov 12 '13 at 12:43
  • @user2885778 You didn't mention that in the question, but they are required to be the same type. The entire first sentence is, "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." If this isn't satisfied, then the code is fundamentally nonsense and you get undefined behavior. (Since all memory allocations behave as `char` arrays, you can always get the distance in bytes by casting both operands to `char *`.) – Potatoswatter Nov 12 '13 at 14:55
  • Requiring the pointed-to objects to be the same type (referring to the first sentence of the previous comment) is insufficient to guarantee a defined or sensible result. Consider `struct { double a; int b; double c; }` in an implementation with eight-byte `double`, four-byte `int`, and an alignment requirement for `double` of only four bytes. Then `c` and `a` may be only four bytes apart, which is “half an element”, so the result of `&foo.c - &foo.a` would not express the distance between `c` and `a` in a sensible way. – Eric Postpischil Nov 12 '13 at 15:44
  • @EricPostpischil … hence the direct quote from the standard. I never claimed to be providing all the requirements of the operation anyway. – Potatoswatter Nov 12 '13 at 23:13
1

You can use a size_t for that (which is often unsigned int) If you need it signed use ssize_t see What is size_t in C?

Edit: You probably should use ptrdiff_t for that see http://www.viva64.com/en/a/0050/

Community
  • 1
  • 1
Antzi
  • 11,625
  • 6
  • 40
  • 66
0

First, you cannot take the addresses of members of types. If my_type is a type name, then &my_type.a is not a valid expression. You first need an object of the type. E.g., you could use my_type foo; (&foo.a - &foo.b.c).

Second, if a and c are not character types, then the result of &foo.a - &foo.b.c is not defined by the C standard, even if they are the same type as each other. The C standard defines the result of subtracting pointers only if they are pointers to elements in the same array object or one past the last element of the array object. (For this purpose, a single element behaves as an array of one element.)

You can obtain a defined result by converting the pointers to a character type:

my_type foo;
(char *) &foo.a - (char *) &foo.b.c

The result of this expression has type ptrdiff_t. It is defined because the entire object foo may be treated as an array of char, so pointers to bytes within it may be subtracted.

Eric Postpischil
  • 141,624
  • 10
  • 138
  • 247