C синтаксис функций, типы параметра, объявленные после списка параметров

  1. Проверка, перепроверьте и проверьте снова любой statment, который делает обновления. Даже если Вы будете думать, что просто делаете простое обновление отдельного столбца, рано или поздно Вы не будете иметь достаточного количества кофе и забудете 'где' пункт, уничтожая целую таблицу.
  2. Пара других вещей я нашел полезными:

    я 've нашел, что эти 3 вещи помешали мне причинять любой серьезный вред.

76
задан Jonathan Leffler 18 October 2009 в 17:06
поделиться

6 ответов

Это старый синтаксис для списков параметров, который все еще поддерживается. В K&R C вы также можете не указывать объявления типов, и по умолчанию они будут иметь значение int. т.е.

main(argc, argv)
char *argv[];
{
    return 0;
}

будет той же функцией.

65
ответ дан 24 November 2019 в 11:20
поделиться

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

1
ответ дан 24 November 2019 в 11:20
поделиться

Это объявление так вызывающего в стиле K&R или в старом стиле .

Обратите внимание, что это объявление существенно ] отличается от современной декларации. Объявление K&R не вводит прототип для функции, то есть не раскрывает типы параметров внешнему коду.

11
ответ дан 24 November 2019 в 11:20
поделиться

Нет никакой разницы, просто это старый синтаксис для объявления функций в C - он использовался до ANSI. Никогда не пишите такой код, если вы не планируете отдавать его своим друзьям из 80-х . Кроме того, никогда не зависят от неявных предположений типа (как, кажется, предполагает другой ответ)

4
ответ дан 24 November 2019 в 11:20
поделиться

Также интересно различие в соглашениях о вызовах функций с прототипом и функций без прототипа. Рассмотрим определение старого стиля:

void f(a)
 float a; {
 /* ... */
}

В этом случае соглашение о вызовах заключается в том, что все аргументы продвигаются перед передачей в функцию. Итак, если f получает double , но параметр имеет тип float (что совершенно верно), компилятор должен выдать код, который преобразует double в float до для выполнения тела функции.

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

void f(float a);
void f(a)
  float a; {

}

В этом случае функция ' s определение преобразует отправленный параметр из double (расширенная форма) в float , потому что определение выполнено в старом стиле. Но параметр был представлен как число с плавающей запятой, потому что у функции есть прототип. У вас есть два следующих варианта разрешения противоречий:

// option 1
void f(double a);
void f(a)
  float a; {

}

// option 2
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) {

}

Вариант 2 должен быть предпочтительным, если у вас есть выбор, потому что он заранее избавляется от определения старого стиля. Если такие противоречащие типы функций для функции появляются в той же единице перевода, компилятор обычно сообщает вам об этом (но это не обязательно). Если такие противоречия возникают в нескольких единицах перевода, ошибка может остаться незамеченной и привести к трудно предсказуемым ошибкам. Лучше избегать этих устаревших определений.

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

// option 1
void f(double a);
void f(a)
  float a; {

}

// option 2
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) {

}

Вариант 2 должен быть предпочтительным, если у вас есть выбор, потому что он заранее избавляется от определения старого стиля. Если такие противоречащие типы функций для функции появляются в той же единице перевода, компилятор обычно сообщает вам (но это не обязательно). Если такие противоречия возникают в нескольких единицах перевода, ошибка может остаться незамеченной и привести к трудно предсказуемым ошибкам. Лучше избегать этих устаревших определений.

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

// option 1
void f(double a);
void f(a)
  float a; {

}

// option 2
// this declaration can be put in a header, but is redundant in this case, 
// since the definition exposes a prototype already if both appear in a 
// translation unit prior to the call. 
void f(float a); 

void f(float a) {

}

Вариант 2 должен быть предпочтительным, если у вас есть выбор, потому что он заранее избавляется от определения старого стиля. Если такие противоречащие типы функций для функции появляются в той же единице перевода, компилятор обычно сообщает вам об этом (но это не обязательно). Если такие противоречия возникают в нескольких единицах перевода, ошибка может остаться незамеченной и может привести к трудно предсказуемым ошибкам. Лучше избегать этих устаревших определений.

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

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

28
ответ дан 24 November 2019 в 11:20
поделиться

Хотя старый синтаксис для определения функций все еще работает (с предупреждениями, если вы спросите свой компилятор), их использование не дает прототипов функций.
Без прототипов функций компилятор не будет проверять, правильно ли вызываются функции.

#include <stdio.h>
int foo(c)
int c;
{ return printf("%d\n", c); }

int bar(x)
double x;
{ return printf("%f\n", x); }

int main(void)
{
    foo(42); /* ok */
    bar(42); /* oops ... 42 here is an `int`, but `bar()` "expects" a `double` */
    return 0;
}

Когда программа запускается, на моем компьютере выводится

$ gcc proto.c
$ gcc -Wstrict-prototypes proto.c
proto.c:4: warning: function declaration isn’t a prototype
proto.c:10: warning: function declaration isn’t a prototype
$ ./a.out
42
0.000000
4
ответ дан 24 November 2019 в 11:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: