Вам нужно более серьезно относиться к предупреждениям компилятора.
C не требует от компиляторов отклонить недействительные программы, для этого требуется просто «диагностика» для нарушений правил. Диагностика может быть либо фатальным сообщением об ошибке, либо предупреждением.
К сожалению, для компиляторов распространено предупреждение о назначении несовместимых типов указателей.
void main()
Это не так; это должно быть int main(void)
. Ваш компилятор может позволить вам уйти от него, и это может не вызвать никаких видимых проблем, но нет смысла не писать его правильно. (Это не совсем просто, но это достаточно близко.)
int *p;
float q;
q = 6.6;
Это нормально.
p = &q;
p
имеет тип int*
; &q
имеет тип float*
. Присвоение одного другому (без литья) является нарушением ограничения . Самый простой способ взглянуть на это - это просто незаконно.
Если вы действительно хотите сделать это задание, вы можете использовать бросок:
p = (int*)&q; /* legal, but ugly */
но редко хороший повод, чтобы сделать это. p
- указатель к int
; он должен указывать на объект int
, если у вас есть очень. Это повод, чтобы он указывал на что-то еще. В некоторых случаях само преобразование может иметь неопределенное поведение.
printf("*p = %f \n q = %f, p = %p, &q = %p \n",*p,q,p,&q);
Формат %f
требует double
аргумента (а float
аргумента назначен double
в этом контексте так float
будет хорошо). Но *p
имеет тип int
. Вызов printf
с аргументом неправильного типа приводит к тому, что поведение вашей программы не определено.
%p
требует аргумента типа void*
, а не только любого типа указателя. Если вы хотите, чтобы напечатать значение указателя, вы должны привести его к void*
:
printf("&q = %p\n", (void*)&q);
Это, скорее всего, работать без броска, но опять же, поведение не определено.
Если вы получаете какие-либо предупреждения при компиляции программы, даже не пытайтесь ее запустить. Сначала исправьте предупреждения.
Что касается вопроса в вашем заголовке, указатели типа int*
и float*
бывают разных типов. int*
должен указывать на объект int
; a float*
должен указывать на объект float
. Ваш компилятор может позволить вам их смешивать, но результат этого - либо определенный реализацией, либо неопределенный. Язык C, и особенно многие компиляторы C, позволят вам уйти со многими вещами, которые не имеют большого смысла.
Причина, по которой они являются различными типами, состоит в том, чтобы (попытаться) предотвратить или, по крайней мере, обнаружить ошибки в их использовании. Если вы объявляете объект типа int*
, вы говорите, что намерены указать ему объект int
(если он не является нулевым указателем). Хранение адреса объекта float
в вашем объекте int*
почти наверняка является ошибкой. Обеспечение безопасности типа позволяет обнаруживать такие ошибки как можно раньше (когда ваш компилятор печатает предупреждение, а не когда ваша программа вылетает во время демонстрации для важного клиента).
Скорее всего (но не гарантировано), что int*
и float*
имеют одинаковый размер и имеют одинаковое внутреннее представление. Но значение , означающее объекта int*
, не является «набором из 32 (или 64) битов, содержащих виртуальный адрес», а «что-то, что указывает на объект int
».
Пожалуйста, покажите код, который вы используете, чтобы получить этот результат. –
Если я понял, вы можете использовать объединение ... –
Это 'int main (void)', а не 'void main()'. 'void main()' полезен в основном для обнаружения книг, написанных авторами, которые не очень хорошо знают C. –