2016-09-21 6 views
0

Я хочу, чтобы вычислить расстояние между БСОМ секцией программы, и в начале кучной секции, так что у меня есть программа, как это:Pointer arithmatic не удался собрать, НКУ говорит преобразование недопустимого типа

$ cat 1.cpp

#include<unistd.h> 
#include<stdlib.h> 
#include<stdio.h> 
int empty;//bss 
int main() 
{ 
    char*p=(char*)malloc(0); 
    printf("%d\n",(int)p-(int)&empty); 
    return 0; 
} 

Когда я скомпилировать этот код с помощью:

$ g++ 1.cpp 

ошибки:

1.cpp: In function ‘int main()’: 
1.cpp:8:22: error: cast from ‘char*’ to ‘int’ loses precision [-fpermissive] 
    printf("%d\n",(int)p-(int)&empty); 
       ^
1.cpp:8:30: error: cast from ‘int*’ to ‘int’ loses precision [-fpermissive] 
    printf("%d\n",(int)p-(int)&empty); 
         ^

Я не думаю, что это неприлично преобразовать int* в int. Я нашел множество примеров, делающих это в Интернете.

Почему мой код не компилируется?

+0

@ user1810087 Ваше удаление тега C++ неверно. OP использует g ++, а код - C++ (он также будет скомпилирован в C, так как языки похожи, но вопрос не о C). – 2501

ответ

3

Не всегда доверяйте тому, что вы читаете в Интернете.

Предположительно, вы находитесь на платформе, где указатели 64-разрядные, а int - 32-разрядный. В этом случае преобразование из указателя в int теряет точность, и вы компилируете флажки справа, чтобы сделать это ошибкой. Отлично сработано!

Тип, который вы ищете для преобразования указателя в интегральный тип: uintptr_t. Это определяется стандартом, чтобы иметь достаточную ширину, чтобы обеспечить конверсию без потерь.

+0

Кроме того, предположение о том, что области malloced должны быть в любом отношении к .bss, как правило, является ошибочным в наши дни. Там могут быть пробелы, и есть реализации, которые выделяют из mmaped областей, расположенных выше bss. – arsv

1

Тип, который следует отличать от указателей, должен быть uintptr_t, который гарантированно не теряет точность, см. Также fixed width integer types.

Если вы настаиваете на использовании printf, вам нужно найти правильный форматтер, потому что это не исправлено. В противном случае используйте:

std::cout << reinterpret_cast<uintptr_t>(p); 
1

Вы можете p-reinterpret_cast<char*>(&empty)

Но я не вижу никаких причин, чтобы вычислить расстояние между двумя адреса. (и это неопределенное поведение, как указано @mch)

+0

'% d' является неправильным спецификатором для печати разницы между двумя указателями. Это также неопределенное поведение для вычисления разницы между двумя указателями, которые не указывают на один и тот же блок памяти. – mch

+0

ну, я использую '% d', потому что OP его использует, и я утверждаю, что я не вижу причин для этого. –

+0

ответ отредактирован. –