Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.67/9: Рейтинг темы: голосов - 9, средняя оценка - 4.67
0 / 0 / 0
Регистрация: 09.06.2019
Сообщений: 5

Почему это работает?

09.06.2019, 17:08. Показов 1956. Ответов 10

Студворк — интернет-сервис помощи студентам
Доброго времени суток. Написал следующую штуку
C++
1
2
3
4
5
6
7
8
9
10
11
12
void foo(char r)
{
    std::cout << r << std::endl; 
}
 
int main()
{
    void* ptr = &foo;
    std::cout << static_cast<int(*) (float)>(ptr)(5.7); 
 
    return 0;
}
Вывод:
f
252885984
Мусор, что логично, хотя f все же является первыми младшими битами представления 5.7, но это такое. 252885984 это что-то рядом стоящее, как я понимаю.

Не могли бы вы объяснить, почему вообще это работает? Я так понимаю, это из-за static_cast, потому что он не делает проверок возможности приведения, но что происходит внутри всего этого?

Премного благодарю за внимание
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
09.06.2019, 17:08
Ответы с готовыми решениями:

Почему это не работает?
Здравствуйте, почемуто программа работает не так как хотелось бы вроде всё просто, нужно чтобы то что написано в &quot;menu&quot;...

C++ Почему это не работает?
Помогите пожалуйста разобраться(создать студента и группу используя наследование) Код: #include&lt;iostream&gt; ...

почему это так работает
по заданию надо создать два одинаковых массива с случайными числами от 0 до 99 for (i = 0; i &lt; 1000; i++) { cout...

10
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
09.06.2019, 17:12
Цитата Сообщение от Litas99 Посмотреть сообщение
Не могли бы вы объяснить, почему вообще это работает?
Code
1
2
3
4
5
6
7
source_file.cpp: In function ‘int main()’:
source_file.cpp:10:18: error: invalid conversion from ‘void (*)(char)’ to ‘void*’ [-fpermissive]
     void* ptr = &foo;
                  ^
source_file.cpp:11:49: error: invalid static_cast from type ‘void*’ to type ‘int (*)(float)’
     std::cout << static_cast<int(*) (float)>(ptr)(5.7); 
                                                 ^
0
0 / 0 / 0
Регистрация: 09.06.2019
Сообщений: 5
09.06.2019, 17:23  [ТС]
Может, из-за разницы стандартов?
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
09.06.2019, 17:31
Цитата Сообщение от Litas99 Посмотреть сообщение
Может, из-за разницы стандартов?
Наверное все таки из-за того что указатель на функцию записывается иначе.
C++
1
2
void(*ptr)(char) = &foo; // OK
// void* ptr = &foo; // NOT OK
Добавлено через 3 минуты
Наверное в студии тестите.
Проверьте на gcc на том же стандарте
1
0 / 0 / 0
Регистрация: 09.06.2019
Сообщений: 5
09.06.2019, 17:34  [ТС]
Я не делал указатель на фнкц. Я проверял поведение приведения типов с общим указателем (void*), а вы только что описали вполне конкретный тип поля void (char). У меня мой вариант работает
0
0 / 0 / 0
Регистрация: 09.06.2019
Сообщений: 5
09.06.2019, 17:36  [ТС]
Да, через студию, сейчас попробую
0
901 / 478 / 93
Регистрация: 10.06.2014
Сообщений: 2,700
09.06.2019, 17:39
Litas99,
Ошибка возникает еще на стадии присвоения ptr адреса функции foo и это нормально.
Судя по всему это просто расширение или баг в студии.
Зачем может быть нужно описать функцию по одному типу а потом кастить ее к другому типу?
Конкретно в вашем случае судя по всему - что бы получить UB
1
Неэпический
 Аватар для Croessmah
18146 / 10730 / 2066
Регистрация: 27.09.2012
Сообщений: 27,029
Записей в блоге: 1
09.06.2019, 19:33
Цитата Сообщение от Litas99 Посмотреть сообщение
У меня мой вариант работает
Шаблонные ф-ции / массив указателей С++
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
10.06.2019, 10:18
Лучший ответ Сообщение было отмечено Litas99 как решение

Решение

Если я правильно понял смысл вопроса

Цитата Сообщение от Litas99 Посмотреть сообщение
252885984 это что-то рядом стоящее, как я понимаю
Нет, это в чистом виде мусор. Функция foo ничего не возвращает. Но в точке её вызова ожидается, что функция вернёт int. Компилятор построит код, который в точке вызова построит чтение int'а из того места, где по программным соглашениям оно должно находиться. В случае интеловской системы команд по программным соглашениям это регистр %eax. Функция foo в этот регистр не записывала никакого осмысленного значения в плане возвращаемого результата. А потому в регистре попросту хранится "нечто"

Тут обсуждение ушло в тему преобразования указателей, но ТС'а, судя по всему, интересовало совсем не это. Чтобы не мучаться с этим вопросом и выяснением тонкостей стандартов, проще переписать программу на Си в виде двух модулей. Или на Си++, но завернуть функцию foo в extern "C", чтобы не спотыкаться о манглирование имён. При таком раскладе мы попросту откинем из рассмотрения геморрой с преобразованием указателей и оставим только тот код, который подсвечивает суть изначального вопроса

C
/* Файл t1.c */
 
#include <stdio.h>
 
void foo (char r)
{
  printf ("foo: %c\n", r);
}
C
/* Файл t2.c */
 
#include <stdio.h>
 
extern int foo (float);
 
int main (void)
{
  printf ("main: %d\n", foo (5.7));
  return 0;
}
Code
$ gcc t1.c t2.c
$ ./a.exe
foo: f
main: 7
Конкретно в моём случае в роли мусора выступает "7". На Си код простой, а потому даже не заглядывая в отладчик или в ассемблерный код я с ходу понял, что сие значение есть результат, который вернула функция printf в функции foo (количество напечатанных символов). В функции foo в строку printf'а можно добавить ещё какие-то символы и наблюсти, что меняется значение, печатаемое в строке "main:". Но в общем случае это не обязательно будет так, просто так происходит в моём конкретном случае (cygwin-32 + gcc-4.8.3)
1
0 / 0 / 0
Регистрация: 09.06.2019
Сообщений: 5
13.06.2019, 01:29  [ТС]
Evg, именно это я и хотел узнать. Спасибо)
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12936 / 6803 / 1821
Регистрация: 18.10.2014
Сообщений: 17,214
13.06.2019, 02:23
Цитата Сообщение от Litas99 Посмотреть сообщение
Может, из-за разницы стандартов?
Никакой "разницы стандартов" тут нет. Ни С, ни С++ никогда не разрешал выполнять преобразования между указателями на функции и указателями на данные.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
13.06.2019, 02:23
Помогаю со студенческими работами здесь

