Kohila G Ответов: 3

Ошибка при приведении целого числа к указателю на целое число


Я получаю такое сообщение об ошибке. Я этого не понимаю, и не могли бы вы сказать, пожалуйста, почему я получаю эту ошибку.
Цитата:
7: предупреждение: приведение к указателю из целого числа разного размера [-Wint-to-pointer-cast]
pi = (int *)num;
^


Что я уже пробовал:

#include<stdio.h>

int main()
{
        int num = 10;
        int *pi = &num;
        //pi = &num is also valid
        printf("%d",*pi);
        //Typecasting
        //pi = num;
        //Will show an error because you can't convert a integer to a 'pointer to the data type integer' However, it is possible to typecast
        pi = (int *)num;
        printf("After typecasting : %d",*pi);


}

3 Ответов

Рейтинг:
1

Stefan_Lang

int num;
...
(int *)num;

Никогда.
Делать.
Вот это!

OriginalGriff уже указывал, почему это будет идти не так (в большинстве случаев). Я иду еще дальше - вот некоторые общие проблемы:

1. Когда вам нужно привести тип чего-то к чему-то другому, это очень часто является признаком того, что в вашем коде что-то не так: либо вы выбрали неподходящий тип для своей локальной переменной, либо вы неправильно используете свои переменные. Или может еще что-то. Хорошо написанный код обычно не нуждается в приведении типа. Приведение типа в коде C/C++ - это все равно что сказать вам: - Кессель пролетел меньше чем за 12 парсеков."[^] : вы не используете правильную единицу измерения!

2. Никогда не бросит типа указатель на указатель типа или наоборот. Адрес-это нечто совершенно иное, чем объект, расположенный по этому адресу. Есть только одно исключение, которое я могу придумать, только то, что оно вызвано Microsoft и поэтому его нельзя избежать: использование DWORD для передачи указателей/адресов через события Windows. Microsoft изменила свои древние библиотеки win32, чтобы использовать вместо них тип DWORD_PTR. Не очень большое улучшение, но, по крайней мере, это будет использовать достаточно большой тип int, чтобы удерживать указатель и работать так, как ожидалось. Все еще нет оправдания, чтобы использовать этот шаблон для вашего собственного кода.

3. В C++ (ваш вопрос помечен как C++) вы не должны использовать приведения типов в стиле C. Вместо этого вы должны использовать reinterpret_cast, dynamic_cast, static_cast, или const_cast (видеть Преобразования типов - учебники по C++ [^]

4. Когда вы пишете some_type variable; и затем (some_other_type)variable вы говорите компилятору полностью игнорировать исходное объявление вашей переменной. Компилятор будет проверять, сколько места some_other_type требуется, и доступ к памяти по адресу вашей переменной, используя размер some_other_type Если размеры типов не совпадают, это, скорее всего, вызовет серьезные проблемы. Даже если они совпадают, это не гарантирует, что следующий код будет корректно обрабатывать вашу переменную. К счастью, если вы используете преобразования типов C++ (см. пункт 3 выше), то компилятор предупредит вас о потенциальных проблемах такого рода. Если вы используете приведения типов в стиле C, компилятор часто будет молчать, потому что для компилятора C приведение типов эквивалентно высказыванию: "заткнись, я знаю это лучше тебя.И такого рода утверждения почти всегда ложны.

5. приведения типов стиля C имеют раздражающий(?) побочный эффект, иногда делая больше, чем просто переосмысливая память: когда вы приведете один числовой тип к другому, вы получите значимое преобразование. например. int num = (int)3.14; это даст 3, а не какое-то странное число, которое вы получите, переосмыслив представление IEEE значения float 3.14. Это поведение, безусловно, то, чему вы можете научиться и привыкнуть, но это просто еще один камень, о который вы можете споткнуться, когда используете слепки типа без необходимости или неуместно.


Рейтинг:
0

Patrice T

Прежде всего, добавьте точку с запятой в конце текста.

int *pi = &num


Kohila G

Извините, если я добавлю ; после &num здесь, он каким-то образом преобразуется в '#'. Не знаю почему. Но не обращай на это внимания.

Mohibur Rashid

Ха-ха, вам нужно иметь некоторые знания о кодировке html. Я делаю это для тебя

Kohila G

Спасибо

Рейтинг:
0

OriginalGriff

Цитата:
предупреждение: приведение к указателю из целого числа разного размера [-Wint-to-pointer-cast]
pi = (int *)num;

num является целым числом:
int num = 10;
Это означает, что в вашем компиляторе это, вероятно, 32 - битное число-оно может содержать значения между -2,147,483,648 (-231) через 2,147,483,647 (231 − 1) )
pi это указатель на целое число, что в вашем компиляторе означает, что это 64-битный указатель.
int *pi = &num;
(И да, чтобы скомпилировать ваше приложение, вам нужно закончить эту строку точкой с запятой)
int *pi = &num
Хотя можно привести целое число к указателю, это не очень хорошая идея, отчасти потому, что вы не можете получить действительный 64-битный указатель в 32 бита, а отчасти потому, что это может вызвать странные ошибки.
Когда процессор выбирает 64-битное число, он игнорирует самые низкие 4 бита адреса, потому что 64-битные обращения к памяти всегда происходят на 16-байтовых границах: Выравнивание данных при переходе на 64-разрядную архитектуру Intel® [^]
32-битные значения выровнены по 8-байтовым адресам, поэтому, рассматривая его как 64-битный указатель, он может получить доступ к вашему целочисленному значению в верхнем или нижнем 32-битном указателе.

Это означает, что вы можете внести кажущееся невинным и безобидным изменение в свое приложение, и несвязанный фрагмент кода потерпит неудачу странным образом.
Поэтому, когда вы пытаетесь привести целое число к указателю, компилятор говорит: "Вы уверены, что знаете, что делаете? Ты действительно хочешь это сделать?":
pi = (int *)num;

И ответ: "Нет! Я совершил ошибку!"и ты действительно хотел этого:
pi = &num;


Kohila G

Спасибо, что ответили.

CPallini

5.