某外企笔试总结——纯C语言

这里写自定义目录标题

  • 一、`sizeof` 计算(32位环境)
  • 二、简答题
  • 三、数据存储区域与可修改性
  • 四、字符串比较输出及原因
  • 五、数组指针运算输出
  • 六、字符串倒序代码错误排查
  • 七、下面程序可以把1维数组转为2维数组,然后调用 printArr2D 打印出数组内容,请补全调用 printArr2D部分的代码(可以增加变量)。(10分)
  • 八、使用C语言实现void memecpy(void* pdest,void* psrc,size_t nsrc)

一、sizeof 计算(32位环境)

在这里插入图片描述
1.1 sizeof(str)char str[] = "Hello";

  • 字符串 "Hello" 实际存储为 'H' 'e' 'l' 'l' 'o' '\0',共 6 字节sizeof 计算数组总字节数,结果为 6

1.2 sizeof(p)char *p = str;

  • 32位系统中,指针变量占 4 字节(存储内存地址),结果为 4

1.3 sizeof(n)long n = 10;

  • 32位系统里,long 类型占 4 字节,结果为 4

1.4 sizeof(str)void foo(char str[100])

  • 数组作为函数参数时,退化为指针,32位下指针占4字节,结果为 4(注:char str[100] 形式仅语法兼容,实际是指针)。

1.5 sizeof(p)void *p = malloc(100);

  • 指针变量 p 存地址,32位下占 4 字节,结果为 4malloc 分配堆内存,但指针本身大小由系统位数决定)。

我的错误点:
sizeof(str)char str[] = "Hello";
我的答案:4
我给的原因:字符数组的数组名难道不是指针吗?指针就是4啊?
豆包给我解答

你的理解存在一个关键误区:数组名本身不是指针,只有在特定上下文中才会“退化”为指针。让我用最直观的方式解释清楚:

①、直接结论
对于 char str[] = "Hello";

  • sizeof(str) 的结果是 6(字符串长度5 + 结尾的 '\0',共6字节)。
  • 数组名 str 不是指针,它代表整个数组的内存区域。

②、为什么容易误以为数组名是指针?
因为在大多数表达式中,数组名会被隐式转换为指向首元素的指针(这叫“退化”)。比如:

char* ptr = str;  // 这里 str 退化为指针,等价于 ptr = &str[0];

但注意,这种退化不是无条件的!有两个例外:

  1. sizeof(数组名):返回数组总大小,而非指针大小。
  2. &数组名:返回数组的地址(类型是 char(*)[N],而非 char*)。

③、用例子验证
看这段代码:

#include <stdio.h>int main() {char str[] = "Hello";char* ptr = str;  // str 退化为指针printf("sizeof(str) = %zu\n", sizeof(str));  // 输出 6printf("sizeof(ptr) = %zu\n", sizeof(ptr));  // 输出 4/8(指针大小)printf("str 的地址: %p\n", (void*)str);     // 首元素地址printf("&str 的地址: %p\n", (void*)&str);   // 数组的地址(数值上与首元素相同,但类型不同)return 0;
}

输出结果(32位系统):

sizeof(str) = 6
sizeof(ptr) = 4
str 的地址: 0x7ffd5a0b8d80
&str 的地址: 0x7ffd5a0b8d80
  • 虽然 str&str 的数值相同,但类型不同:
    • strchar[6] 类型(数组)。
    • &strchar(*)[6] 类型(指向数组的指针)。

④、对比:真正的指针
如果直接定义指针:

char* ptr = "Hello";  // 指针指向常量区的字符串

此时:

  • sizeof(ptr) 永远是 4/8字节(取决于系统是32位还是64位)。
  • 字符串 "Hello" 存储在常量区,ptr 只是存储它的地址。

⑤、一句话总结
数组名 ≠ 指针
数组名在内存中直接表示整个数组的内存区域,而指针是一个存储地址的变量。sizeof 作用于数组名时,返回的是数组实际占用的内存大小,而非指针的大小。

二、简答题

在这里插入图片描述

  1. const 的用途(至少两种)
  • 修饰变量:定义只读变量,编译期限制修改(如 const int a = 10;a 不可被赋值改变 )。
  • 修饰函数参数:保护传入参数,防止函数内意外修改(如 void func(const int x),确保 x 在函数内只读 )。
  • 修饰函数返回值:限制返回值不可被直接修改(如 const int func(),返回值赋值给普通变量不影响,但赋值给 const 变量可增强约束 )。
  1. C++ 调用 C 编译函数加 extern "C" 的原因
  • 解决命名冲突:C++ 支持函数重载,编译会给函数名加额外修饰(如 func(int) 变成 _func_int );C 编译的函数名无修饰。加 extern "C" 让 C++ 按 C 规则查找函数名,保证调用匹配。

我的回答:可以让C语言调用C++的接口不够完善!
八股文的回答:
在C++中,"extern”关键字有两个主要作用:
①声明变量的外部链接:

​ 当一个变量在一个文件中声明,但在另一个文件中定义时,我们可以使用"extern”关键字来告知编译器该变量在其他地方定义,避免编译器的编译错误。
②extern"C":

​ 在导出C++函数符号时,通过extern"C",可以保证导出的符号为C符号,而不是C++的符号(namemangling),这样可以更好的做兼容。比如Ilvm编译器导出的库,通过C符号可以做到MSVC编译器也可以正常链接使用。

  1. int (*s[10])(int) 表示的含义
  • 这是一个函数指针数组
    • s 是数组,包含 10 个元素;
    • 每个元素是函数指针,指向的函数接收 int 类型参数、返回 int 类型结果。

三、数据存储区域与可修改性

在这里插入图片描述

  1. char s[] = "abc";
  • "abc" 存于静态初始化区域/全局/静态存储区(数组 s 是局部变量,但字符串字面量编译时放静态区,运行时数组 s 会拷贝字面量内容到栈上,不过严格说字面量源头在静态区 )。
  1. char *p1 = "123456";
  • "123456\0" 存于常量区(字符串字面量默认放常量区,p1 是指针,存于栈,指向常量区内容 )。
  1. char *p2 = (char*)malloc(20);
  • p2 指向的内存由 malloc 分配,存于堆区
  1. 可修改性判断
  • s[]:数组 s 在栈上,内容可修改(如 s[0] = 'A'; 合法 )。
  • p1:指向常量区,内容不可修改(p1[0] = 'A'; 会触发未定义行为,常量区只读 )。
  • p2:指向堆区,内容可修改(如 p2[0] = 'A'; 合法,堆内存可读写 )。

我的错误:
char s[] = "abc"; 我的答案:"abc" 存于 “常量区”
豆包回答我的问题:
这里需要区分字符串字面量本身的存储数组 s 的存储,可以从编译、运行阶段拆分理解:

①字符串字面量 "abc" 的本质

  1. 编译时
    字符串字面量 "abc" 是程序的“静态数据”,编译器会把它放到只读数据段(静态区的一种)。不管你用不用 char s[] = "abc";,只要代码里写了 "abc",它就会被存到静态区,目的是让多个相同字面量共享内存(比如 char* p = "abc"; 也会指向这里)。

  2. 运行时
    当执行 char s[] = "abc"; 时,程序会把静态区里的 "abc"(包括末尾 '\0')拷贝一份,放到栈上给数组 s 使用。

    所以,字面量本身的“源头”在静态区,但数组 s 是栈上的拷贝,二者是“内容相同、存储区不同”的关系。

② 为什么说数组 s 不在静态区?

  • 静态区的特点:数据编译时分配,程序结束才释放,且全局可见(比如全局数组、static 变量)。

  • 数组 s 的特点

    • 它是局部变量(假设在函数内定义),运行时在栈上分配内存,函数结束就释放。
    • 它的内容是静态区字面量的“拷贝”,不是字面量本身。

    因此,数组 s 存储在栈上,而它的“数据源”(字面量 "abc")在静态区。

③、对比 char* p = "abc"; 加深理解

  • char* p = "abc";
    p 是指针(存在栈/全局区,看定义位置),它直接指向静态区的 "abc"(没有拷贝)。此时,静态区的 "abc" 是只读的(修改 p[0] 会触发未定义行为)。

  • char s[] = "abc";
    s 是数组(存在栈上),它拷贝静态区的 "abc" 到栈,内容可修改(s[0] = 'A'; 合法)。

④、一句话总结
"abc" 作为字符串字面量,源头在静态区;但 char s[] = "abc"; 是把字面量“复制”到栈上的数组,所以数组 s 存储在栈,而非静态区。核心区别是“直接引用静态区”还是“拷贝到栈” 。
你的理解基本正确,但需要更精确地区分字符串字面量的存储区域变量(指针/数组)的存储区域,以及术语的统一性(“常量区”和“静态区”在很多场景下是重叠的概念)。下面详细拆解:

⑤、关于 char* p1 = "123456";

  1. 字符串字面量 "123456" 的存储
    字符串字面量 "123456" 本质是常量字符串,编译时会被放入只读数据段(属于静态区/常量区)
    • 它的完整内容是 "123456\0"(编译器自动添加结束符 '\0'),存储在静态区的只读区域,不可修改(强行修改会触发未定义行为,比如程序崩溃)。

⑥、关于 char s[] = "abc";

  1. 字符串字面量 "abc" 的存储
    "123456" 一样,字符串字面量 "abc" 本身在编译时也存于静态区(常量区),完整内容是 "abc\0"

⑦、关键术语统一:静态区 vs 常量区

  • 静态区:是程序内存布局的一个大分类,包含全局变量、静态变量、常量字符串字面量等,特点是编译时分配内存,程序结束后释放。
  • 常量区(只读数据段):是静态区的一部分,专门存储不可修改的常量(如字符串字面量、const 修饰的全局变量等)。

因此,“字符串字面量存在静态区”和“存在常量区”并不矛盾——常量区属于静态区的子集,字符串字面量是静态区中只读的那部分

⑧、总结表格

代码字符串字面量存储位置变量(指针/数组)存储位置能否修改内容?
char* p1 = "123";静态区(常量区,"123\0"p1 本身在栈/静态区(看定义)不能(字面量只读)
char s[] = "abc";静态区(常量区,"abc\0"s 本身在栈/静态区(看定义)能(拷贝的内容可改)

简单说:所有字符串字面量的“源头”都在静态区的常量区,但数组会拷贝字面量内容到自己的存储区(栈或静态区),而指针直接指向字面量本身。

以下是题目详细解答,按题目模块拆分说明:

在这里插入图片描述

四、字符串比较输出及原因

代码:

char str1[] = "abc";
char str2[] = "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char *str5 = "abc";
const char *str6 = "abc";
char *str7 = "abc";
char *str8 = "abc";cout << (str1 == str2) << endl; 
cout << (str3 == str4) << endl; 
cout << (str5 == str6) << endl; 
cout << (str7 == str8) << endl; 

输出结果

0  
0  
1  
1  

原因

  • str1str2str3str4数组,每个数组独立分配内存(栈上),即使内容相同,地址不同,== 比较地址,结果为 0(假)。
  • str5str6str7str8指针,指向字符串字面量(存常量区,相同字面量共享地址 ),所以 str5str6str7str8 地址相同,== 结果为 1(真)。

我的答案: 0 0 0 0
我的原因: 不都是在栈区申请了的临时变量指针吗?
仔细思考: 指针说白了就是用来存储地址的,说白了str5 str6 和str7 str8都指向的是同一块地址,自然而然值相同,对于str1 str2 str3 str4 来说 char str1[] = “abc”; 存在栈区的str1 会把静态常量区的“abc”拷贝到栈区?

豆包给我的回答:
详细分析:

  1. str1str2 是数组(栈上独立内存)
  • char str1[] = "abc";char str2[] = "abc"; 分别在栈上创建两个独立的数组。
  • 虽然它们的内容都是 "abc\0",但数组名代表数组首地址,而两个数组在内存中的位置不同,因此 str1str2 的地址不同。
  • str1 == str2 比较的是地址,结果为 0(假)
  1. str3str4 同理(const 不影响存储位置)
  • const 仅限制对数组内容的修改,但数组本身仍在栈上分配独立内存。
  • 因此 str3str4 的地址不同,str3 == str4 结果为 0
  1. str5str6 是指针(指向静态区的同一字符串)
  • const char *str5 = "abc";str6 都指向静态区的字符串字面量 "abc\0"
  • 编译器通常会将相同的字符串字面量合并为一处存储,因此 str5str6 指向同一块内存地址。
  • str5 == str6 比较的是指针值(地址),结果为 1(真)
  1. str7str8 同理(即使没有 const,仍指向静态区)
  • 虽然 char *str7 = "abc"; 没有显式声明 const,但字符串字面量 "abc\0" 仍存于静态区且不可修改。
  • str7str8 同样指向静态区的同一字符串,因此 str7 == str8 结果为 1

关键区别:

  • 数组名(如 str1str2)代表数组首地址,每个数组在内存中独立分配,地址不同。
  • 指针(如 str5str6)存储的是字符串字面量的地址,相同的字面量通常共享同一内存位置。

因此,数组比较结果为 0,指针比较结果为 1

五、数组指针运算输出

在这里插入图片描述

代码:

main()
{int a[5]={1,2,3,4,5};int *ptr=(int *)(&a+1);printf("%d,%d",*(a+1),*(ptr-1));
}

输出结果2,5

解析

  • *(a + 1)a 是数组首地址,a + 1 指向 a[1],值为 2
  • &a 是数组指针(类型 int (*)[5]),&a + 1 跳过整个数组(偏移 5 * sizeof(int) 字节 ),ptr 指向数组末尾后第一个位置;ptr - 1 回退到 a[4],值为 5

六、字符串倒序代码错误排查

在这里插入图片描述

原代码(功能:字符串倒序):

#include"string.h"
main()
{char* src = "hello,world";char* dest = NULL;int len = strlen(src);dest = (char*)malloc(len); char* d = dest;char* s = src[len]; while(len-- !=0)  d++ = s--; printf("%s", dest); return 0;
}

错误及修正

  1. malloc 空间不足

    • 原代码 malloc(len) 未给字符串结束符 '\0' 留空间,需改为 malloc(len + 1)
  2. src[len] 语法错误

    • src 是指针,src[len] 是字符(越界,src 有效下标 0~len-1 ),应改为 src + len - 1(指向最后一个有效字符 )。
  3. 未处理字符串结束符

    • 倒序后需手动在 dest 末尾加 '\0',否则输出乱码。
  4. main 函数标准写法

    • 建议显式写 int main(),增强可读性。

修正后代码

#include <string.h>
#include <stdio.h>
#include <stdlib.h>int main() {char* src = "hello,world";char* dest = NULL;int len = strlen(src);// 1. 分配足够空间(含 '\0')dest = (char*)malloc(len + 1); char* d = dest;// 2. 指向最后一个有效字符char* s = src + len - 1; while (len-- != 0) {*d++ = *s--; }// 3. 手动加结束符*d = '\0'; printf("%s", dest); free(dest); // 释放堆内存(可选,若关注内存泄漏)return 0;
}

最终答案整理
4. 输出依次:0011(数组地址不同,常量区字符串指针地址相同 )。
5. 输出:2,5(指针运算定位数组元素 )。
6. 错误:malloc 空间不足、src[len] 语法错、缺结束符、main 不标准;修正后可正确倒序输出 dlrow,olleh

七、下面程序可以把1维数组转为2维数组,然后调用 printArr2D 打印出数组内容,请补全调用 printArr2D部分的代码(可以增加变量)。(10分)

在这里插入图片描述

要调用 printArr2D,需要构造一个符合 int** 类型的参数。由于 arr2D 是二维数组,在 C 语言中,二维数组名可以转换为指向指针的指针,但更直接的方式是构造一个指针数组,每个元素指向二维数组的一行。

以下是补全的代码:

#include <stdio.h>
#define ROW 2
#define COL 3void printArr2D(int** arr2D, int row, int col) {int i, j;for (i = 0; i < row; i++) {for (j = 0; j < col; j++) {printf("%d ", arr2D[i][j]);}printf("\n");}
}int main(int argc, char *argv[]) {int arr1D[] = {1, 2, 3, 4, 5, 6};int arr2D[ROW][COL];int i, j;for (i = 0; i < ROW; i++) {for (j = 0; j < COL; j++) {arr2D[i][j] = arr1D[i * COL + j];}}// 构造一个指针数组,每个元素指向 arr2D 的一行int* rowPtrs[ROW];for (i = 0; i < ROW; i++) {rowPtrs[i] = arr2D[i];}// 调用 printArr2D,传递指针数组printArr2D(rowPtrs, ROW, COL);return 0;
}

关键步骤说明:

  1. 构造指针数组 rowPtrs
    由于 printArr2D 的参数是 int**(指向指针的指针),而二维数组 arr2D 的行地址可以通过指针数组存储。
    rowPtrs[i] = arr2D[i]; 让每个指针元素指向 arr2D 的一行。

  2. 调用 printArr2D
    直接传递 rowPtrs(类型为 int**),匹配函数参数要求。

这样就能正确打印二维数组的内容,输出:

1 2 3 
4 5 6 

八、使用C语言实现void memecpy(void* pdest,void* psrc,size_t nsrc)

在这里插入图片描述

实现思路
memcpy 函数用于将一段内存区域的数据复制到另一个区域,需要处理以下关键点:

  1. 内存重叠问题:标准 memcpy 不保证处理重叠内存(需用 memmove),但题目要求实现 memcpy,因此忽略重叠。
  2. 字节级复制:使用 char* 指针逐字节复制,确保处理任意数据类型。
  3. 参数合法性检查:检查输入指针是否为 NULL,提高函数健壮性。

代码实现

#include <stddef.h>  // 包含 size_t 定义void* memcpy(void* pdest, const void* psrc, size_t nsrc) {// 1. 检查参数合法性(标准库通常不检查,此处为增强健壮性)if (pdest == NULL || psrc == NULL) {return NULL;}// 2. 转换为 char* 以逐字节操作char* dest = (char*)pdest;const char* src = (const char*)psrc;// 3. 逐字节复制 nsrc 字节for (size_t i = 0; i < nsrc; i++) {dest[i] = src[i];}// 4. 返回目标指针return pdest;
}

关键说明

  1. 指针类型转换

    • void* 转换为 char* 以逐字节复制,确保正确处理任意数据类型。
    • src 被声明为 const char*,防止修改源数据。
  2. 内存重叠处理

    • 若源区域与目标区域重叠,结果未定义(如 srcdest 前且部分重叠,可能覆盖未复制的数据)。
    • 若需处理重叠,应使用 memmove(通过逆向复制避免覆盖)。
  3. 返回值

    • 返回 pdest 以便链式调用(如 strcpy(dest, memcpy(dest, src, n)))。
  4. 性能优化

    • 实际标准库实现可能使用更高效的方式(如按字长复制或 SIMD 指令),但此处采用简洁的逐字节复制以保证通用性。

此实现符合标准 memcpy 的行为,适用于非重叠内存的复制场景。

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

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

相关文章

Qt Graphs 模块拟取代 charts 和 data visualization还有很长的路要走

近期关注 Qt 6.10 的分支进展&#xff0c; 发现了 Qt 6.10 的 charts 和 data visualization &#xff08;以下简称 DV&#xff09;已经被deprecated, 功能将会合并到 graphs 模块。如果后面 charts\ DV 被弃用&#xff0c;那算是很大的API变化了。从Qt 6.5 以后开始引入的 gra…

2025牛客暑期多校训练营2(部分补题)

题目链接&#xff1a;牛客竞赛_ACM/NOI/CSP/CCPC/ICPC算法编程高难度练习赛_牛客竞赛OJ B Bitwise Perfect 思路 考虑到由&#xff0c;那么只有变小的时候对答案的贡献才能够减少&#xff0c;从二进制的角度考虑什么时候变小&#xff0c;只有min(x,y)中的最高位1异或之后变…

Nginx的location匹配规则

Nginx的location匹配规则 为什么你的Nginx配置总是不生效&#xff1f; 改了Nginx配置无数次&#xff0c;reload命令执行了几十遍&#xff0c;浏览器访问时却依然返回404&#xff1f;运维工程师小张上周就遇到了这个问题&#xff1a;明明配置了location /static/ { root /var/ww…

USB 2.0 vs USB 3.0:全面技术对比与选择指南

USB 2.0 vs USB 3.0&#xff1a;全面技术对比与选择指南 引言 在当今数字时代&#xff0c;USB接口已成为连接设备与计算机的最普遍标准之一。从2000年USB 2.0的发布到2008年USB 3.0的问世&#xff0c;USB技术经历了显著的演进。本文将深入比较这两种广泛使用的USB标准&#xff…

DApp架构设计与开发流程指南

目录 DApp架构设计与开发流程指南 引言:DApp的核心特性 一、DApp架构设计 1.1 分层架构设计 各层核心组件: 1.2 典型架构模式 1.2.1 全去中心化架构 1.2.2 混合架构(推荐) 二、开发流程 2.1 敏捷开发流程 2.2 详细开发阶段 阶段1:需求分析与设计(1-2周) 阶段2:智能合约…

Windows下odbc配置连接SQL Server

一、查看SQL Server服务是否启动打开SQL Server 2022配置管理器查看SQL Server运行状态&#xff0c;可以设置 启动或停止服务二、windows下如何配置ODBC数据源1、Windows搜索栏中输入“ODBC数据源管理器”并选择“以管理员身份运行”来打开它2、添加新的数据源ODBC数据源管理器…

MySQL—表设计和聚合函数以及正则表达式

文章目录一、第一范式&#xff08;原子性&#xff09;二、第二范式&#xff08;消除部分依赖&#xff09;三、第三范式&#xff08;消除传递依赖&#xff09;四、表设计五、聚合函数六、正则表达式MySQL 的三大范式&#xff08;1NF、2NF、3NF&#xff09;是关系型数据库设计的核…

基于Electron打包jar成Windows应用程序

基于Electron打包jar成Windows应用程序简介注意编译及命令&#xff1a;运行效果登录界面用户管理界面界面全屏锁屏界面文档查看界面简介 本文介绍了一种将maven jar包打包成Windows下EXE可执行程序的方法。 Maven打包Java Web应用成jar&#xff0c;Electron封装jar成Windows …

Autosar RTE实现观测量生成-基于ETAS软件

文章目录前言观测量定义arTypedPerInstanceMemoryPorts Measurable工具链配置及使用Port中的配置arTypedPerInstanceMemory观测量生成文件分析总结前言 之前我们在XCP中&#xff0c;对于标定量和观测量并没有严格按照Autosar标准中定义&#xff0c;Autosar RTE中对标定量和观测…

【REACT18.x】creat-react-app在添加eslint时报错Environment key “jest/globals“ is unknown

今天在创建新项目的时候&#xff0c;给cra创建的项目添加eslint支持&#xff0c;出现如下报错 添加eslint npx eslint --init页面报错 Compiled with problems:ERROR [eslint] package.json eslint-config-react-app/jest#overrides[0]:Environment key "jest/globals&…

Linux的例行性工作 -- (练习)

1、atd和crond两个任务管理程序的区别 答&#xff1a; atd 专为一次性任务设计&#xff0c;允许用户在特定未来时间点&#xff08;绝对或相对时间&#xff09;执行单次命令后就结束。 crond 则是周期性任务的调度核心&#xff0c;通过配置文件&#xff08;crontab&#xff09;实…

《Java语言程序设计》1.6 复习题

1.6.1 什么是Java语言规范?计算机有严格的使用规则。如果编写程序时没有遵循这些规则&#xff0c;计算机就不能理解程序。Java语言规范和Java API定义了Java的标准。Java语言规范(Java language specification)是对Java程序设计语言的语法和语义的技术定义。应用程序接口(Appl…

【机器学习深度学习】什么是量化?

目录 前言 一、量化的基本概念 1.1 量化对比示例 1.2 量化是如何实现的&#xff1f; 二、为什么要进行量化&#xff1f; 2.1 解决模型体积过大问题 2.2 降低对算力的依赖 2.3 加速模型训练和推理 2.4 优化训练过程 2.5 降低部署成本 小结&#xff1a;量化的应用场…

告别 T+1!解密金融级实时数据平台的构建与实践

在数字金融浪潮下&#xff0c;数据处理的“实时性”已不再是加分项&#xff0c;而是逐渐成为决定业务价值的核心竞争力。然而&#xff0c;金融机构在追求实时的道路上&#xff0c;往往陷入一个新的困境&#xff1a;实时分析系统与离线大数据平台形成了两套独立的“烟囱”&#…

[Python] -项目实战7- 用Python和Tkinter做一个图形界面小游戏

一、为什么从小游戏入门GUI? 趣味性强:小游戏直观、有趣,一学就上手。 系统掌握事件驱动:了解按钮点击、键盘响应、图形刷新机制。 扎实基础:为日后构建更复杂应用奠定 GUI 编程基础。 二、选定游戏:猜数字小游戏 🎯 这个小游戏界面简单,核心机制是:3 个按钮分别…

【18】MFC入门到精通——MFC(VS2019)+ OpenCV 显示图片的3种方法

MFC (VS2019)+ OpenCV,显示图片的3种方法 1 方法介绍 2 方法一:嵌套OpenCV窗口显示图片 2.1 建立供工程 添加控件 2.2 引用头文件 2.3 找到OnInitDialog()函数,在其中添加如下代码 2.4 在button触发函数中加入代码(就是你双击button进入的函数) 2.5 注意事项 3 方法二:…

以“融合进化 智领未来”之名,金仓Kingbase FlySync:国产数据库技术的突破与创新

目录开篇&#xff1a;国产数据库的历史性跨越一、KFS 产品定位及发展历程回顾1.1 Kingbase FlySync 发展1.2 Kingbase FlySync与Oracle GoldenGate的对比分析1.2.1 Kingbase FlySync 功能优势1.2.2 技术架构对比1.2.3 性能与扩展性二、数字化时代的新挑战2.1 决策实时性要求越来…

服务器配置错误漏洞

文章目录一、文件解析漏洞1.Apache HTTPD多后缀解析漏洞二、目录遍历漏洞1.Apache目录遍历漏洞2.Nginx目录穿越漏洞服务器配置错误漏洞指因服务器&#xff08;含系统、Web服务、数据库等&#xff09;的参数设置、权限分配、组件配置等不当&#xff0c;导致的安全问题&#xff0…

大模型预测输尿管上段结石技术方案大纲

目录 1. 术前阶段 2. 术中阶段 3. 术后阶段 4. 并发症风险预测 5. 根据预测定手术方案 6. 麻醉方案 7. 术后护理 8. 统计分析 9. 技术验证方法 10. 实验证据 11. 健康教育与指导 12. 完整术方案流程图(Mermaid) 1. 术前阶段 步骤 关键要素 可编辑字段 1.1 影像采集 CT-IVU / …

docker compose 编排容器 mysql Springboot应用

写一个docker-compose.yml文件 内容如下&#xff1a; services:db:image: "docker.xuanyuan.me/library/mysql:8.3.0"restart: unless-stoppedhostname: dbports:- "3306:3306"container_name: mysqlenvironment:- "MYSQL_ROOT_PASSWORD1234"m…