Не нужна ли точка с запятой (';') после объявления функции в C ++?

174

Я только недавно сдал промежуточный тест по программированию, и один из вопросов, который я ошибся, был следующим:

Точка с запятой (';') не требуется после объявления функции.

Правда или ложь.

Я выбрал «false» (и, пожалуйста, исправьте меня, если я ошибаюсь, потому что я чувствую, что схожу с ума), объявление функции - это то, что вы пишете перед определением (вверху кода), чтобы компилятор знал функцию даже позвонить перед вызовом, а функция определения является то , что делает функцию в целом.

То есть,

Декларация:

int func();

Определение:

int func() {
  return 1;
}

Разве ответ на этот вопрос не должен быть ложным?

логан
источник
41
Определение также является декларацией. Но я бы сказал, что ваш ответ был правильным.
216
Это сложный вопрос, придирчивый и не имеющий никакого отношения к способности кого-либо хорошо программировать.
телефонная метка
40
Я всегда нахожу вопросы, которые приводят к двойным негативам, запутывающими. На мой взгляд, такие вопросы предназначены для того, чтобы сбить студентов с толку. Почему вопрос не может быть сформирован следующим образом: «Точка с запятой (';') всегда нужна после объявления функции. Верно или неверно."? : /
Альгирдас Преиджюс
18
@phonetagger Вся эта путаница показывает, насколько серьезно сформулирован вопрос.
Франсуа Андриё
34
Бритва Хэнлона предполагает, что автор теста перепутал «декларацию» и «определение».
Sneftel

Ответы:

161

Может возникнуть ситуация, когда вы объявляете и определяете функцию за один шаг, т.е. если вы включаете определение функции в тот момент, когда вы объявляете ее. Так что технически я полагаю , правда , это правильно. Но вопрос сформулирован так, что я бы ответил на него так же, как и вы.

jwismar
источник
10
Я бы сказал, что истина не верна из-за причины, которую вы дали. Если есть случаи, когда точка с запятой необходима, тогда это ложно (или не верно). Истина для меня абсолют, если есть явные случаи, когда это необходимо, тогда нельзя сказать правду.
Я Funball
16
@IFunball Хороший аргумент. Глупые естественные языки. Предложение «Точка с запятой (';') не требуется после объявления функции» может быть прочитано как «Точка с запятой (';') (никогда) не нужна (когда-либо) после объявления функции» или как «Точка с запятой (';' ) (не всегда) необходимо после объявления функции ". Квалифицировать ли утверждение как истинное или ложное, зависит от выбора интерпретации. Строго говоря, вопрос неясен и, следовательно, не имеет четкого ответа.
Питер - Восстановить Монику
6
@IFunball Это потому, что «декларация», без дополнительного контекста и без заявления о том, что мы занимаемся языковым правоведением, обычно понимается как «неопределяющая декларация». Вопрос был несправедливым.
Гонки
2
Любой вопрос экзамена, который неясен для кого-то, кто знает, что контент проверяется, прослушивается.
Nat
2
Похоже, нам нужно добавить неопределенный пункт о поведении в английский язык
Ник Мертин
147

В дополнение к «определение также является декларацией», допустим C ++:

int f(), g();

Это объявляет две функции, fпричем gоба без аргументов и с типом возврата int, но за определением fне следует (сразу) точка с запятой. Точно так же это законно:

int f(), i = 42;

Но в этих случаях нельзя полностью опускать точку с запятой, поэтому было бы несколько удивительно, если бы они были взяты в качестве примера объявления без следующей точки с запятой. На самом деле, следующее незаконно:

void *p, f() {}

Помимо (простого) объявления функции, определение функции не может быть объединено с любым другим объявлением или определением для того же спецификатора типа . (Если бы это было законно, это определило бы и a void *pи a void f() {}.)

В любом случае, это, кажется, вопрос типа «гоча», который не должен быть в промежуточном тесте программирования.

