Приведение к void (...функций)

Модератор: Модераторы разделов

Аватара пользователя
edoc_modnar
Бывший модератор
Сообщения: 1638
Статус: Форум больше не посещаю

Приведение к void

Сообщение edoc_modnar »

Довольно редко наблюдаю в коде вот такое:

Код: Выделить всё

(void)printf("XXX");

Между тем, встретился с мнением, что такое "заvoidование" функций корректнее, чем

Код: Выделить всё

printf("XXX");

Есть ли все-таки разница? Какой вариант предпочтительнее с точки зрения переносимости?
So long, and thanks for all the fish.
Douglas Adams, The Hitchhiker's Guide to the Galaxy
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Приведение к void

Сообщение elide »

а каков сдесь глубинный смысл?
особенно если учесть, что это "заvoidование" вовсе не функции, а ее возвращаемого значения.
слава роботам!
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Приведение к void

Сообщение t.t »

(elide @ Вторник, 17 Мая 2005, 21:55) писал(а):а каков сдесь глубинный смысл?
Наверное, такой же, как в фразах типа

Код: Выделить всё

int a; float b;
...
a=(int)b;

Я такое частенько встречал.
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
Sparky
Сообщения: 604
Статус: core dumped
ОС: Plan 9

Re: Приведение к void

Сообщение Sparky »

(t.t @ Вторник, 17 Мая 2005, 23:38) писал(а):
(elide @ Вторник, 17 Мая 2005, 21:55) писал(а):а каков сдесь глубинный смысл?
Наверное, такой же, как в фразах типа

Код: Выделить всё

int a; float b;
...
a=(int)b;

Я такое частенько встречал.


не совсем.... то что ты написал это чистое приведение типа.... от себя замечу, что в (void)printf("xxx") особого смысла не вижу.... на переносимость никак не влияет во всяком случае точно :unsure:
кстати, тот кто тебе сказал что ставить (void) првильнее пусть расскажет почему, а ты нам поведаешь ;)
Блог
--------------------

GCS/M/MU/P/IT/E d- s: a- C++(+++) UBL++ P->-- L+++$ E- W+++$ N* o? K? w>--
O M-@ V- PS@ PE+ Y+ PGP+ t 5 X R* tv-->- b++ DI? D>+ G e+(++) h--- r+ y++
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Приведение к void

Сообщение t.t »

(Sparky @ Среда, 18 Мая 2005, 2:22) писал(а):не совсем.... то что ты написал это чистое приведение типа...
Ну, это я понимаю :rolleyes: Которое на самом деле даже в стандарте прописано как автоматическое.
(Sparky @ Среда, 18 Мая 2005, 2:22) писал(а):от себя замечу, что в (void)printf("xxx") особого смысла не вижу.... на переносимость никак не влияет во всяком случае точно
Это, собственно, тоже приведение типа, int -> void, наверное по принципу "раз некому результат возвращать, его надо явно завойдить". А то, что я написал, как влияет на переносимость?
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
Аватара пользователя
flook
Сообщения: 585
Статус: Просто flook

Re: Приведение к void

Сообщение flook »

В ядре иногда встречаются такие (примерно) вещи:

Код: Выделить всё

#ifdef CONFIG_XXX
static int *x;
static inline int *func(int y)
{
      x += y;
      return x;
}
#else
#define func(x) (NULL)
#endif

И если где-то кто-то вдруг для чего-то захочет проигнорировать возврат func(), то
можно написать так:

Код: Выделить всё

func(1);

Однако если CONFIG_XXX выключен, то компилятор скажет
statement with no effect
Для этого пишут так

Код: Выделить всё

(void)func(1);

Пример тупой, но для примера имхо потянет :)
В каждом из нас спит гений... и с каждым днем все крепче...
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Приведение к void

Сообщение oav »

