2015-05-01 3 views
0

Следующий код выдает ошибку компиляции на обоих звоном (3.6.0) и GCC (4.9.2) (coliru link)Непоследовательность поведения при передаче параметров в функции с 0 параметров

#include <stdio.h>      

void foo(void){ 
    printf("lalala\n"); 
} 

int main(void) 
{ 
    foo(1, 2, 3, 4, 5, 6, 67); 
    return 0; 
} 

Хотя VS2013 (в то время как компилируются с/TC/W4) только выдаст предупреждение

предупреждение C4087: 'Foo': объявленный с Пустотой списка параметров ... 9 1

Является ли это ошибка в VC или clang и gcc слишком суровые?

+0

В VC вы делаете компиляцию C компиляции на C++? Предупреждение выглядит как C++ как функция без параметров, как правило, 'foo()'. – chux

+0

@chux в [C++ это ошибка для VC] (http://rextester.com/RYTJH69552) –

+0

@chux Да, как я писал в вопросе, я использую флагов/TC, а также «Компилировать как код C (/ TC) "в свойствах проекта -> Свойства конфигурации -> C/C++ -> Дополнительно -> Компиляция как опция – Scis

ответ

4

От 6.5.2.2 Функции вызывает:

2 - Если выражение, которое обозначает вызываемую функцию имеет типа, который включает в себя прототип, то числа аргументов согласовывает с числом параметров. [...]

VC намеренно разрешительный, чтобы разрешить компиляцию (для совместимости с) неправильного кода. Это допускается Стандартом в качестве реализации при столкновении с определенными типами неправильного кода, например, это позволяет испускать программу, пока испущена также диагностика.

-1

Когда вы вызываете функцию с аргументами, каждый аргумент помещается в стек вызовов перед тем, как вы перепрыгиваете на вызываемую функцию. Затем, когда вы переходите к функции, удаляются только данные, указанные в аргументах, или, действительно, указатель стека перемещается настолько, насколько это необходимо, для аргументов, указанных в объявлении функции. После того, как ваша функция вернется, указатель стека не будет находиться в месте, где он находится, так как во время вызова функции он слишком сильно сдвинулся вниз. Я не уверен, как компилятор справляется с этим, но похоже, что это может вызвать проблемы, если вы возвращаетесь из нескольких функций.

2

В соответствии с C99 gcc и clang оба являются правильными, void в списке параметров означает, что он не принимает никаких параметров. Из проекта C99 стандартной секции 6.7.5.3 Функция declarators (в том числе прототипы):

Особый случай безымянного параметра типа пустоты в качестве единственного элемента в списке указывает, что функция не имеет параметров.

Но так как Visual Studio выпускает диагностику, это допустимое расширение. Что согласуется с документацией для C4087:

Объявление функции не имеет формальных параметров, но вызов функции имеет фактические параметры. Дополнительные параметры передаются в соответствии с вызывающим соглашением функции.

Это предупреждение предназначено для компилятора C.

Хотя документация не идет до визуальной Stuido 2013.

4

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

Итак, в Visual Studio нет «ошибки», только GCC и clang в этом случае являются более строгими. Возможно, разработчики VS подумали, что это недостаточно серьезно, поскольку переданные аргументы будут проигнорированы и решили только выпустить предупреждение, я могу только догадываться.

0

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

Смежные вопросы