二叉树的最大深度&C/C++ 中的预处理器指令有哪些?&解释一下宏定义和函数调用的区别。

每日一道编程题

104. 二叉树的最大深度

class Solution {
public:
    int ans = 0;
    int maxDepth(TreeNode* root) {
        dfs(root,1);
        return ans;
    }
    //使用深度优先遍历遍历二叉树 记录路径长度 不断更新全局变量最长长度
    //遍历完成后ans即为最长长度
    void dfs(TreeNode* r,int depth)
    {
        if(!r)return;//如果当前为空节点就返回
        ans = max(ans,depth);//更新最深深度
        dfs(r->left,depth+1);//向左搜索
        dfs(r->right,depth+1);//向右搜索
    }
};

C/C++ 中的预处理器指令有哪些?举例说明其用途。 

        C/C++ 中的预处理器指令是在编译之前由预处理器处理的命令。预处理器指令以 # 开头,并且通常不需要分号。它们用于控制源代码的编译过程、定义常量、包含头文件、条件编译等。

        常见的预处理器指令有:

常见预处理器指令:

#define
用于定义宏。宏是一个名字和一个值或代码块之间的映射,通常用来简化代码,或实现常量替换。

#define PI 3.14159  // 定义一个常量宏

PI 被定义为 3.14159,每次在代码中遇到 PI 时,都会被替换为 3.14159

#include
用于包含头文件。在编译时,指定的头文件会被插入到当前文件中。常用于引入标准库或自定义头文件。

#include <stdio.h>  // 引入标准库头文件
#include "myheader.h"  // 引入自定义头文件

#include <stdio.h> 用于引入标准输入输出库,而 #include "myheader.h" 用于引入当前目录中的自定义头文件。

 #if, #ifdef, #ifndef, #else, #endif
条件编译指令,用于根据不同条件选择性地编译代码块。用于在不同的平台或环境下进行不同的处理。

#define DEBUG
#ifdef DEBUG
printf("Debugging mode\n");
#endif

 如果定义了 DEBUG,则输出调试信息;否则不输出。

#undef
用于取消先前定义的宏。

#define MAX_SIZE 100
#undef MAX_SIZE  // 取消定义

 #line
用于改变预处理器输出的文件行号。这通常用于调试工具中,改变源代码的显示行号。

#line 200 "new_file.c"

 #error
用于生成编译错误,可以输出一条错误信息并停止编译。

#error "This code is not supported"

 #pragma
用于向编译器发送特殊指令,编译器可以根据指令进行优化、警告控制等。

#pragma once  // 防止头文件被多次包含

解释一下宏定义和函数调用的区别。

宏定义函数调用在 C/C++ 中有以下几个显著区别:

  1. 替换方式

    • 宏定义是在预处理阶段进行的文本替换,所有出现宏名的地方都会被直接替换为宏定义的内容,类似于直接复制粘贴。
    • 函数调用是在运行时发生的,它是调用某个函数并跳转到该函数的位置,执行其中的代码。
    // 宏定义
    #define SQUARE(x) ((x) * (x))  // 宏定义,直接替换
    int a = SQUARE(3);  // 预处理阶段变成 int a = ((3) * (3)); 
    
    // 函数调用
    int square(int x) { return x * x; }
    int a = square(3);  // 运行时调用函数
    

  2. 参数处理

    • 宏定义的参数是简单的文本替换,不进行类型检查,因此可能会出现预期之外的副作用(例如:运算顺序问题)。
    • 函数调用会对参数进行类型检查和计算,并且具有更明确的作用域。
    // 宏定义
    #define SQUARE(x) ((x) * (x))  // 宏定义,直接替换
    int a = SQUARE(3);  // 预处理阶段变成 int a = ((3) * (3)); 
    
    // 函数调用
    int square(int x) { return x * x; }
    int a = square(3);  // 运行时调用函数
    

  3. 性能

    • 宏定义没有函数调用的开销,因为它只是在预处理阶段做替换,不需要跳转、栈管理等。
    • 函数调用需要进行堆栈操作和函数跳转,会有一定的性能开销,尤其是在频繁调用时。
  4. 调试

    • 宏定义的调试相对困难,因为它只是文本替换,不会显示在调试器中的调用栈上。
    • 函数调用在调试时可以清晰地显示在调用栈中,且具有类型信息和返回值等。
  5. 作用域

    • 宏定义没有作用域限制,在整个文件中都有效,可能导致命名冲突或副作用。
    • 函数调用有作用域限制,仅在函数内部有效,不会影响外部。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值