LINUX.ORG.RU

C, не могу получить разницу между двумя указателями


0

0

Надо получить разницу между двумя указателями и передать её одной
кривой фортрановской библиотеке (не спрашивайте, зачем :). Что-то
у меня получаются какие-то странные вещи. Вот простой пример:

$ cat ptr.c
#include <stdio.h>
#include <stddef.h>
int main()
{
    void *a = (void *) 0x81792d8;
    void *b = (void *) 0xb7d23e5c;
    ptrdiff_t diff = a - b;
    printf("a=%p, b=%p, diff=%ti\n", a, b, diff);
    return 0;
}
$ gcc ptr.c -o ptr
$ ./ptr
a=0x81792d8, b=0xb7d23e5c, diff=1346720892 

Итак, получается, что 0x81792d8 - 0xb7d23e5c = 1346720892, хотя
любой калькулятор скажет, что должно быть -2948246404. Где я туплю?

А, забыл,

$ uname -a
Linux everest 2.6.20-16-generic #2 SMP Thu Jun 7 20:19:32 UTC 2007 i686 GNU/Linux

$ gcc --version
gcc (GCC) 4.1.2 (Ubuntu 4.1.2-0ubuntu4)

ero-sennin ★★
() автор топика

> что должно быть -2948246404

видимо, используется int32, в котором такие числа непредставимы.

Murr ★★
()
Ответ на: комментарий от dilmah

Блин, ну в мане сказано, что в ptrdiff_t гарантированно влезает разница между двумя указателями. Меня, выходит, обманули? :)

Числа я не сам придумал, первое - это указатель на фортрановский массив, второе - указатель на память, выделенную malloc'ом.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

-2948246404 > 2^31 и в знаковое целое не помещается.
для проверки: 2 ^ 32 - 1346720892 как раз и даст 2948246404.

bik ★★
()

следует заметить, что вычитать можно указатели только в пределах одного массива.

dilmah ★★★★★
()
Ответ на: комментарий от ero-sennin

> Блин, ну в мане сказано, что в ptrdiff_t гарантированно влезает разница между двумя указателями.

она влезает. Просто она напечаталась в знаковом виде

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

> следует заметить, что вычитать можно указатели только в пределах одного массива.

Об этом я как-то не подумал. :)

Создатели этой чудо-библиотеки таким образом организовали в Фортране-77 динамическое выделение памяти. То есть, они создат массив размера 1, потом вызывают сишную функцию, передают ей этот массив, а она выделяет кусок памяти заданного размера и возвращает разницу между началом массива и началом выделенной памяти. Потом из фортрана к этой памяти так и обращаются: array(offset + blablabla). И числа эти я не сам придумал, первое - это указатель на фортрановский массив, а второе - указатель на память, выделенную malloc'ом. И блин, как-то ведь оно у них работало, именно под Линуксом и на x86. %-/

Видно, придётся мне всё капитально переделывать.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

>И блин, как-то ведь оно у них работало, именно под Линуксом и на x86

видимо, a-b попадало в диапазон int. Если не ошибаюсь, то тип разницы - int, он же int32 для gcc/x86 и в нем в вашем конкретном примере по определению не может поместиться правильный результат. То, что вы запишете разницы в ptrdiff_t ничего не изменит, поскольку результат изначально "кривой"

anonymous
()
Ответ на: комментарий от dilmah

> она влезает. Просто она напечаталась в знаковом виде

фиг два! :) Оказалось, у меня на машине sizeof(ptrdiff_t) == sizeof(int) == 4, так что не может оно туда влезть.

ero-sennin ★★
() автор топика
Ответ на: комментарий от ero-sennin

>> следует заметить, что вычитать можно указатели только в пределах одного массива.

>Об этом я как-то не подумал. :)

Это пятЪ с плюсом. :D

anonymous
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.