Форум программистов, компьютерный форум, киберфорум
C для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.94/18: Рейтинг темы: голосов - 18, средняя оценка - 4.94
Alvin Seville
343 / 273 / 134
Регистрация: 25.07.2014
Сообщений: 4,537
Записей в блоге: 9
1

Если функция не принимает аргументов, то принято ли писать в её заголовке void?

18.11.2018, 10:50. Показов 3601. Ответов 27
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Если функция не принимает аргументов, то принято ли писать в её заголовке void? Например, вместо:
C
1
int F()
писать:
C
1
int F(void)
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.11.2018, 10:50
Ответы с готовыми решениями:

Ошибка: void не принимает 0 аргументов
Сделал void в нем кусок кода, пытаюсь вызвать через fight();, пишет что не принимает 0 аргументов,...

Функция не принимает 1 аргументов
Добрый день! По ООП проходим тему наследования, пишу лабораторную. Нужно чтобы был контейнер...

Функция не принимает 0 аргументов
Доброво времени суток, форумчане) У меня такой вопрос: Как исправить ошибку: < >. Текст...

Функция не принимает 0 аргументов
Помогите разобраться с ошибкой консольное приложение где выдаёт ошибку using namespace std; int...

27
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
19.11.2018, 10:10 2
Вообще-то, лучше писать, но обычно всем лень.
Без void'а Си (не С++!) считает, что количество и типы аргументов не определены, так что записи вроде такой будут вполне допустимыми ля компилятора:
C
1
2
3
4
5
void func(){}
...
func();
func(1);
func("some_str", 'd', 3.14);
Так что явное указание void защищает от вызова с параметрами. С другой стороны, тот, кто пишет функцию без параметров, их и считывать не будет, так что серьезной ошибкой это тоже не станет.
0
Модератор
Эксперт по электронике
8945 / 6711 / 921
Регистрация: 14.02.2011
Сообщений: 23,675
19.11.2018, 11:10 3
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
так что серьезной ошибкой это тоже не станет.
а вот так станет
C
1
2
3
void fnc();// на это обижается
void fnc()// вот так молчит
{
по крайней мере Keil
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 11:22 4
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
так что записи вроде такой будут вполне допустимыми ля компилятора:
Мне кажется тут UB.
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
19.11.2018, 12:32 5
Цитата Сообщение от prik Посмотреть сообщение
Мне кажется тут UB.
С чего бы?
Стек для функции готовит вызывающая сторона, она же его и чистит, то есть здесь никаких проблем нет.
Вызываемая сторона не знает, что ей передали аргументы, значит и пользоваться ими не будет. То есть ничего не попортит, так что тут тоже проблем нет.

Добавлено через 2 минуты
Цитата Сообщение от ValeryS Посмотреть сообщение
а вот так станет
Код
$ cat main.c
#include <stdio.h>

void func();

void func(){
  printf("AAA\n");
}

int main(){
  func();
  func(1);
  func(1, "test func!\n");
}

$ gcc main.c -Wall -Wextra -Wpedantic
$ ./a.out 
AAA
AAA
AAA
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 13:06 6
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
С чего бы?
Со стандарта языка. В вашем примере ф-ция без прототипа и как я помню, не совпадение числа аргументов с числом параметров в этом случае есть не определенное поведение. Если суть важно могу попозже поискать кусочек в стандарте.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Стек для функции готовит вызывающая сторона, она же его и чистит, то есть здесь никаких проблем нет.
ABI для Си вообще никак не регламентируется.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
gcc main.c -Wall -Wextra -Wpedantic
а clang как более строгий компилятор должен ругаться. Что бы gcc ловил такое нужно -Wstrict-prototype вместо всех ваших -W*

Добавлено через 13 минут
up: -Wstrict-prototypes извините.
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
19.11.2018, 15:50 7
Цитата Сообщение от prik Посмотреть сообщение
не совпадение числа аргументов с числом параметров в этом случае есть не определенное поведение. Если суть важно могу попозже поискать кусочек в стандарте.
Я всегда считал это типичным для Си хаком наравне с 2["str"] и прочими извращениями. Что-то для оптимизации, выразительности и тому подобного. Так что цитата из стандарта была бы полезна.
Цитата Сообщение от prik Посмотреть сообщение
Что бы gcc ловил такое нужно
Ругается, но неуверенно:
Код
$ gcc main.c -Wall -Wextra -Wpedantic -Wstrict-prototypes
main.c:3:1: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 void func();
main.c:5:6: warning: function declaration isn’t a prototype [-Wstrict-prototypes]
 void func(){
Добавлено через 21 минуту
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
цитата из стандарта
вот что нашел:
6.7.6.3.3 An identifier list in a function declarator that is not part of a definition of that function shall be empty.
6.7.6.3.10 The special case of an unnamed parameter of type void as the only item in the list specifies that the function has no parameters.
6.7.6.3.14 An identifier list declares only the identifiers of the parameters of the function. An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters. The empty list in a function declarator that is not part of a definition of that function specifies that no information about the number or types of the parameters is supplied.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 16:28 8
COKPOWEHEU, по моему ваш пример попадает под такое (грепаю C11):
6.7.6.3
An identifier list declares only the identifiers of the parameters of the function. An empty
list in a function declarator that is part of a definition of that function specifies that the
function has no parameters. The empty list in a function declarator that is not part of a
definition of that function specifies that no information about the number or types of the
parameters is supplied.
т.е т.к. объявление (declaration) есть часть определения (definition) ф-ции, то звать fnc(1) уже покрайней мере идеологически не верно, но еще не криминал. смотрим дальше
6.5.2.2
If the expression that denotes the called function has a type that includes a prototype, the
number of arguments shall agree with the number of parameters.
К нам вроде не относиться, т.к. у fnc() прототипа нет. А вот чуть ниже там где описывают преобразование типа аргументов кажется наш случай:
If the expression that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument
promotions. If the number of arguments does not equal the number of parameters, the
behavior is undefined.
Я считаю, что обсуждаемый пример как раз попадает под этот абзац.
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
19.11.2018, 16:49 9
Последний пример больше похож на неявный int. Хотя полностью смысл этой фразы я понять не могу.
Возможно, имелось в виду использование в функциях вроде printf, где несоответствие аргументов форматной строке действительно является UB.
Впрочем, предлагаю вернуться к исходному вопросу: если функция объявлена без параметров, то они использоваться наверняка не будут, а в таком случае единственное что мы теряем это контроль ошибок, когда передаем что-то в функцию и ожидаем реакции.
То есть само по себе такое объявление безопасно, даже вызов такой функции с несколькими параметрами безопасен. Вот если она будет пытаться анализировать параметры (интересно, как? Стек что ли читать?), могут возникнуть проблемы.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 17:18 10
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Последний пример больше похож на неявный int. Хотя полностью смысл этой фразы я понять не могу.
Да, как раз и пишут о правилах неявного преобразования типов аргументов для ф-ций без прототипа. И выдвигают требование о совпадении числа аргументов с числом параметров, что в примере не выполняется.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Возможно, имелось в виду использование в функциях вроде printf, где несоответствие аргументов форматной строке действительно является UB.
нет. у printf() как минимум есть прототип.
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Впрочем, предлагаю вернуться к исходному вопросу: если функция объявлена без параметров, то они использоваться наверняка не будут, а в таком случае единственное что мы теряем это контроль ошибок, когда передаем что-то в функцию и ожидаем реакции.
Поверьте, я прекрасно понимаю, что в реальной жизни все в данном случае будет работать так как ожидается. Но как я уже писал стандарта на ABI для Си нет т.е. вполне можно нафантазировать такое соглашение о вызовах где такой трюк вызовет сатану
0
2317 / 1141 / 705
Регистрация: 25.04.2016
Сообщений: 3,280
19.11.2018, 17:25 11
Соколиный глаз, зависит от компилятора, некоторые требуют указывать void, некоторые нет.

Добавлено через 48 секунд
я предпочитаю всегда ставить войд, тогда можно вообще не задумываться о компиляции - код будет одинаково распознан где угодно.
1
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 17:30 12
Кстати, кто-нибудь может объяснить почему gcc просто не выкинет эти явно не используемые параметры при любых уровнях оптимизации???
А вот clang выкидывает начиная с -O1
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
19.11.2018, 18:22 13
Цитата Сообщение от prik Посмотреть сообщение
нет. у printf() как минимум есть прототип.
...с переменным числом аргументов. То есть самих аргументов и их типов там как раз нет.
Цитата Сообщение от prik Посмотреть сообщение
для ф-ций без прототипа
Можно подумать, есть разница с прототипом функция или без. Вот в 5 посте прототип есть, что это меняет?
Цитата Сообщение от prik Посмотреть сообщение
вполне можно нафантазировать такое соглашение о вызовах где такой трюк вызовет сатану
Причем в printf не будет? Не могу такого представить, разве что если не делать if( список_аргементов == 0 && передано_аргументов != ){вызвать_сатану();}
Принцип-то один: для функции безразлично сколько аргументов ей передали. Это может быть ассемблерная функция, которая считывает со стека нужные (без указания компилятору ожидаемого списка!). Кстати, вполне вероятный сценарий - разрешили такие функции для более простой линковки с ассемблером. Ведь там нет средств подсказать компилятору количество и типы аргументов.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
19.11.2018, 18:47 14
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Можно подумать, есть разница с прототипом функция или без. Вот в 5 посте прототип есть, что это меняет?
Увы, это не прототип. Так же как и функции с (, ...) "ellipsis" рассматриваются отдельно и туда никак не попадают.
Дался вам этот стек, для вашего примера на куче актуальных платформ будут использованы регистры для передачи параметров.
Линковка с XXX подразумевает полное совпадение ABI, ответственность за это, лежит на XXX т.е. языку Си на это глубоко пофиг .
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
20.11.2018, 10:01 15
Цитата Сообщение от prik Посмотреть сообщение
Дался вам этот стек, для вашего примера на куче актуальных платформ будут использованы регистры для передачи параметров.
И в чем разница? Регистры точно так же чистятся вызывающей стороной. Да и их порча далеко не так опасна, как срыв стека.
Цитата Сообщение от prik Посмотреть сообщение
Линковка с XXX подразумевает полное совпадение ABI, ответственность за это, лежит на XXX т.е. языку Си на это глубоко пофиг .
Исторически Си делался максимально простым и гибким. Там нет многих обязательных для более молодых языков вещей: проверки границ массивов, проверки входных и выходных значений, порядок операций. Туда же можно отнести вызов функции без прототипа: компилятор только ругнется warning'ом, что функция не объявлена, но объектник соберет. А уж линкер подставит нужную функцию из другого модуля. Или ругнется уже error'ом что таковой нет.
Между прочим, тот же функционал используется для вызова из динамических библиотек: ни компилятор, ни линкер не знают точного списка аргументов. Они могут предполагать на основе *.h файла, но гарантировать - нет. Поэтому компилятор вынужден генерировать такой код, чтобы даже при несовпадении параметров не поломать стек.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
20.11.2018, 10:45 16
COKPOWEHEU, я уже просто не понимаю, что вы хотите объяснить/доказать.
Что нет разницы между t f(); и t f(void); ?
Или что t f(); и t f(t, ...); одно и тоже?
что-то другое?
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
20.11.2018, 12:43 17
prik, что объявление функции без аргументов и последующее использование не являются неопределенным поведением.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
20.11.2018, 13:23 18
В такой формулировке это не UB, а всего лишь одна устаревшая фича, про которые пишут: может быть удалено в последующих редакциях стандарта, не используйте в новых реализациях. т.е. держат для возможности сборки старого кода.
Но если в такую ф-цию передавать аргументы - поведение не определено. Почему так происходит я показал в 8ом сообщении.
If the expression that denotes the called function has a type that does not include a
prototype, the integer promotions are performed on each argument, and arguments that
have type float are promoted to double. These are called the default argument
promotions. If the number of arguments does not equal the number of parameters, the
behavior is undefined.
1. У нас нет прототипа - void f(); им не является по определению, т.к. нет описания типа параметров.
2. Число аргументов не совпадает с числом параметров.
С чем именно вы тут не согласны?
0
3989 / 2534 / 426
Регистрация: 09.09.2017
Сообщений: 11,218
20.11.2018, 13:49 19
Цитата Сообщение от prik Посмотреть сообщение
Но если в такую ф-цию передавать аргументы - поведение не определено. Почему так происходит я показал в 8ом сообщении.
Если передавать - определено, как я показал в 7 сообщении.
Вот если она попытается их принять - не определено.
Цитата Сообщение от prik Посмотреть сообщение
1. У нас нет прототипа - void f(); им не является по определению, т.к. нет описания типа параметров.
void f(); очевидно, является прототипом, поскольку задает имя функции для дальнейшего использования. Наличие и типы параметров тут ни при чем.
0
724 / 224 / 72
Регистрация: 01.03.2011
Сообщений: 629
20.11.2018, 14:13 20
Выделение мое.
A function prototype is a declaration of a function that declares the types of its parameters.

Добавлено через 7 минут
COKPOWEHEU, повторюсь в 3й раз.
Я _полностью_ с вами согласен, что на практике, _это_ будет работать. Так же как и uint32_t a = 1; a << 33; покажет 2 на всех платформах где я работаю, но ведь мы так не пишем...
Я говорю вам о том, что текущие стандарты языка считают это UB. Если вы не согласны с этим, ткните меня не в свой код, а в текст C99+.
0
20.11.2018, 14:13
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
20.11.2018, 14:13
Помогаю со студенческими работами здесь

Функция не принимает 0 аргументов
Class1(header) #pragma once class Class_1_Ignateva_Anna { public:...

Функция не принимает 5 аргументов
Возникает ошибка, не могу исправить...помогите #include&lt;iostream&gt; #include&lt;Windows.h&gt; using...

функция не принимает 3 аргументов,в чём ошибка?
// лаба 6.1.cpp: определяет точку входа для консольного приложения. // #include &quot;stdafx.h&quot;...

Есть функция с кучей аргументов, как её вызвать в другой функции (если половины аргументов у меня нет)?
Я конечно, понимаю, что на такие вопросы отвечают &quot;почитай книжку&quot;. Я читала, честное слово:)...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru