为什么 C 允许我调用未声明的函数? [复制]

2023-12-01

我有两个文件:test1.c, and test2.c,其中包含main()功能。

test1.c:

#include <stdio.h>  // printf() function declaration/prototype

// function definition
void say_hello() {
  printf("\tHello, world!\n");
}

test2.c:

#include <stdio.h>  // printf() function declaration/prototype
int main() {
  printf("Inside main()\n");
  say_hello();

  return 0;
}

这是我的 makefile:

a.out: test1.o test2.o
    $(CXX) -o a.out test1.o test2.o

test1.o: test1.c
    $(CXX) -c test1.c

test2.o: test2.c
    $(CXX) -c test2.c

现在应该清楚问题出在哪里了:test2.c 中的 main() 函数在没有声明的情况下调用了 say_hello() ! 我运行以下命令来使用 gcc 编译器:make CXX=gcc我在屏幕上收到此警告:

gcc -c test1.c
gcc -c test2.c
test2.c: In function ‘main’:
test2.c:16:3: warning: implicit declaration of function ‘say_hello’ [-Wimplicit-function-declaration]
   say_hello();
   ^
gcc -o a.out test1.o test2.o

尽管 *.o 文件已编译并链接到可执行文件中。这很奇怪。想象一下,当我运行 a.out 文件时,我看到了这一点,我有多惊讶main()成功调用say_hello(),一个没有在 main 的翻译单元内部声明的函数,就好像根本没有问题一样!我的理由是,自从say_hello()之前没有声明过test2.c,它不应该被允许被调用main()根本不。请注意,我已将评论添加到#include <stdio.h>。这些预处理器指令包括函数声明/原型,它们将其范围扩展到相应的 *.c 文件中。这就是为什么我们能够使用它们。没有函数声明/原型 == 在该翻译单元中没有范围,至少我到目前为止是这么认为的。

然后我将上面的代码编译为C++代码:make CXX=g++

我在屏幕上看到此错误:

test2.c: In function ‘int main()’:
test2.c:16:13: error: ‘say_hello’ was not declared in this scope
   say_hello();
             ^
makefile:18: recipe for target 'test2.o' failed
make: *** [test2.o] Error 1

g++ 执行它应该执行的操作,并停止编译过程。但gcc没有这样做!这是怎么回事?这是 C 编程语言的优势吗?是编译器的问题吗?


很简单,因为 C 允许调用未声明的函数,而 C++ 不允许。无论哪种方式,gcc警告您,您可能需要认真对待警告。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么 C 允许我调用未声明的函数? [复制] 的相关文章

  • X11 模式对话框

    如何使用 Xlib 在 X11 中创建模式对话框 模态对话框是一个位于应用程序其他窗口之上的窗口 就像瞬态窗口一样 并且拒绝将焦点给予应用程序的其他窗口 在 Windows 中 当试图从模态窗口夺取焦点时 模态也会通过闪 烁模态窗口的标题栏
  • .NET 单点登录

    我一直在尝试使用 C 为 NET Web 应用程序实现 WEB SSO 服务提供程序插件 我将使用 shibboleth 身份提供商 我已经使用 OpenSAML 库为 java 应用程序实现了相同的功能 我想知道在 NET 应用程序中使用
  • Linq - 从表达式 创建表达式

    我有一个谓词Expression
  • 为什么我会收到未找到分析器的警告?

    我创建了一个玩具项目来检查最新的 NET 7 预览版 5 和正则表达式代码生成 它效果很好 所以我对现有项目应用了相同的更改 不是为了生产 而是为了个人生产力 由于某种原因 我收到这些警告 CS8032 An instance of ana
  • .crt 部分?这个警告是什么意思?

    我最近收到此警告 VC 2010 warning LNK4210 CRT section exists there may be unhandled static initializers or terminators 我假设这是关键部分
  • 将字符串作为 PChar 从 CSharp 传递到 Delphi DLL

    我正在尝试将字符串从 C 传递到 Delphi 构建的 DLL Delphi DLL 需要 PChar 这是Delphi导出 procedure DLL Message Location PChar AIntValue integer st
  • 为什么子函数不销毁GtkWindow?

    这是我的代码 void window first void enter window2 GtkWidget w gpointer data void quit GtkWidget w gpointer data void quit int
  • 在没有 epsilon 的情况下可以将浮点数与 0.0 进行比较吗?

    我知道 要比较两个浮点值 需要使用一些 epsilon 精度 因为它们并不精确 但是 我想知道是否存在边缘情况 我不需要那个 epsilon 特别是 我想知道这样做是否总是安全的 double foo double x if x lt 0
  • Monotouch全局异常处理

    我在野外发现了一只令人讨厌的虫子 但我无法确定它的具体情况 有没有办法拥有全局 Try Catch 块 或者有办法处理 Monotouch 中未处理的任何异常 我可以包起来吗UIApplication Main args 在 try cat
  • 对作为函数参数传递的指针使用删除

    删除作为函数参数传递的指针是否可以 并且合法 如下所示 include
  • 控制台应用程序中使用 Unicode 字符的 _tprintf

    我正在从 Unicode 构建的控制台应用程序 使用 C 和 Visual Studio 2008 执行这个简单的输出 此代码旨在在 Windows 上运行 tprintf L Some sample string n 一切正常 但是如果我
  • .NET 5 EF Core SaveChangesAsync 因错误而挂起

    尽管这个问题有很多结果 但没有一个真正给我明确的答案 每次我尝试通过 AddAsync 和 SaveChangesAsync 方法插入错误数据 例如重复的主键 时 我都会看到以下日志 执行 DbCommand 失败 15 毫秒 我还在 SQ
  • C#:自定义转换为值类型

    是否可以将自定义类转换为值类型 这是一个例子 var x new Foo var y int x Does not compile 是否有可能实现上述情况 我需要超载一些东西吗Foo 您将必须重载强制转换运算符 public class F
  • 从 DataRow 单元格解析 int [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 如何从 DataRow 单元格解析 int 值 Int32 Parse item QuestionId ToString 这段代码可以工作 但看
  • 传递数组时在 C 中的函数参数中强制指定数组大小

    Context 在 C 中 我有一个以数组作为参数的函数 该参数用作该函数的输出 输出的大小始终相同 我会 让阅读代码的人清楚所需的大小 不过它已经在函数注释中了 理想情况下 编译会输出警告或错误 这样我就可以在编译时而不是运行时防止出现问
  • 如何检测应用程序正在运行的 .NET 版本?

    我尝试使用Environment Version ToString 确定目标计算机上正在使用什么 NET 框架 但安装了 4 0 版本时 它说我正在使用 NET 2 0 如何检测目标计算机上正在运行的 NET Framework 版本 En
  • 当我的进程被终止时到底会发生什么?

    我有一个包含本机代码和托管代码的混合进程 在 Windows Server 2003 上运行 当我从进程资源管理器中终止进程时 它会进入 100 cpu 的状态 并在消失之前保持这种状态一段时间 有时甚至 10 分钟 在此期间我无法 杀死
  • Boost.asio和异步链,unique_ptr?

    我对异步编程不太熟悉 我有一个问题 我的问题如下 给出 boost asio 中 C 11 的 echo server 示例 http www boost org doc libs 1 60 0 doc html boost asio ex
  • 如何在 C 中创建最低有效位设置为 1 的掩码

    这个功能如何运作 最低有效 n 位设置为 1 的掩码 Example n 6 gt 0x2F n 17 gt 0x1FFFF 我根本不明白这些 尤其是 n 6 gt 0x2F 另外 什么是面膜 通常的方法是采取1 并将其左移n位 这会给你类
  • 实体框架代码首次日期字段创建

    我正在使用实体框架代码优先方法来创建我的数据库表 下面的代码 创建一个DATETIME数据库中的列 但我想创建一个DATE柱子 DataType DataType Date DisplayFormatAttribute ApplyForma

随机推荐

  • 如何解决 Rails 插件上的 rake 任务弃用问题?

    由于引入的概念here Rails Plugin 只不过是一个 Rails Engine 但由于它已加载 在启动过程中为时已晚 它确实 不具有相同的配置权力 作为一个裸露的 Rails Engine 与 Rails Railtie 相对并且
  • NestJS/TypeORM:无法设置只有 getter 的 # 的属性元数据

    我尝试运行我的 Nestjstutorial 应用程序 显示以下错误 我的后端连接到 PostgreSQL 数据库 TypeError 无法设置只有 getter 的 属性元数据 在 EntityManager getCustomRepos
  • 使用代码默认值对集合属性进行 XML 反序列化

    对于应用程序配置 我经常会创建一个配置类 其中包含应用程序的配置值 然后将其反序列化为要使用的对象 配置对象通常与用户界面控件进行数据绑定 以便用户可以更改和保留配置 配置类通常具有分配给属性的默认值 以便始终存在默认配置 这效果很好 我最
  • Prolog - 将列表的偶数元素乘以数字 (F)

    我正在 Prolog 中编程 从任何给定的数字 F 开始 将列表中的偶数元素相乘 保留那些不是的值 开发了以下内容 实际上程序 编译 没有任何错误 但在输入值时它只返回 false 我哪里可能错了 base case evenproduct
  • 禁用 Pygame 控制台输出 [重复]

    这个问题在这里已经有答案了 可能的重复 如何在Python中抑制控制台输出 目前我正在使用 pygame 读取操纵杆输入 我需要解决以下问题 当调用操纵杆模块中的函数时 例如get axis or get button 该函数打印出诸如SD
  • ListView 项目的原始坐标

    我有以下问题 在我的布局上 我有一个操作栏 例如 高度为 150dp 其余的是 ListView 我可以从操作栏中获取一些视图并将其拖动到列表视图上 拖动是通过windowsmanager实现的 所以当拖动时我得到原始Y坐标 现在 我想将
  • 在Python中证明傅里叶变换运算

    我有一个时域表达式 f 1j H t exp 1j a b t 可以使用解析傅立叶变换已知属性 H是亥维赛阶跃函数 该 FT 运算的结果是 F w a 1j b w a 2 b 2 where w是频率 现在我正在使用中的提示本文进行数值傅
  • iPhone Codesign 目标文件格式无效或不合适

    我不小心删除了 xcode 中的目标 所以我创建了一个具有完全相同名称的新项目 在目标设置中 我再次选择了正确的代码签名身份 但现在我无法再为该设备进行编译了 一旦我想构建 我就会得到 CodeSign build Release ipho
  • 我可以使用 ADO.Net 实体框架延迟加载标量属性吗?

    我有一个数据库表Image有一根巨大的柱子 Data 我宁愿延迟加载这一列 这样当我获得所有图像的列表时 我就不会查询所有内容 我知道我可以将数据放入其自己的列和实体中 如下所示 但是 我必须这样做吗 是的 我相信你确实必须这样做 我认为
  • 适用于 Excel 2007 和 2010 的 Excel 插件

    我正在编写一个可以在 2007 和 2010 中运行的 Excel 插件 当我使用 Visual Studio 创建新项目时 我需要决定我想要哪个版本 我之前选择了2007 但由于我安装了2010 所以无法调试它 我收到错误 您无法调试或运
  • 使用 JGit 与上次提交进行文件比较

    我正在尝试使用 JGit 来获取文件从上次提交到最近未提交更改的差异 我怎样才能用 JGit 做到这一点 使用命令行的输出是git diff HEAD 经过多次讨论 link1 link2 我附带了一段代码 能够找到未提交的文件 但我无法得
  • 在c#中添加progressBar来查看进程的进度百分比

    这是关于我的流程的代码 StreamReader outputReader null StreamReader errorReader null ProcessStartInfo processStartInfo new ProcessSt
  • Bower安装EACCESS错误

    我尝试从 Bower json bower install 安装依赖项时遇到此错误 但我不知道它是什么或如何修复它 任何帮助将不胜感激 deniz946 UbuntuOS Desktop meanapp client resourcejs
  • Spring boot - 使用动态 TTL 周期驱逐缓存

    从我的微服务 SERVICE A 中 我对另一个微服务 SERVICE B 进行了其余 api 调用以进行登录并获取访问令牌 该 API 将使用该令牌的 TTL 进行响应 我需要缓存令牌 直到 SERVICE B 响应的 TTL 秒 为止
  • XML 解析难题

    更新 我重新设计了这个问题 以显示我所取得的进展 也许可以更容易回答 更新 2 我已向 XML 添加了另一个值 每个 zip 中都提供扩展 每个项目可以有多个由选项卡分隔的项目 所以它的结构将是这样的 平台 gt 分机 子组 gt 名称 g
  • 在android中实现pdf.js从sd卡读取

    我正在尝试为我的 Android 应用程序实现一个 pdf 查看器 它显示 SD 卡中存在的不同 pdf 文件 我正在考虑使用 pdf js 库 我使用了此处发布的代码示例 https bitbucket org butelo pdfvie
  • 在嵌套组件孙子组件和根组件之间发出事件

    I have wheels component嵌套到car component 轮子 组件 export class WheelsComponent Output onLoaded EventEmitter
  • 将参数作为 const 引用与普通引用传递[重复]

    这个问题在这里已经有答案了 可能的重复 为什么非常量引用不能绑定到临时对象 有这样的代码 void fun ref int par void fun const ref const int par int main fun ref 2 er
  • 在 PHP 上使用正则表达式获取 HTML 页面 值和名称

    好的 正如标题所示 我有一个使用 libcurl PHP 内的 cURL 获取的 HTML 页面 该页面有一个 我需要提取 名称和值 我想使用正则表达式来执行此操作 我使用正则表达式来制作它 因为我认为这是更简单的方法 如果您认为我不应该使
  • 为什么 C 允许我调用未声明的函数? [复制]

    这个问题在这里已经有答案了 我有两个文件 test1 c and test2 c 其中包含main 功能 test1 c include