(О, кстати, пожалуйста, на самом деле не пишите код как int f(), i = 42;.)

Арне Фогель
источник
2
Также возможно использовать typedef для определения типа функции, а затем использовать это для объявления многих функций одновременно, например, typedef int fooProc(int); fooProc a,b.c.d.e;я не уверен, почему стандартные заголовки для компиляторов на основе дисковода гибких дисков не сделали этого в день, так как я думаю, что это позволило бы значительно уменьшить размер заголовочных файлов и, следовательно, ускорить их обработку.
суперкат
Также учтите, int f(int(&g)(),int(*h)()){return g()+h();}что здесь есть три объявления функций, одно из которых сопровождается открытой фигурной скобкой, другое - запятой, а третье - закрывающей скобкой.
Дэвид
1
@DavidHammen: это не строго объявляет функции кроме int f(stuff). Даже в области видимости функции, gпредставляет собой автоматические переменный тип ссылки на функцию , и hявляется указателем на функцию .
Питер Кордес
83

В других ответах и ​​комментариях упоминается несколько причин, по которым это ужасный, вводящий в заблуждение и плохо написанный вопрос. Но есть еще одна проблема, которую еще никто не определил. Вопрос в том:

Точка с запятой (';') не требуется после объявления функции. Правда или ложь.

Хорошо, давайте посмотрим на объявление функции:

int func();       /* */
/*           ^       */
/*           |       */
/* That whitespace is "after the function declaration". */

Все это декларация . Декларация не int func()затем следуют; . Объявление int func();и затем следует пробел.

Итак, вопрос: нужна ли точка с запятой после объявления ? Конечно нет. Декларация уже содержит точку с запятой, которая завершила ее. Точка с запятой после объявления будет бессмысленной. Напротив, int func(); ;будет точка с запятой после объявления функции .

Вопрос был почти наверняка предназначен для того, чтобы задать вопрос «истина или ложь: последний токен в объявлении функции - это всегда точка с запятой». Но это не тот вопрос, который они написали, потому что автор теста не думал четко о проблеме.

Мой совет - вообще избегать тестов по языку программирования. Они довольно ужасны.


Интересный факт, пока мы на эту тему. В C # все это законно:

class C {}
class D {};
struct E {}
struct F {};

В C # объявление класса или структуры может заканчиваться точкой с запятой или нет по вашему усмотрению. Эта странная небольшая функция была добавлена ​​в пользу программистов на C / C ++, пришедших на C #, которые имеют под рукой, чтобы объявления типов заканчивались бессмысленной точкой с запятой; команда разработчиков не хотела наказать их за эту привычку. :-)

Эрик Липперт
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Самуэль Лью
25

Вы также можете объявить такую ​​функцию:

int func(){
    return 1;
}

Утверждение очень неоднозначно. Правильный ответ должен быть: это зависит от того, как вы объявляете функцию.

В любом случае, я бы тоже выбрал false, и, может быть, вы можете сообщить об этом кому-нибудь.

Лука Корсини
источник
3
Во всяком случае, не ставьте вещь на личном уровне. Важно то, что вы поняли, как работает определение объявления функции, поэтому не беспокойтесь об этом, просто убедитесь, что вопрос будет хотя бы проверен и продолжен
Luca Corsini
11
Абсолютно. Честно говоря, я узнал больше об определении-определении функции из неправильного вопроса, чем если бы я получил в нем правильный ответ.
Логан
1
@Logan не волнуйся слишком сильно. Если вы знаете, как написать и прочитать функцию, это все, что вам нужно. Лично я ненавижу такие вопросы, которые: 1. не очень хорошо определены, 2. проверить ваши теоретические знания синтаксиса. Для меня это как мышечная память. Когда я пишу, каждая цифра без особых усилий направляется к той клавише, на которую она должна идти, но если вы дадите мне тест о том, какие клавиши должны нажимать цифру, я был бы совершенно безнадежен без клавиатуры, чтобы физически выполнить действие ...
bolov
2
... Написание общего синтаксиса (например, функции) станет для вас второй натурой. И когда вы все испортите, потому что вы просто поменяли языки, ну ... интеллигентность и подсветка синтаксиса позволяют быстро и эффективно решать проблемы. Вложите свое время и энергию во что-то более полезное.
Болы
20

Точка с запятой (';') не требуется после объявления функции.

Правда или ложь.

Правда . Точка с запятой не нужна после любого объявления. Ни после какого определения. Ни после какого-либо заявления.

Многие виды объявлений должны заканчиваться точкой с запятой, как указано в синтаксисе в разделе 7 [dcl.dcl]. Но больше нет необходимости писать второй после этого.

Марк ван Леувен
источник
1
Я вижу, что Эрик Липперт уже спорил по этому вопросу. Я предполагаю, что все противники заставили меня пропустить это. Не стесняйтесь отдавать свои голоса там.
Марк ван Леувен
Практически любой вопрос, который задает: «Х всегда верен: правда или ложь?» будет иметь ответ «ложь». Черт, нет необходимости иметь точку с запятой где - нибудь ; компилятор может жаловаться и отказываться компилировать вашу программу, но вряд ли это конец света; Я бы не назвал это фундаментальной потребностью . ;)
Quuxplusone
@Quuxplusone, если компилятор отклоняет вашу программу, ваша программа не имеет каких-либо объявлений функций :)
Ben Millwood
6

Это зависит от того, объявляем мы или определяем функцию. Если мы объявляем функцию, нам нужно включить точку с запятой ( ;), а если мы определяем функцию, точка с запятой не нужна.

Объявление выглядит так:

int add(int, int);

И определение таково:

int add(int a, int b)
{
    // ...
}
Rocx En Ruff
источник
10
Проблема с этим ответом состоит в том, что он предполагает, что определения и декларации являются взаимоисключающими. Фактически каждое определение является декларацией; определения являются подмножеством объявлений.
MSalters
6

Хотя я согласен почти со всеми остальными ответами, заявив, что вопрос сформулирован очень двусмысленно, и что ваш ответ технически верен, позвольте мне дать другую точку зрения:

Вот как я их всегда называл:

void func();  // The function prototype

...

void func()
{
    // The function definition
}

Я предполагаю, что вопрос был составлен с учетом этой терминологии.

Определение и декларация - это одно и то же понятие в моих глазах. «Я определяю x = y» == «Я объявляю x = y».

Но, конечно, есть большая разница между прототипом функции (сверху) и фактическим определением функции.

Opifex
источник
Для меня ваш прототип - это декларация, основанная на том, как я учился (хотя я и не говорю, что вы не правы), но тогда я бы также ожидал, что прототип будет указывать количество и тип аргументов, или void, но я ожидаю, что вы пропустили это. для краткости.
Дэвид С
David S: Да, конечно, он также будет содержать количество и тип аргументов, но я действительно опущу их для краткости (обратите внимание, что в фактическом объявлении функции также нет аргументов). Однако я не совсем согласен, когда вы говорите, что полное объявление функции называется прототипом. Я цитирую Википедию: «прототип функции или интерфейс функции - это объявление функции, которое указывает имя функции и тип подписи (арность, типы данных параметров и тип возвращаемого значения), но опускает тело функции».
Opifex
@DavidS: В C ++ объявления функций всегда являются прототипами (или определениями) и void func();в точности эквивалентны void func(void);. Это очень отличается от C , где void func();компилятор ничего не говорит об аргументах и ​​не то же самое, что и void func(void);. Более поздний прототип или определение являются хорошей идеей, в противном случае вызывающая сторона должна применять стандартные аргументы arg (например, float -> double и узкие целочисленные типы к int. Те же правила, что и для args для функций с переменными числами.)
Peter Cordes
Мои извинения, я оказался здесь, глядя на что-то связанное с Си, и не заметил смены языка. Я не буду удалять свой комментарий в интересах ясности, но считаю, что он отозван.
Дэвид С.
6

Жаль, что вопрос, который вы взяли, не говорит «сразу после». Мы могли бы, например, написать это:

int func()  /* My function */ ;

Или я мог бы написать:

int func()
int a = 42;

В первом случае точка с запятой не сразу после объявления, но это будет нормально.

Во втором случае стоит точка с запятой «после» объявления, но не сразу после.

Я думаю, что Эрик Липперт имеет правильную идею в своем ответе .

Это все равно что сказать «должен ли быть какой-нибудь период после окончания предложения на английском?». Возможно, предложение уже имеет точку в конце (иначе это не было бы предложение), и поэтому после предложения не должно быть периода .

Ник Гаммон
источник
4
Ницца. Завершение этого предложения с дополнительным периодом. Я вижу что ты тут делал.
Дэвид С
2
int func() int a=42;не компилируется Вам нужна запятая, а не другая int. См. Ответ @ Арне, опубликованный за день до этого. Единственное новое в этом ответе - последний абзац с аналогией с английскими предложениями.
Питер Кордес
1
Я не сказал, что второй пример скомпилирован. Я указывал, что высказывание о том, что точка с запятой необходима «после» декларации, было неоднозначным. В моем примере после объявления была точка с запятой, но она не компилируется.
Ник Гэммон,
1
Эта же проблема возникает в сообщениях об ошибках; любимый пример из C # - « Параметр params должен быть последним параметром в списке формальных параметров ». Теперь предположим, что вместо этого я сказал: «Лягушка должна быть последним глобусом в списке глобусов». Означает ли это, что (1) у каждого списка глобусов есть ровно одна лягушка в конце, как у каждого вопроса в конце ровно один вопросительный знак, (2) в списке глобусов может быть любое количество лягушек, но если в нем есть одна или несколько лягушек последний элемент должен быть лягушкой, как четное число может иметь любое число 02468, но одно из последних должно быть последним, или ...
Эрик Липперт
... (3) список глобусов может иметь ноль или одну лягушку, и если она есть, она приходит в конце? Если вы не знаете контекст, я думаю, что (1) является наиболее разумным объяснением, но в случае «параметра params», (3) является правильным объяснением. Многие неофициальные описания элементов языка программирования имеют свойство, которое мои друзья из технического редактора называют «COIK» - «Очистить только, если известно». Если вы еще не полностью поняли материал, его описание бесполезно для вас, но если вы уже поняли его полностью, описание не нужно!
Эрик Липперт
4

Вы можете использовать ;только для прототипов.

M7off
источник
4

Это довольно сложный вопрос, но они использовали слово объявление, которое означает что-то вроде этого:

int example();

Так что это правда в этом случае.

Если бы они использовали слово « реализация», то оно было бы ложным.

dark_3nergy
источник
2

Точка с запятой (;) используется для указания компилятору, что после этой точки с запятой (;) начинается новый оператор.

Поэтому я думаю, что точка с запятой (;) требуется только во время объявления функции. Так что, по мне, ответ будет верным.

Jatinder
источник
Объявления не являются заявлениями все же.
HolyBlackCat
но после объявления функции мы выполняем новую строку кода, используя компилятор. поэтому я думаю, что перед выполнением новой строки компилятора кода необходимо знать, где заканчивается предыдущая строка кода, только тогда компилятор может сгенерировать собственный код (т. е. 0101).
Джатиндер
2

Когда функции определены перед main () :

  • Не нужно ставить точку с запятой, потому что функция уже определена

Когда функции определены после main () :

  • Нужна точка с запятой, потому что вы создаете прототип этой функции и сообщаете компилятору о выходе из функции.
шив шах
источник