【问题标题】:How to make function local to main only?如何使功能仅对 main 本地化?
【发布时间】:2010-09-05 16:01:19
【问题描述】:

假设我有

文件1.c:

#include<stdio.h>
#include"File2.c"

void test(void)
{
sum(1,2);
}

int main(void)
{
int sum(int a,int b);
test();
sum(10,20);
return 0;
}

文件2.c:

int sum(int x,int y)
{
printf("\nThe Sum is %d",x+y);
}

现在就我的理解而言,调用 sum() 的 test() 应该给出一个编译时错误,因为我已经将 sum() 设为/声明为 main 本地的,但我没有得到,并且程序运行良好,无需任何错误。

我的主要目的是在 File2.c 中定义 sum 并使其成为 main() 的本地函数,这样其他函数就无法看到该函数 sum()。

我哪里出错了?

【问题讨论】:

  • main() 内部的sum() 声明前面有一个隐含的extern。使用您编写的代码,test()'看到'test() 的定义,因为它出现在test() 之前的翻译单元中。如果只有main() 可以看到sum(),那么一个文件必须包含main()static int sum(...){...}
  • 如果您从test, too 调用它,为什么要让sum 函数仅对main 可见?您是否打算拥有 2 个sum 功能(用途不同)?
  • @Cristian Ciupitu:Xaero 不想从test 打电话给sum;这只是一个示例,表明它没有给出编译错误。
  • 在 C 中(与 C++ 不同):不需要在使用前声明函数。编译器很乐意生成适当的函数调用内容,然后链接器将链接解析后者的名称。请注意,如果在 test() 中执行 sum( 1.2 , 2.4),您将得到非常奇怪的结果,因为编译器会将双精度值推入堆栈(而不是整数),但链接器仍将正确链接代码.如果您在 main() 中执行了 sum(1.2, 2.4),那么双精度数将在被推入堆栈之前转换为整数(因为 main 函数知道 sum() 需要整数)。

标签: c++ objective-c c


【解决方案1】:
  1. 将函数标记为static(这使它成为当前翻译单元的本地)。

  2. 看在上帝的份上,不要包含.c文件! (read me)

【讨论】:

  • 只标记函数static 将无济于事,除非Xaero 也更改了哪些文件包含sumtest 的定义。
【解决方案2】:

原型在编译时很有帮助,因为它们告诉编译器函数的签名是什么。不过,它们不是访问控制的手段。

您要做的是将sum() 放入与main() 相同的源文件中,并为其提供static 链接。声明它static 意味着它只能在那个.c 文件中使用,因此其他源文件中的函数将无法调用它。

然后将test() 移动到另一个源文件。这将让main() 调用test(),但不能让test() 调用sum(),因为它现在位于不同的源文件中。

文件1.c

#include <stdio.h>

/* NO! Do not #include source files. Only header files! */
/*** #include "File2.c" ***/

/* Prototypes to declare these functions. */
static int sum(int a, int b);
void test(void);

int main(void)
{
    test();
    sum(10, 20);
    return 0;
}

/* "static" means this function is visible only in File1.c. No other .c file can
 * call sum(). */
static int sum(int x, int y)
{
    printf("\nThe Sum is %d", x + y);
}

文件2.c

void test(void)
{
    /* Error: sum() is not available here. */
    sum(1, 2);
}

请注意,顺便说一句,我注释掉了 #include "File2.c" 行。你不应该将#include 用于.c 源文件,只用于.h 头文件。相反,您将分别编译这两个源文件,然后将它们链接在一起以制作最终程序。

如何做到这一点取决于您的编译器。如果您在 Windows 上使用像 Visual C++ 这样的 IDE,则将这两个源文件添加到一个项目中,它将负责将它们链接在一起。在 Linux 上,您可以使用以下内容编译它们:

$ gcc -o test File1.c File2.c
$ ./test

【讨论】:

  • 原型不应该也像这样在前面有静态吗? static int sum(int a, int b);
  • static 仅在函数实现时有意义。原型永远不会在外部可见(即对其他 .c 文件可见),它们只会告诉编译器“当你准备好将一个可执行文件链接在一起时,一个名为 sum 的函数将可用。”
  • Xaero 是正确的;无知就是无知。如果稍后将定义函数static,则在原型中省略static是无效的(编译器应该发出诊断消息)。
  • 为了迂腐,在 后续 原型中省略 static 是有效的,如果它们以其他方式匹配 确实 包含它的早期原型。然而,这对我来说似乎是可怕且毫无意义的脆弱。因此,从广义上讲,R 是正确的。请参阅此问题(虽然表面上要求 C,但已回答 C++...):stackoverflow.com/questions/5261299/…
【解决方案3】:

您已将 File2.c 包含在 File1.c 中,因此 sum 函数在 File1.c 中定义。删除该行,一切正常(您必须在 File2.c 中 #include &lt;stdio.h&gt;)。

请注意,大多数编译器都会接受在 test() 中使用的 sum() 函数的隐式定义,除非它们处于严格模式。例如,调用gcc File1.c File2.c 将成功且没有错误。如果您想查看所有可用的警告,请调用gcc -Wall -pedantic File1.c File2.c,它会警告您 sum 是在 test() 中隐式定义的,并且 sum() 的实现不会返回 int。即使这样,它也会成功编译并运行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-06
    • 1970-01-01
    • 1970-01-01
    • 2017-06-20
    • 1970-01-01
    • 2011-06-09
    • 2013-09-10
    相关资源
    最近更新 更多