在C语言中,是否必须声明函数?

5

可能重复:
在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;

    }

2
重复的问题:在C中必须声明函数原型吗? [我特别推荐AndreyT的答案] - James McNellis
1
标题说的是C语言,问题也是关于C语言的,但标签却是C++,为什么? - GManNickG
1
@GMan:吸引C++开发者。 - Emile Cormier
@Emile:为什么?C不是C++。只需标记您正在使用的语言,正确的人群将看到它,而无需向其他人撒谎。 - GManNickG
@GMan:我在评论中有点讽刺。我也不喜欢被欺骗。 - Emile Cormier
4个回答

5
如果您在使用函数之前没有声明它,编译器可能会尝试猜测函数的签名,这可能会起作用。但是,如果编译器猜错了实际函数的签名,则可能会得到非常奇怪的结果:例如,如果您将一个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

奇怪,对吧?

0
如果你想在函数定义之前调用它,你必须声明一个原型。否则不行。这就是为什么许多 C 程序都是在底部写上 main 函数,而在顶部写一些小的辅助函数。只有在相互递归的情况下,编译单元内真正需要函数原型。

@David:重新考虑什么?我哪里表达不清楚了吗? - nmichaels
@David:我不了解C ++,但我的C99编译器会在函数在声明之前被使用时报错。 - nmichaels

0

传统的C编译器不需要原型,只要调用和后面的声明不冲突就可以工作。但是在C++中并非如此。

注意:我已经有一段时间没有编写纯C模块了,所以我不知道最新版本的gcc在处理.c文件时会发生什么情况。


0

C89在遇到没有定义或原型的函数调用时所需的行为是假定它返回一个int,并且具有您在调用中提供的参数数量和类型。如果您随后使用不同的参数类型进行调用,这些类型不能被合法地隐式转换,或者参数数量不同,则编译器将拒绝该代码。

当编译器或链接器最终发现不匹配的定义时,它们会发出警告。使用原型允许编译器在调用而不是定义时生成错误,或者在尝试从另一个模块链接定义时生成错误。因此,简而言之,如果您希望编译器帮助您编写可工作的代码,请不要这样做!

在C99和C ++中,如果定义不可见,则需要原型。


C99要求声明但不需要原型。定义可以满足这个要求。 - R.. GitHub STOP HELPING ICE
@R.:这就是我所说的“如果定义尚未可见”的意思。 - Clifford
我的观点是不需要原型。非原型声明是可以接受的。 - R.. GitHub STOP HELPING ICE

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接