да все гораздо проще и смысл в этом есть, хоть и не большой :) данная конструкция просто указывает компилятору что результат работы функции, данный кусок кода совсем себе даже не интересует, а уж компилятор типа может это дело заоптимизировать. Вроде так оно и есть
Спасибо сказали:
Аватара пользователя
t.t
Бывший модератор
Сообщения: 7390
Статус: думающий о вечном
ОС: Debian, LMDE

Re: Приведение к void

Сообщение t.t »

(oav @ Среда, 18 Мая 2005, 10:10) писал(а):да все гораздо проще и смысл в этом есть, хоть и не большой  данная конструкция просто указывает компилятору что результат работы функции, данный кусок кода совсем себе даже не интересует, а уж компилятор типа может это дело заоптимизировать. Вроде так оно и есть
А что, если (void) не указать, то результат, возвёрнутый функцией будет храниться в памяти?
¡иɯʎdʞ ин ʞɐʞ 'ɐнɔɐdʞǝdu qнεиж
Спасибо сказали:
fulltick
Сообщения: 25

Re: Приведение к void

Сообщение fulltick »

Некоторые компиляторы и средства статического анализа кода (типа FlexeLint) могут выводить сообщения о "неиспользуемом возвращаемом значении" для функций. Приведение к void затыкает сильно умные инструменты. Насчет оптимизации - сильно сомневаюсь. Внутри функции компилятор ничего оптимизировать не будет, т.к. эта же функция может использоваться в другом месте. А снаружи функция возвращающая что-то от void-функции отличается только тем, что последняя возвращет в регистре eax мусор. Т.е. тоже оптимизировать нечего.
Спасибо сказали:
Аватара пользователя
ilich
Сообщения: 156

Re: Приведение к void

Сообщение ilich »

(fulltick @ Среда, 18 Мая 2005, 10:50) писал(а):Некоторые компиляторы и средства статического анализа кода (типа FlexeLint) могут выводить сообщения о "неиспользуемом возвращаемом значении" для функций. Приведение к void затыкает сильно умные инструменты. Насчет оптимизации - сильно сомневаюсь. Внутри функции компилятор ничего оптимизировать не будет, т.к. эта же функция может использоваться в другом месте. А снаружи функция возвращающая что-то от void-функции отличается только тем, что последняя возвращет в регистре eax мусор. Т.е. тоже оптимизировать нечего.

Совершенно согласен. Если честно, то в заvoidовании функции я вообще особого смысла не вижу. У меня, по крайней мере, такой потребности никогда не возникало.
!!! БЕРИ ОТ ЖИЗНИ ВСЕ !!!
Спасибо сказали:
Аватара пользователя
elide
Бывший модератор
Сообщения: 2421
Статус: Übermensch
ОС: лялих

Re: Приведение к void

Сообщение elide »

в заvoidовании функции я вообще особого смысла не вижу
ну тебе же сказали - шоб у некоторых компиляторов некоторые варнинги не сыпались....
слава роботам!
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Приведение к void

Сообщение oav »

(fulltick @ Среда, 18 Мая 2005, 11:50) писал(а):Некоторые компиляторы и средства статического анализа кода (типа FlexeLint) могут выводить сообщения о "неиспользуемом возвращаемом значении" для функций. Приведение к void затыкает сильно умные инструменты. Насчет оптимизации - сильно сомневаюсь. Внутри функции компилятор ничего оптимизировать не будет, т.к. эта же функция может использоваться в другом месте. А снаружи функция возвращающая что-то от void-функции отличается только тем, что последняя возвращет в регистре eax мусор. Т.е. тоже оптимизировать нечего.

Ну это как минимум не корректно, так как есть спецификаторы типа передачи значений (входных и выходных) в типе самой функции. Например через стек. Если функция определена на уровне 1 единицы трансляции то компилятор елементарно можно понять что по-другому эта функция не используется.
Спасибо сказали:
fulltick
Сообщения: 25

Re: Приведение к void

Сообщение fulltick »

