2011-02-22 3 views
3

Можно создать дубликат:
Must declare function prototype in C?Вам нужно объявлять функции в C?

Я учусь C и в книге я читаю этот лакомый кода имеет заявление void scalarMultiply(int nRows, int nCols, int matrix[nRows][nCols], int scalar);. Кажется, что программа работает, даже если я не включаю эту строку?

int main(void) 
    { 

     void scalarMultiply(int nRows, int nCols, int matrix[nRows][nCols], int scalar); 
     void displayMatrix(int nRows, int nCols, int matrix[nRows][nCols]); 
    int sampleMatrix[3][5] = { 
     { 7, 16, 55, 13, 12}, 
     { 12, 10, 52, 0, 7 }, 
     { -2, 1, 2, 4, 9 } 

    }; 

    scalarMultiply(3, 5, sampleMatrix, 2); 


} void scalarMultiply(int nRows, int nCols, int matrix[nRows][nCols], int scalar){ 
     int row, column; 

     for (row = 0; row < nRows; ++row) 
      for (column = 0; column < nCols; ++column) 
       matrix[row][column] *= scalar; 

    } 
+0

Полезно знать! Благодарю. – steve

+2

Дубликат [Должен объявить прототип функции в C?] (Http://stackoverflow.com/questions/2575153/must-declare-function-prototype-in-c) [я особенно рекомендую ответить AndreyT] –

+1

Заголовок говорит C, вопрос говорит C, теги имеют C++. Зачем? – GManNickG

ответ

0

Если вы хотите вызвать функцию до ее определения, вам необходимо объявить прототип. В противном случае нет. Вот почему многие программы C записываются с main внизу и небольшими вспомогательными функциями вверху. Единственный раз, когда вы действительно, действительно нужны прототипы функций в компиляционной единице, - это взаимная рекурсия.

+0

@ Давид: Пересмотрите, что? Где-то я был неясен? – nmichaels

+0

@David: Я не знаю о C++, но мой компилятор C99 будет жаловаться, если функция используется до ее объявления. – nmichaels

1

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

В любом случае вы можете получить очень странные результаты, если функция компилятор догадывался отличается от фактической функции: например, если вы передаете long long в качестве первого параметра scalarMultiply, он не будет преобразован в int, и это приведет к неопределенному поведению: скорее всего, вы повредите свой стек (функция будет читать параметры по-другому, что вы имели в виду), и все взорвется.


Посмотрите:

#include <stdio.h> 
int main() { 
    f((long long int) -1); 
    g(1, 1); 
    return 0; 
} 
void f(int a, int b) { 
    printf("%d, %d\n", a, b); 
} 
void g(long long int a) { 
    printf("%lld\n", a); 
} 

выход будет:

-1, -1 
4294967297 

Weird, а?

0

Ваш традиционный компилятор C не требует прототипирования и вызова функции, и объявление позже будет работать до тех пор, пока вызов и последующее объявление не будут конфликтовать. Это не относится к C++.

Предостережение: я не написал модуль C только через некоторое время, поэтому не знаю, какие последние версии gcc будут делать в этом случае для файла .c.

0

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

Компилятор или компоновщик будут жаловаться, когда он в конечном итоге найдет определение с неправильным совпадением. Использование прототипа позволяет компилятору генерировать ошибку при вызове, а не в определении, при попытке связать определение с другим модулем. Короче говоря, не делайте этого, если вы хотите, чтобы компилятор помог вам написать рабочий код!

В прототипах C99 и C++ требуются, если определение еще не видно.

+0

C99 требует деклараций, но не прототипов. Это требование отвечает требованиям. –

+0

@R .: Это было то, что я имел в виду под «если определение еще не видно» – Clifford

+0

Мое мнение состояло в том, что прототип не требуется. Допустимое объявление не является прототипом. –

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