Как называется эта функция C ++?


82

Я писал код на C ++ и по ошибке пропустил имя функции WSASocket. Однако мой компилятор не выдал ошибку и связал my SOCKETс целочисленным значением 1 вместо действительного сокета.

Рассматриваемый код должен был выглядеть так:

this->listener = WSASocket(address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Но вместо этого это выглядело так:

this->listener = (address->ai_family, address->ai_socktype, address->ai_protocol, NULL, NULL, WSA_FLAG_OVERLAPPED);

Исходя из других языков, похоже, что это какой-то анонимный тип. Как называется функция, если это действительно функция?

Какова его цель?

Его сложно искать, когда не знаешь, с чего начать.


3
+1, хороший вопрос для викторины в пабе (или ужасный вопрос на собеседовании для фирм, которые любят нанимать людей, которые хорошо разбираются в головоломках).
Вирсавия

8
Ссылка на статью в Википедии об операторе запятой . FWIW, одно из распространенных применений - получение двух побочных эффектов в forвыражении цикла * итерация , ala для (int i = 0, j = 0; i <10; ++ i, --j) ... `
Тони Делрой

1
@ MichaelJ.Gray Технически вы ошибаетесь. Это не перезаписывает поведение. Представьте:i=0;j=0;x=i++,j=6; x и j были бы 6, а я в любом случае был бы 1. Если поведение i ++ было бы перезаписано, оно осталось бы 0. Но каждый оператор вызывается, и после достижения ,только всех расширений отбрасываются, и вызывается следующая точка псевдопоследовательности. Таким образом, первый =просто назначает часть после последней, ,но каждая точка вызывается. В любом случае: я не понимаю, почему ваш компилятор не предупреждает вас о переопределении объявления функции, а вместо этого меняет ваш код на что-то
другое

5
Если вы используете правильный компилятор с включенными предупреждениями, он будет предупреждать о таком хитром коде, например, gccи g++с помощью-Wall опцией сказать:warning: left-hand operand of comma expression has no effect [-Wunused-value]
Сэм Уоткинс

3
Поэтому, на мой взгляд, лучший ответ на этот вопрос - «всегда включать предупреждения» - тогда компилятор сам объяснит, что произошла ошибка, и расскажет, что вы сделали; и этот ответ решит и для вас множество других проблем.
Сэм Уоткинс

Ответы:


151

Оператор запятая † вычисляет левую часть, отбрасывает ее значение и в результате возвращает правую часть. WSA_FLAG_OVERLAPPEDравно 1, и это результат выражения; все остальные значения отбрасываются. Никаких сокетов не создается.


† Если не перегружен. Да, может быть перегружен. Нет, не стоит его перегружать. Отойдите от клавиатуры прямо сейчас!


9
+1, дух ускорения очень эффективно перегружает оператор запятой, но это очень одинокое исключение из правила: не делайте этого .
Вирсавия

2
@Bathsheba Boost.Assign также перегружает оператор запятой, но кто использует это с C ++ 11?
rubenvb

39
Но у вас было лучшее объяснение того, насколько ужасной может быть запятая. Неумолимый и полный насмешек, он несколько минут мучил мой код, глядя на меня без стыда за свое поведение.
Майкл Дж. Грей


1
@ R.MartinhoFernandes - Eigen также очень эффективно перегружает оператор запятой. См. Этот вопрос SE для примера использования.
Дэвид Хаммен

22

Оператор запятой помогает понять ваш код.

Вы эффективно устанавливаете, this->listener = WSA_FLAG_OVERLAPPED;что просто синтаксически верно.


3
Действует не только синтаксически, но, поскольку Windows API небезопасен по типу, это также допустимое преобразование.
MSalters

5
@MSalters не то, что POSIX намного лучше в этом отношении
chbaker0

1
Вот почему конструкторы, вызываемые с одним аргументом, должны быть явными , тогда произошла бы ошибка компилятора, и разработчик мог бы еще раз взглянуть на эту причудливую конструкцию.
Matthieu M.

@MSalters Ну, SOCKETэто typedef для unsigned intи WSA_FLAG_OVERLAPPEDявляется intлитералом. Если SOCKETбы это было синонимом int, это даже не было бы обращением .
Joker_vD

1
@Joker_vD: Конечно. Если бы они сделали это typedef для struct __socket*, у нас было бы меньше ошибок. Но существует слишком много кода, который «знает» SOCKETявляется неотъемлемой частью.
MSalters

21

Компилятор по очереди оценивает каждую точку последовательности в круглых скобках, и результатом является последнее выражение WSA_FLAG_OVERLAPPEDв выражении.

Оператор запятая ,- это точка последовательности в C ++. Выражение слева от запятой полностью вычисляется раньше, чем выражение справа. Результатом всегда является значение справа. Когда у вас есть выражение в форме (x1, x2, x3, ..., xn), результат выражения всегда xn.


После того, как вы добавили туда свое разъяснение, оно приобретает больше смысла. Сначала я не совсем понимал важность вопроса о точках последовательности.
Майкл Дж. Грей
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.