Ну это как минимум не корректно, так как есть спецификаторы типа передачи значений (входных и выходных) в типе самой функции. Например через стек.

Согласен, eax - это частный случай. В любом случае, снаружи функции оптимизировать особо нечего, независимо от того, какой у неё тип компоновки.

Если функция определена на уровне 1 единицы трансляции то компилятор елементарно можно понять что по-другому эта функция не используется.

Для этого функция должна использоваться толькой в той единице трансляции, в которой определена. Причём компилятор может предположить это только в случае, если функция определена как static. Где и как определена printf? :)
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Приведение к void

Сообщение oav »

(fulltick @ Среда, 18 Мая 2005, 12:37) писал(а):
Ну это как минимум не корректно, так как есть спецификаторы типа передачи значений (входных и выходных) в типе самой функции. Например через стек.

Согласен, eax - это частный случай. В любом случае, снаружи функции оптимизировать особо нечего, независимо от того, какой у неё тип компоновки.

Если функция определена на уровне 1 единицы трансляции то компилятор елементарно можно понять что по-другому эта функция не используется.

Для этого функция должна использоваться толькой в той единице трансляции, в которой определена. Причём компилятор может предположить это только в случае, если функция определена как static. Где и как определена printf? :)


Вот, отрылось...


let SP be the stack pointer and let FP be the frame pointer, both
pointing into a stack. A stack frame has the following layout:

+-------------+
n+m+4: |local var_m | <-- SP
+-------------+
| ... |
+-------------+
n+4: local var_0 |
+-------------+
n+3: |old frame ptr| <-- FP
+-------------+
n+2: |return addr |
+-------------+
n+1: |return value |
+-------------+
n: |parameter_n |
+-------------+
| ... |
+-------------+
0: |parameter_0 |
+-------------+

Just before calling a function, the parameters are pushed on slots
0 ... n, an empty slot (to be set by the callee) is pushed at location
n+1 and a call (or jump subroutine) causes the return address to be
pushed at stack location n+2. The callee sets up its own stack frame
by pushing the old frame pointer (set by the caller) at location n+3,
and it makes room for its own local variables by pushing the stack
pointer upwards. After doing what it had to do, the callee stores
its return value in a slot located at the stack pointed to by FP-2,
it resets the SP register using the FP register, pops the old FP
value and finally returns (note that those operations set the SP
register to the slot where the return address is located.)

We're back at the callers level now. The return value is located
where SP points to. The caller has to reset the SP register below
the location where parameter_0 was stored (it knows how to do that,
'cause it knows the number of parameters pushed before calling the
callee function.) It is free to discard any return value before
resetting the SP register just below slot 0.

Here's the point: assume that `(void)f()' makes the compiler skip
the pushing of the empty slot where the return value has to be
stored (location n+1) and assume that function f() doesn't take
any parameters. Also assume that function f() was already compiled,
(say, it's somewhere in a standard library.) Function f() _does_
return a value and it will store its return value at location
FP-2, which accidentally happens to point _below_ location 0,
therefore destroying data local to the calling function.

The conclusion must be: a compiler can _never_ skip the allocation
step for a return value on a stack, but it can _always_ safely
discard any value, returned by the callee, no matter what type
cast you stick in front of the function call. IMHO, writing:

(void)printf("foo");

is completely useless and any self respecting compiler can very
well do without it and it saves you some keystrokes ... ;-)
Спасибо сказали:
fulltick
Сообщения: 25

Re: Приведение к void

Сообщение fulltick »

Век живи, век учись... А если всё-таки функция возвращает значение через регистры?
Спасибо сказали:
Аватара пользователя
oav
Бывший модератор
Сообщения: 296

Re: Приведение к void

Сообщение oav »

(fulltick @ Среда, 18 Мая 2005, 17:43) писал(а):Век живи, век учись... А если всё-таки функция возвращает значение через регистры?

ну тады ничего не попишешь - и так все имхо оптимизировано :)
Спасибо сказали: