嵌入式八股文面试题(一)C语言部分

1. 变量/函数的声明和定义的区别?

(1)变量

        定义不仅告知编译器变量的类型和名字,还会分配内存空间。

int x = 10;  // 定义并初始化x
int x;   //同样是定义

         声明只是告诉编译器变量的名字和类型,但并不为它分配内存空间。使用extern来修饰。告诉编译器这个变量的定义在其他地方,这里使用此变量。

extern int x;  // 声明x是一个整型变量

(2)函数

        函数定义提供了函数的具体实现,它包括了函数的返回类型、函数名、参数类型以及函数体的内容。

int add(int a, int b) {return a + b;  // 函数体
}

        函数声明告知编译器函数的返回类型、函数名及其参数类型,但并不提供函数的具体实现。

int add(int a, int b);  // 声明add函数

 2. sizeof和strlen的区别?

(1) sizeof 是一个操作符(与<、>类似),而 strlen 是一个库函数(在#inlcude <string>中)。

(2)sizeof 的参数可以是任何数据类型或变量,而strlen 只能是以‘ \0 ’结尾的字符串作为参数。

(3)编译器在编译时就计算出了sizeof的结果,而strlen 函数必须要在运行时才会被计算出来,其核心是因为strlen 是通过遍历字符串,在遇到 ‘\0’ 就会结束(结果大小不包含‘\0’),而sizeof 则会将其包含在内计算大小。

char str[] = "Hello";
printf("sizeof(str) = %zu\n", sizeof(str));  // 输出6(包括'\0')
printf("strlen(str) = %zu\n", strlen(str));  // 输出5(不包括'\0')

 3. &的用法:引用和取地址。

(1)& 用作取地址符号:表示获取变量的内存地址。

int x = 10;
int *ptr = &x;  // 使用 & 获取 x 的地址,并赋给指针 ptrprintf("x 的地址:%p\n", (void*)&x);  // 输出 x 的内存地址

(2)& 用作引用符号:表示一个变量的引用,即该变量的别名。创建一个引用,引用是变量的别名,它不会创建新的内存空间,而是直接使用原变量的内存。

int x = 10;
int& ref = x;  // ref 是 x 的引用,两个变量共享相同的内存地址ref = 20;  // 通过引用修改 x 的值
printf("x = %d\n", x);  // 输出 x = 20,引用修改了原变量

 4. static关键字。

        static关键字可以修饰变量和函数,对此有着不同给功能。static修饰的变量默认初始化值为0。

变量

(1)在函数内部定义的变量。

        当 static 用于函数内部的局部变量时,它表示该变量的生命周期改变。

        局部变量通常在每次函数调用时被创建并销毁,但使用 static 关键字后,局部变量在函数调用结束后不会销毁,而是保留其值,直到下一次函数调用时继续使用上一次的值。直到程序结束后销毁。

void count_calls() {static int count = 0;  // 静态变量,只初始化一次count++;printf("This function has been called %d times.\n", count);
}int main() {count_calls();  // 输出: This function has been called 1 times.count_calls();  // 输出: This function has been called 2 times.return 0;
}

(2)在函数外部定义的变量。

        当 static 用于函数外部的变量或函数时,它限制了该变量或函数的作用域,使得它只能在当前文件中使用,无法被其他文件访问。对于被static修饰全局变量来说,其他文件无法通过 extern 来引用它。

函数

         当 static 用于函数时,它限制了该函数的作用域,使得它只能在当前文件中使用,无法被其他文件访问。(即只能在当前的C文件中使用,其他文件中无法调用该函数)

        注意:在多线程程序中,使用 static 变量时要小心,因为它们的值会在多个线程之间共享,可能会引发竞态条件。为了保证线程安全,通常需要使用同步机制(如互斥锁)来访问这些静态变量。

5. volatile关键字。

        在 C 和 C++ 中,volatile 是一个非常重要的关键字,它告诉编译器不要优化该变量的读取或写入操作。例如,减少不必要的变量读取或写入,以提高程序的效率。但是,对于某些变量,如硬件寄存器或多线程共享变量,编译器优化可能导致程序行为不符合预期。因此,volatile 被用来告诉编译器:不要对该变量进行优化,每次访问该变量时,都必须从内存中读取最新的值。

        场景:对硬件寄存器进行访问时,都要加上此关键字。

#define STATUS_REGISTER (volatile int*)0x40001000int main() {int status = *STATUS_REGISTER;  // 硬件寄存器的读取,每次都要从内存重新读取// 其他代码
}

6. const关键字。 

        在 C 和 C++ 中,const 关键字用于声明常量或表示某个对象的值不能被修改。const 提供了一种有效的方式来增强程序的可读性、可维护性以及避免意外的修改。常见的有限制常量、指针、数组、函数参数等的修改性。

(1)常量

const int x = 10;  // x 是常量,值不能被修改
x = 20;  // 错误:无法修改常量变量 x

(2)指针

        常量指针:指向常量数据的指针,const 放在 * 之前,表示指向的数据是常量。

        作用:即通过这个指针你不能修改它所指向的数据,但指针本身可以指向其他内存位置。

const int *ptr = &x;  // ptr 是指向常量 int 的指针,不能通过 ptr 修改 x 的值
*ptr = 20;  // 错误:不能通过 ptr 修改值
ptr = &y;   // 合法:可以让 ptr 指向其他位置

        指针常量:指的是指针本身是常量,const 放在 * 之后,表示指针本身是常量。

        作用:即你不能改变指针指向的地址,但指针所指向的数据可以被修改。

int x = 5;
int y = 10;
int *const ptr = &x;  // ptr 是常量指针,指向 x*ptr = 20;  // 合法:可以通过 ptr 修改 x 的值
ptr = &y;   // 错误:不能改变 ptr 的值(即不能让 ptr 指向 y)

        常量指针指向常量:既不允许修改指针的值(即指针常量),也不允许修改指针所指向的数据(即指向常量的数据)。

const int *const ptr;  // ptr 是常量指针,指向常量 int

(3)数组

        使用 const 可以确保数组中的元素在程序执行过程中保持不变。

const int arr[] = {1, 2, 3, 4};  // arr 中的元素是常量,不能修改
arr[0] = 10;  // 错误:不能修改 arr 中的元素

(4)函数参数

        在函数参数中使用 const,可以确保函数不会意外修改传入的参数,特别是对于指针或引用类型的参数。这有助于增加代码的可维护性和安全性。

void print(const int &x) {printf("%d", x);  // 不能修改 x
}void foo(const int *ptr) {*ptr = 10;  // 错误:不能修改 ptr 指向的数据
}

7. inline关键字。 

        在 C/C++ 中,inline 关键字用于请求编译器将函数的代码插入到调用该函数的地方,而不是通过传统的函数调用机制(即通过栈保存返回地址、传递参数等)。它的目的是提高代码的执行效率,特别是对于那些调用频繁且函数体较小的函数。递归函数不能内联。

#include <iostream>inline int square(int x) {return x * x;
}int main() {int a = 5;int result = square(a);  // 在这里会将 square(a) 展开为 a * astd::cout << result << std::endl;  // 输出 25return 0;
}

        编译器会尽可能地将内联函数的代码嵌入到调用点。但是如果内联函数太复杂,编译器可能不会进行内联优化,尽管我们声明了 inline。编译器有最终决定权,可能会忽略 inline 关键字的请求。 

    8. C中的 malloc 和C++中的 new 有什么区别?

    在 C 和 C++ 中,mallocnew 都用于动态内存分配,但它们有一些重要的区别。

    (1)new、delete是操作符,可以重载,只能在C++中使用。而 malloc、函数 free是函数,在C++和C中都可以使用,在stdlib头文件中。

    (2)new 在 C++ 中它不仅分配内存,还会调用类的构造函数,delete调用类的析构函数(如果是类类型的话)。而 malloc 和 free 函数仅仅是分配内存和释放内存,并不执行构造和析构函数。

    (3)new、delete返回的是某种数据类型的指针,而malloc和free返回的是void类型的指针(因此需要强制类型转换)。

    (4)malloc申请的内存要使用free来释放,new申请的内存要使用delete来释放,两者不能混用,因为底层实现原理不同。

    (5)malloc申请内存失败时会返回NULL,所以判断返回值来判断内存是否申请成功。而new申请内存失败时会抛出异常。

    int* arr = (int*)malloc(10 * sizeof(int));  // 分配 10 个整数的空间
    free(arr);  // 释放内存int* arr = new int[10];  // 分配 10 个整数的数组,自动初始化
    delete[] arr;            // 释放数组,自动调用析构函数

    9. 程序中的内存分配方式。

    (1)栈区:对于所有的局部变量(除了局部静态变量),都存储在栈区中,栈内存的分配和释放由编译器自动管理,不需要程序员显式调用。

    (2)堆区:使用malloc/new创建的内存都存储在堆区,需要程序员手动创建和释放。如果分配的内存,使用完成后就必须要记得释放,不然会造成内存泄漏的风险!

    (3)静态存储区:用于存放全局变量和静态变量,内存在程序编译时就已经分配好了,这块内存在程序整个运行期间都存在。

     10. 什么是野指针,如何避免?

            野指针(Dangling Pointer)是指指向已经被释放或未初始化的内存位置的指针。野指针是指针操作中常见的错误之一,它会导致程序崩溃、内存泄漏或者不预期的行为。平时使用时一定要避免野指针的情况。如下所示:

    // 1. 使用销毁的指针
    int *ptr = new int(10);  // 在堆上分配内存
    delete ptr;               // 释放内存
    // ptr 现在是一个野指针,因为它指向已释放的内存//第二种情况:
    int* createPointer() {int x = 10;  // 局部变量 xreturn &x;  // 返回指向 x 的指针
    }
    int main() {int* p = createPointer();  // p 指向局部变量 xprintf("%d\n", *p);  // 试图访问已超出作用范围的变量return 0;
    }
    /* 原因:局部变量在函数执行完毕后销毁,指针p获取到的是销毁空间的变量,会导致崩溃*/// 2. 使用未初始化的指针
    int *ptr;  // 未初始化的指针
    *ptr = 10; // 访问未初始化的指针,导致未定义行为// 3. 超过作用域。
    

    野指针的产生原因及解决办法如下:

    (1)指针变量未初始化。解决办法:指针声明时初始化,可以是具体位置,也可以指向NULL。

    int *ptr = NULL;  // C语言中使用NULL初始化
    

    (2)使用被free或delete释放的指针。解决办法:指针指向的内存空间被释放后,应该指向NULL。

    int *p=(int *)malloc(sizeof(int));
    free(p);p=NULL;
    

    (3)指针越界。解决办法:在变量的作用域结束前释放掉变量的地址空间并且指向NULL。

     11. 什么是函数指针和指针函数?

    (1)函数指针

            是指向函数的指针。可以通过它调用函数,使得程序在运行时能够动态地决定调用哪个函数。这在实现回调函数、函数数组等情况下非常有用。

    定义一个函数指针:

    返回类型 (*指针变量名)(参数类型1, 参数类型2, ...);
    

    使用举例: 

    #include <iostream>// 定义一个普通函数
    int add(int a, int b) {return a + b;
    }int main() {// 声明一个指向函数的指针int (*func_ptr)(int, int);// 将指针指向 add 函数func_ptr = &add;// 通过函数指针调用函数int result = func_ptr(3, 4);  // 调用 add(3, 4)std::cout << "Result: " << result << std::endl;  // 输出 7return 0;
    }
    

    (2)指针函数

            指返回指针的函数。它是一个普通的函数,只是返回值类型是一个指针。

    返回类型 *函数名(参数类型1, 参数类型2, ...);
    

    12. 指针的大小。

            在 C/C++ 中,指针的大小是由编译器和系统架构决定的。指针本身的大小与它所指向的数据类型(intdoublechar 等)无关,而是与计算机的位数有关。在 32 位系统中,指针通常占 4 字节(32 位),在 64 位系统中,指针通常占 8 字节(64 位)。

    13. 内存对齐。

            内存对齐指计算机中数据在内存中的存储方式,确保数据结构的成员按照特定规则排列,以提高访问效率。 

    (1)为什么要进行内存对齐?

            CPU访问内存时,如果数据地址是对齐的(比如4字节对齐),那么访问速度会更快。如果数据没有对齐,可能需要多次访问内存,甚至导致错误。尤其是在不同的硬件平台上,对齐要求可能不同,所以编译器会自动进行内存对齐优化。

    (2)对齐规则。

           通常,每个数据类型的对齐要求是其自身的大小。比如,int通常是4字节,所以它需要4字节对齐;double是8字节,需要8字节对齐。结构体的对齐要求则是其成员中最大的对齐值。结构体的总大小需要是对齐值的整数倍,所以在成员之间可能会插入填充字节。

    (3)如何减少填充?

            对于结构体而言,调整成员顺序可以优化结构体大小。如下所示:

    //字节大小为24
    struct MyStruct {int a;      // 4 字节,对齐值 4double b;   // 8 字节,对齐值 8char c;     // 1 字节,对齐值 1
    };//字节大小为16
    struct OptimizedStruct {double b;   // 8 字节,对齐值 8int a;      // 4 字节,对齐值 4char c;     // 1 字节,对齐值 1
    };

    14. 结构体和联合体中成员所占内存大小。 

    (1)内存分配。

            结构体中的每个成员都有自己的内存空间,所有成员的内存是按顺序排列的。

            联合体中的所有成员共享同一块内存空间。

    (2)内存所占大小。

            结构体的总大小是各个成员大小的总和(可能会有填充字节以保证字节对齐,结构体的对齐方式通常由其最大成员的对齐要求决定。)。

            联合体无论定义了多少个成员,内存大小总是等于其最大成员的大小。

    举例:

    #include <iostream>
    //结构体
    struct MyStruct { int a;      // 4 bytesdouble b;   // 8 byteschar c;     // 1 byte
    };struct MyStruct2 { int a;      // 4 byteschar c;     // 1 bytedouble b;   // 8 bytes    
    };//联合体
    union MyUnion {int a;      // 4 bytesdouble b;   // 8 byteschar c;     // 1 byte
    };int main() {MyStruct  s1 = {1, 3.14, 'A'};MyStruct2 s2 = {1, 3.14, 'A'};MyUnion u={10,2.2,'C'};std::cout << "Size of struct: " << sizeof(s1) << " bytes" << std::endl;  //大小为24字节。std::cout << "Size of struct: " << sizeof(s2) << " bytes" << std::endl;  //大小为16字节。std::cout << "Size of union: " << sizeof(u) << " bytes" << std::endl;   //大小为8字节。return 0;
    }
    

    结构体大小分析:以使得结构体的总大小是 8最大成员所占字节的倍数。

    • int a 占用 4 字节。插入 4 字节填充,使 double b 从 8 字节边界开始。

    • double b 占用 8 字节。

    • char c 占用 1 字节。插入 7 字节填充,使结构体总大小为 8 的倍数。 

    • 大小:4+4+8+1+7=24。

    15. 数组和链表的区别。

    (1)数组的地址空间是连续的,而链表的地址空间不是连续的。

    (2)数组大小固定,而链表的大小不固定。

    (3)数组的访问速度更快。数组直接可以使用下标进行访问,而链表则需要遍历访问。

    (4)链表增删改查的速度更快。

    (5)数组适用于数据量固定或变化不大,且需要频繁随机访问的场景。链表适合需要频繁插入和删除,不需要随机访问的场景。

    16. define和typedef的区别。 

    (1)#define 是 C/C++ 中的预处理指令,它在编译之前由预处理器处理,进行简单的文本替换。适合定义常量、宏或代码片段,但不安全且难以调试。

    ●特点:不进行类型错误检查,只是简单的文本替换。可以定义常量、函数宏或代码片段。

    #define PI 3.14159          // 定义常量
    #define MAX(a, b) ((a) > (b) ? (a) : (b))  // 定义函数宏int main() {double radius = 5.0;double area = PI * radius * radius;  // 替换为 3.14159 * radius * radiusint max_value = MAX(10, 20);         // 替换为 ((10) > (20) ? (10) : (20))return 0;
    }

    (2)typedef 是 C/C++ 中的关键字,用于为现有类型定义别名。类型安全且易于调试,适合提高代码可读性和维护性。

    ●特点:进行类型检查,是类型安全的。只能用于定义类型别名,不能定义常量或宏。

    typedef unsigned int uint;  // 定义 uint 为 unsigned int 的别名
    typedef int* IntPtr;        // 定义 IntPtr 为 int* 的别名int main() {uint x = 10;            // 等价于 unsigned int x = 10;IntPtr p = &x;          // 等价于 int* p = &x;return 0;
    }

           如果需要类型安全或定义复杂类型别名,优先使用 typedef;如果需要定义常量或宏函数,可以使用 #define

    17. 程序分为几个段?

             通常,程序分为代码段(text)、数据段(data)、BSS段、堆(heap)和栈。具体详情查看本文内容第二章节。

    ●代码段:存储可执行指令(编译后的机器码)。

    ●数据段:通常包括已初始化的全局变量和静态变量。

    ●BSS段:存放未初始化的全局变量和静态变量,或者初始化为0的变量。 

    堆:动态分配的内存(如 malloc)。

    ●栈:局部变量。

    18. 栈和队列的区别?

    (1)核心规则

     

    (2)基本操作

     (3)结构特点

    (4)示例

    19. c文件是如何转为可执行文件的?

    具体详情查看文章:Linux环境下的编译和调试。

    本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/894567.shtml

    如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

    相关文章

    go-zero学习笔记(三)

    利用goctl生成rpc服务 编写proto文件 // 声明 proto 使用的语法版本 syntax "proto3";// proto 包名 package demoRpc;// golang 包名(可选) option go_package "./demo";// 如需为 .proto 文件添加注释&#xff0c;请使用 C/C 样式的 // 和 /* ... */…

    【25考研】南开软件考研复试复习重点!

    一、复试内容 复试采取现场复试的方式。复试分为笔试、机试和面试三部分。三部分合计100分&#xff0c;其中笔试成绩占30%、机试成绩占30%、面试成绩占40%。 1.笔试&#xff1a;专业综合基础测试 考核方式&#xff1a;闭卷考试&#xff0c;时长为90分钟。 笔试考查内容范围…

    【最长上升子序列Ⅱ——树状数组,二分+DP,纯DP】

    题目 代码&#xff08;只给出树状数组的&#xff09; #include <bits/stdc.h> using namespace std; const int N 1e510; int n, m; int a[N], b[N], f[N], tr[N]; //f[i]表示以a[i]为尾的LIS的最大长度 void init() {sort(b1, bn1);m unique(b1, bn1) - b - 1;for(in…

    012-51单片机CLD1602显示万年历+闹钟+农历+整点报时

    1. 硬件设计 硬件是我自己设计的一个通用的51单片机开发平台&#xff0c;可以根据需要自行焊接模块&#xff0c;这是用立创EDA画的一个双层PCB板&#xff0c;所以模块都是插针式&#xff0c;不是表贴的。电路原理图在文末的链接里&#xff0c;PCB图暂时不选择开源。 B站上传的…

    对象的实例化、内存布局与访问定位

    一、创建对象的方式 二、创建对象的步骤: 一、判断对象对应的类是否加载、链接、初始化: 虚拟机遇到一条new指令&#xff0c;首先去检查这个指令的参数能否在Metaspace的常量池中定位到一个类的符号引用&#xff0c;并且检查这个符号引用代表的类是否已经被加载、解析和初始化…

    传输层协议 UDP 与 TCP

    &#x1f308; 个人主页&#xff1a;Zfox_ &#x1f525; 系列专栏&#xff1a;Linux 目录 一&#xff1a;&#x1f525; 前置复盘&#x1f98b; 传输层&#x1f98b; 再谈端口号&#x1f98b; 端口号范围划分&#x1f98b; 认识知名端口号 (Well-Know Port Number) 二&#xf…

    实验十一 Servlet(二)

    实验十一 Servlet(二) 【实验目的】 1&#xff0e;了解Servlet运行原理 2&#xff0e;掌握Servlet实现方式 【实验内容】 改造实验10&#xff0c;引入数据库&#xff0c;创建用户表&#xff0c;包括用户名和密码&#xff1a;客户端通过login.jsp发出登录请求&#xff0c;请求…

    服务SDK三方新版中央仓库和私服发布详解

    预备信息Github仓库发布Gradle版本匹配Gradle项目构建全局变量定义Gradle项目Nexus仓库配置与发布过程Gradle项目发布至Sonatype中央仓库配置过程总结当我们在实现一个项目技术总结、工具类封装或SDK封装,通常是为了方便开发者使用特定服务或平台而提供的一组工具和API。您可能…

    openmv的端口被拆分为两个 导致电脑无法访问openmv文件系统解决办法 openmv USB功能改动 openmv驱动被更改如何修复

    我之前误打误撞遇到一次&#xff0c;直接把openmv的全部端口删除卸载然后重新插上就会自动重新装上一个openmv端口修复成功&#xff0c;大家可以先试试不行再用下面的方法 全部卸载再重新插拔openmv 要解决OpenMV IDE中出现的两个端口问题&#xff0c;可以尝试以下步骤&#x…

    LabVIEW双光子成像系统:自主创新,精准成像,赋能科研

    双光子成像系统&#xff1a;自主创新&#xff0c;精准成像&#xff0c;赋能科研 第一部分&#xff1a;概述 双光子成像利用两个低能量光子同时激发荧光分子&#xff0c;具有深层穿透、高分辨率、低光损伤等优势。它能实现活体深层组织的成像&#xff0c;支持实时动态观察&…

    Deepseek-R1 和 OpenAI o1 这样的推理模型普遍存在“思考不足”的问题

    每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

    Vue3学习笔记-Vue开发前准备-1

    一、安装15.0或更高版本的Node.js node -v npm -v 二、创建Vue项目 npm init vuelatest 三、Vue项目结构 node_modules: Vue项目运行的依赖文件public&#xff1a;资源文件夹package.json&#xff1a;信息描述文件

    数据结构:时间复杂度

    文章目录 为什么需要时间复杂度分析&#xff1f;一、大O表示法&#xff1a;复杂度的语言1.1 什么是大O&#xff1f;1.2 常见复杂度速查表 二、实战分析&#xff1a;解剖C语言代码2.1 循环结构的三重境界单层循环&#xff1a;线性时间双重循环&#xff1a;平方时间动态边界循环&…

    S4 HANA明确税金汇差科目(OBYY)

    本文主要介绍在S4 HANA OP中明确税金汇差科目(OBYY)相关设置。具体请参照如下内容&#xff1a; 1. 明确税金汇差科目(OBYY) 以上配置点定义了在外币挂账时&#xff0c;当凭证抬头汇率和税金行项目汇率不一致时&#xff0c;造成的差异金额进入哪个科目。此类情况只发生在FB60/F…

    87.(3)攻防世界 web simple_php

    之前做过&#xff0c;回顾 12&#xff0c;攻防世界simple_php-CSDN博客 进入靶场 <?php // 显示当前 PHP 文件的源代码&#xff0c;方便调试或查看代码结构 // __FILE__ 是 PHP 的一个魔术常量&#xff0c;代表当前文件的完整路径和文件名 show_source(__FILE__);// 包含…

    pycharm 中的 Mark Directory As 的作用是什么?

    文章目录 Mark Directory As 的作用PYTHONPATH 是什么PYTHONPATH 作用注意事项 Mark Directory As 的作用 可以查看官网&#xff1a;https://www.jetbrains.com/help/pycharm/project-structure-dialog.html#-9p9rve_3 我们这里以 Mark Directory As Sources 为例进行介绍。 这…

    【基于SprintBoot+Mybatis+Mysql】电脑商城项目之用户注册

    &#x1f9f8;安清h&#xff1a;个人主页 &#x1f3a5;个人专栏&#xff1a;【计算机网络】【Mybatis篇】 &#x1f6a6;作者简介&#xff1a;一个有趣爱睡觉的intp&#xff0c;期待和更多人分享自己所学知识的真诚大学生。 目录 &#x1f3af;项目基本介绍 &#x1f6a6;项…

    Microsoft Power BI:融合 AI 的文本分析

    Microsoft Power BI 是微软推出的一款功能强大的商业智能工具&#xff0c;旨在帮助用户从各种数据源中提取、分析和可视化数据&#xff0c;以支持业务决策和洞察。以下是关于 Power BI 的深度介绍&#xff1a; 1. 核心功能与特点 Power BI 提供了全面的数据分析和可视化功能&…

    [SAP ABAP] 在ABAP Debugger调试器中设置断点

    在命令框输入/H&#xff0c;点击回车以后&#xff0c;调试被激活&#xff0c;点击触发任意事件进入ABAP Debugger调试器界面 点击按钮&#xff0c;可以在Debugger调试器中新增临时断点 我们可以从ABAP命令、方法、功能、表单、异常、消息、源代码等多个维度在Debugger调试器中设…

    【NEXT】网络编程——上传文件(不限于jpg/png/pdf/txt/doc等),或请求参数值是file类型时,调用在线服务接口

    最近在使用华为AI平台ModelArts训练自己的图像识别模型&#xff0c;并部署了在线服务接口。供给客户端&#xff08;如&#xff1a;鸿蒙APP/元服务&#xff09;调用。 import核心能力&#xff1a; import { http } from kit.NetworkKit; import { fileIo } from kit.CoreFileK…