Подскажите, почему это работает!?)
Мне необходимо изменить все строчные буквы на заглавные, это все получается. Я ввожу символы(причем заметьте массив чар из 0, но программа...

[c++] fgets не могу понять почему это не работает
Вообщем на диске C:\ лежит 3 файла 1 Файл test.txt 2 Файл 1.dll 3 Файл 2.dll в test.txt записано: 1.dll 2.dll

Почему функция не работает с чарами? Это из-за недостатка памяти?
#include&quot;stdafx.h&quot; #include&lt;stdio.h&gt; template&lt;class T&gt; T min(T a, T b, T c) { if((a&lt;b)&amp;&amp;(a&lt;c)) return(2*a); else { ...

Curiously Recurring Template Pattern; CRTP - почему это работает
Всем добрый вечер! Я задумался над тем почему и как работает CRTP в C++. #include &lt;iostream&gt; using std::cout; ...

Русификация.Работает-супер! Обьяснитте, как это работает?
#include &lt;iostream&gt; #include &lt;conio.h&gt; #include &lt;windows.h&gt; using namespace std; char* Rus(const char* text); int main () ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
SDL3 для Web (WebAssembly): Обработчик клика мыши в браузере ПК и касания экрана в браузере на мобильном устройстве
8Observer8 02.02.2026
Содержание блога Для начала пошагово создадим рабочий пример для подготовки к экспериментам в браузере ПК и в браузере мобильного устройства. Потом напишем обработчик клика мыши и обработчик. . .
Философия технологии
iceja 01.02.2026
На мой взгляд у человека в технических проектах остается роль генерального директора. Все остальное нейронки делают уже лучше человека. Они не могут нести предпринимательские риски, не могут. . .
SDL3 для Web (WebAssembly): Вывод текста со шрифтом TTF с помощью SDL3_ttf
8Observer8 01.02.2026
Содержание блога В этой пошаговой инструкции создадим с нуля веб-приложение, которое выводит текст в окне браузера. Запустим на Android на локальном сервере. Загрузим Release на бесплатный. . .
SDL3 для Web (WebAssembly): Сборка C/C++ проекта из консоли
8Observer8 30.01.2026
Содержание блога Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а. . .
SDL3 для Web (WebAssembly): Установка Emscripten SDK (emsdk) и CMake для сборки C и C++ приложений в Wasm
8Observer8 30.01.2026
Содержание блога Для того чтобы скачать Emscripten SDK (emsdk) необходимо сначало скачать и уставить Git: Install for Windows. Следуйте стандартной процедуре установки Git через установщик. . . .
SDL3 для Android: Подключение Box2D v3, физика и отрисовка коллайдеров
8Observer8 29.01.2026
Содержание блога Box2D - это библиотека для 2D физики для анимаций и игр. С её помощью можно определять были ли коллизии между конкретными объектами. Версия v3 была полностью переписана на Си, в. . .
Инструменты COM: Сохранение данный из VARIANT в файл и загрузка из файла в VARIANT
bedvit 28.01.2026
Сохранение базовых типов COM и массивов (одномерных или двухмерных) любой вложенности (деревья) в файл, с возможностью выбора алгоритмов сжатия и шифрования. Часть библиотеки BedvitCOM Использованы. . .
SDL3 для Android: Загрузка PNG с альфа-каналом с помощью SDL_LoadPNG (без SDL3_image)
8Observer8 28.01.2026
Содержание блога SDL3 имеет собственные средства для загрузки и отображения PNG-файлов с альфа-каналом и базовой работы с ними. В этой инструкции используется функция SDL_LoadPNG(), которая. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru