当前位置: 首页 > article >正文

C/C++程序设计的基本概念详解

学C语言有很长一段时间了想做做笔记把C和C相关的比较容易忽视的地方记下来也希望可以给需要的同学一些帮助。我的这些文章不想对C和C的语法进行讲解和罗列这些东西随便找一本书就讲的比我清楚我只是想把一般人忽视的地方尽自己所能描述一下。权当班门弄斧贻笑大方了。首先我想先从C和C的一些基本概念入手。main()函数稍微学过C和C的人都知道main()函数市所有C和C程序必不可少的东西。叫做主函数。所有的程序都应该从main()函数开始执行。但是你们又对这个函数了解多少呢我们都知道C和C是一种函数语言几乎绝大多数的功能都是通过各种函数的调用来实现的C和C也提供了丰富的函数库供编程人员调用。可虽然main()函数每个C程序都必须有的函数在C或者C的函数库里却没有叫做main()的函数它是需要程序设计人员实现的函数。而且你们发现了没有main并不是C和C的保留字。因此理论上你可以在其他地方使用main这个名字比如变量名、类名字、名字空间的名字甚至成员函数的名字。但是即使这样你也不能修改main()函数本身的函数名否则连接器就会报告错误。main()函数是C和C程序的入口这是因为C和C语言实现会有一个启动函数比如MS-C的启动函数就叫做mainCRTStartup()或者WinMainCRT-Startup()。在这个启动函数的最后会调用main()函数然后再调用exit()函数结束程序。如果没有main()函数当然会报错了。所以再C和C开发环境中main()函数其实是一个回调函数。它是需要我们来实现的。有些同学可能学过一些应用程序框架比如MFC什么的。这些程序代码中往往找不到main()函数这是因为那些应用程序框架把main()函数的实现给隐藏起来了main()函数在它们这里有固定的实现模式所以不需要我们编写。在连接阶段框架会自动将包含main()实现的库加进来连接。main()函数也是有原型的。这个原型已经是一种标准了在ISO/IEC14882中对main()的原型进行了定义。123intmain(){/*......*/}和intmain(intargc,char*argv[]){/*......*/}上面这两种形式是最具有可移植性的正确写法。当然不同的编译器可能会允许出现一些扩展。比如允许main()返回void或者有第三个参数char *env[]什么的。这个就要看具体的编译器文档了。关于返回值我们知道main()返回的是int类型的。到底返回什么是有不同含义的。一般情况下返回0表示程序正常结束返回任何非0表示错误或非正常退出。前面讲到了启动函数最后还会调用exit()函数。那么main()函数的返回值就会作为exit()函数的操作数来返回操作系统。在C当中对main()函数还有一些特殊的限制。比如不能重载不能内联不能定义为静态的不能取其地址不能由用户自己调用关于main()函数的参数它可以让编译好的执行程序具有处理命令行参数的能力。这里需要注意不要把“命令行参数”和main()函数的“函数实参”混淆这是两个不同的概念。命令行参数由启动程序截获并打包成字符串数组传递给main()的形参argv[]而包括命令字也就是执行文件自己的名字在内的所有参数的个数则被传递给形参argc。试一下吧咱们来模拟copy命令写个简单的文件拷贝程序。123456789101112131415161718192021222324252627282930313233343536373839//mycopy.c:文件拷贝程序。#include stdio.hintmain(intargCount,char* argValue[]){FILE*srcFile 0;FILE*destFile 0;intch 0;if(argCount ! 3){printf(使用方法%s 原文件 目标文件\n,argValue[0]);}else{if((srcFile fopen(argValue[1],r)) 0){printf(无法打开原文件\%s\!,argValue[1]);}else{if((destFile fopen(argValue[2],w)) 0){printf(无法打开目标文件\%s\!,argValue[2]);fclose(srcFile);}else{while((ch fgetc(srcFile)) ! EOF){fputc(ch,destFile);}fclose(srcFile);fclose(destFile);return0;}}}return1;}//用法mycopy C:\file1.dat D:\newfile.dat内部名称在编写C程序的时候如果没有main()函数连接器会报错。一般报错信息会提示“unresolved external symbol_main”。这里的_main其实就是编译器为main生成的内部名称。其实C和C语言在编译过程中都会按照特定的规则把用户定义的标识符函数、变量、类型、名字空间什么的转换为相应的内部名称。而这些规则还跟指定的连接规范有关。比如在C语言中main的内部名称就叫做_main。C语言这么做是告诉连接器这个东西是个函数。实际上C语言在所有函数的函数名前其实都是加了前缀“_”的以此来区别函数名和其他标识符名称。这种规范在C又是另一种样子。这是因为在C中所有函数只要不是局部于编译单元文件作用域的static函数就会是具有extern连接类型的和global作用域的全局函数。全局函数是不可以有同名的。但是在C里面可以在不同的作用域比如class,struct,union,namespace中定义同名的函数甚至在同一个作用域也可以定义同名函数也就是函数重载。那么转换为内部名称的连接规范就要复杂一些了。比如1234567891011121314classSample_1{charm_name[16];public:voidfoo(char*newName);voidfoo(intage);};classSample_2{charm_name[16];public:voidfoo(char*newName);voidfoo(boolsex);};在其他地方根据这两个类生成两个实例并进行操作123456Sample_1 a;Sample_2 b;a.foo(aaa);a.foo(100);b.foo(bbb);b.foo(false);这里有四个函数但是确是同一个名称。编译器应该怎么区分呢通过各自对象的成员标识符区分那是在代码中区分的但是在连接器看来所有函数其实都是全局函数而全局函数是不能重名的。所以为了避免二义在C中有一个名字修饰规则。也就是在函数名前面添加各级作用域的名称以及重载函数经过编码的参数信息。比如上面四次调用foo函数其实它们会调用四个具有全局名称的函数分别是Sample_1_foopch1Sample_1_fooint1Sample_2_foopch1Sample_2_fooint1。然而这种标准并不是强制的所以不同厂家开发的C编译器有可能会有些许不同而这也正是导致不同厂家的C编译器和连接器不能兼容的原因。那么好了当使用不同编程语言联合开发时候就要定义一个统一的规范这个规范叫做连接规范。这个很好理解了吧因为如果同一个标识符在不同编译单元中用不同的连接规范就会产生不一致的内部名称连接肯定会失败。所以在开发程序库的时候就一定要明确你要用那条连接规范。比如编写C程序是就要规定C连接规范extern “C”。大约有这么几种情况仅对一个类型、函数、变量或常量指定连接规范1234externCvoidWinMainCRTStartup();externCconstCLSID CLSID_DataConverter;externCstructStudent{/*....*/};externCStudent g_Student;对一段代码限定连接规范123456789101112131415161718#ifdef __cplusplusexternC{#endifconstintMAX_AGE 200;#pragma pack(push,4)typedefstruct_Person{char*m_Name;intm_Age;} Person, *PersonPtr;#pragma pack(pop)Person g_Me;int__cdeclmemcmp(constvoid*,constvoid*,size_t);void* __cdeclmemcpy(void*,constvoid*,size_t);void* __cdeclmemset(void*,int,size_t);#ifdef __cplusplus}#endif当前使用的是C编译器并且使用了extern C限定了一段代码的连接规范但又想在其中某行或某段代码保持C的连接规范。123456789101112131415161718192021222324#ifdef __cplusplusexternC{#endifconstintMAX_AGE 200;#pragma pack(push,4)typedefstruct_Person{char*m_Name;intm_Age;} Person, *PersonPtr;#pragma pack(pop)Person g_Me;#if __SUPPORT_EXTERN_CPP_externC{#endifint__cdeclmemcmp(constvoid*,constvoid*,size_t);void* __cdeclmemcpy(void*,constvoid*,size_t);#if __SUPPORT_EXTERN_CPP_}#endifvoid* __cdeclmemset(void*,int,size_t);#ifdef __cplusplus}#endif某个声明中指定了某个标识符的连接规范为extern “C”那么对应的定义也要指定extern “C”1234567891011121314151617#ifdef __cplusplusexternC{#endifmemcmp(constvoid*,constvoid*,size_t);#ifdef __cplusplus}#endif#ifdef __cplusplusexternC{#endifmemcmp(constvoid*p,constvoid*a,size_tlen){//功能实现}#ifdef __cplusplus}#endif其实如果是面向接口的编程就不用考虑这么多了。因为即使接口两端的内部名称不同只要使用了一致的成员对其和排列方式并遵守一致的调用规范一致的函数实现方式。也就是C一致的对象模型那么基本不会有什么问题的。变量和它的初始化在C和C中全局变量extern或static的存放在程序的静态数据区里面。这些变量在程序进入main()之前就被创建了并在main()结束后销毁C和C提供了一个默认的全局初始化器0。也就是编译器会默认的用0来初始化它们。函数内部的static变量和类的static成员也是在静态存储区因此也会默认初始化为0。除非你在创建的时候就提供了初值。这是编译器对静态变量的待遇。而对于其他的自动变量就需要我们给他初始化了。不要指望编译器自动对它们初始化。

相关文章:

C/C++程序设计的基本概念详解

学C语言有很长一段时间了,想做做笔记,把C和C相关的比较容易忽视的地方记下来,也希望可以给需要的同学一些帮助。我的这些文章不想对C和C的语法进行讲解和罗列,这些东西随便找一本书就讲的比我清楚,我只是想把一般人忽视…...

Docker原生WASM运行时落地实践:从零搭建低延迟边缘AI推理节点(含性能压测数据)

更多请点击: https://intelliparadigm.com 第一章:Docker原生WASM运行时落地实践:从零搭建低延迟边缘AI推理节点(含性能压测数据) WebAssembly(WASM)正突破浏览器边界,成为边缘计算…...

神经网络在NLP中的应用与Transformer实现详解

1. 神经网络模型在自然语言处理中的核心价值 第一次接触自然语言处理(NLP)时,我被传统基于规则的方法折磨得够呛——那些复杂的语法解析树和手工设计的特征模板,就像试图用乐高积木搭建一座摩天大楼。直到2013年Mikolov提出word2vec,神经网络…...

MCP 2026国产化配置实战:从零搭建符合等保2.0三级+信创名录要求的高可用集群(含OpenEuler 24.03 LTS完整脚本)

更多请点击: https://intelliparadigm.com 第一章:MCP 2026国产化部署概述与合规基线解析 MCP(Mission-Critical Platform)2026 是面向关键信息基础设施的国产化高可靠平台,其部署需严格遵循《信创产品适配目录&#…...

阿里云国际站服务器DNS服务器设置成什么?服务器dns怎么填写?

阿里云国际站服务器DNS服务器设置成什么?服务器dns怎么填写?针对阿里云国际站(Alibaba Cloud International)的 ECS 服务器,设置 DNS 分为两种常见场景:使用阿里云内网 DNS(推荐)或使…...

Learning to AutoFocus:深度学习驱动的自动对焦实战

文章目录 Learning to AutoFocus:深度学习驱动的自动对焦实战 一、问题背景 二、技术方案 三、数据准备 四、模型 五、训练 六、推理与对焦控制 七、部署考虑 八、实验结果 九、总结 代码链接与详细流程 购买即可解锁1000+YOLO优化文章,并且还有海量深度学习复现项目,价格仅…...

香港工地火灾的警示:边缘AI如何让“监控”真正变成“安全”

引言近期香港某在建工地发生严重火灾,造成多人伤亡。事故原因指向违规动火、疏散通道堵塞、监控预警不及时。这让我不禁思考:在AI和边缘计算足够成熟的今天,我们能不能用技术提前掐灭火灾的苗头?本文不讲产品,只讲技术…...

Nixtla时间序列预测生态:统一接口、高速统计与深度学习模型实战

1. 项目概述:时间序列预测的“瑞士军刀”如果你正在处理时间序列数据,无论是销售预测、服务器监控还是能源消耗分析,那么“Nixtla/nixtla”这个名字很可能已经出现在你的雷达上。这不是一个单一的工具,而是一个由Nixtla团队维护的…...

助贷CRM系统比较是什么?其主要特点应关注哪些方面?

在探讨助贷CRM系统比较时,有几个关键方面需要我们重点关注。首先是获客能力,优秀的系统能够帮助金融机构有效获取和管理客户资源。其次,合规性是确保业务稳定发展的基础,务必符合相关法规,以避免不必要的法律风险。再者…...

hyperf 微服务架构方案大全

---1. 服务拆分原则 大白话: 什么时候该拆、怎么拆、拆多细。 拆分原则…...

scikit-learn预测建模全流程解析与实战技巧

1. 预测建模基础与scikit-learn概览 机器学习预测建模的核心在于从历史数据中发现规律,并将这些规律应用于新数据。scikit-learn作为Python最流行的机器学习库,提供了统一的API设计,使得从数据预处理到模型评估的整个流程变得异常简单。我初次…...

C/C++:类型转换

最近复盘C基础,发现类型转换看着简单,实际细碎考点非常多。很多代码写法平时随手就能写,但一深挖底层编译逻辑就容易混乱。我把整套知识点按步骤拆解、条理化整理,配上完整可运行代码,全程条目化讲解,适合自…...

AI模型部署效率提升210%,Docker AI Toolkit 2026到底重构了哪4层编排协议?

更多请点击: https://intelliparadigm.com 第一章:AI模型部署效率跃升210%:Docker AI Toolkit 2026的范式革命 Docker AI Toolkit 2026(DAIT-2026)正式终结了传统模型容器化部署中“构建慢、启动卡、调试难”的三重瓶…...

基于向量数据库的视频语义检索:从多模态特征提取到工程实践

1. 项目概述:当视频遇见向量数据库最近在折腾一个挺有意思的项目,叫video-db/bloom。光看这个名字,你可能觉得它和视频数据库或者某种“绽放”效果有关。实际上,它解决的是一个更底层、更核心的问题:如何让机器像人一样…...

DemoGPT:从自然语言描述到完整Web应用的AI智能体编程实践

1. 项目概述:当大模型学会自己写代码最近在GitHub上看到一个项目,叫DemoGPT。初看标题,你可能会觉得这又是一个基于GPT的代码生成工具,没什么新意。但当我深入使用和拆解后,发现它的设计理念和实现方式,完全…...

机器学习超参数调优:从原理到工程实践

1. 机器学习超参数调优的本质理解超参数调优是每个机器学习工程师的必修课,但很多人把它简单理解为"试参数"。我在金融风控和推荐系统领域摸爬滚打八年,发现优秀的调参师和普通使用者的本质区别在于:前者把调参视为对问题空间的系统…...

Real-ESRGAN-ncnn-vulkan:3分钟让模糊图像焕然新生的AI超分辨率神器

Real-ESRGAN-ncnn-vulkan:3分钟让模糊图像焕然新生的AI超分辨率神器 【免费下载链接】Real-ESRGAN-ncnn-vulkan NCNN implementation of Real-ESRGAN. Real-ESRGAN aims at developing Practical Algorithms for General Image Restoration. 项目地址: https://gi…...

神经形态视觉传感器与3D堆叠计算架构解析

1. 神经形态视觉与事件相机的技术演进神经形态视觉传感器(Neuromorphic Vision Sensors)正彻底改变传统计算机视觉的范式。这类受生物视觉启发的传感器采用完全异步的工作机制,每个像素独立检测亮度变化并触发事件(Event&#xff…...

京东大屏AI手机+东东APP:银发智能,诚意够!

4月25日,京东举办了大屏AI手机生态发布会。说实话,一开始我对“银发青年”这个定位的产品没抱太高期待——毕竟市面上不少所谓的“长辈机”,要么是简单减配、贴个标签,要么是功能堆砌,根本没真正懂中老年用户的需求。但…...

EasyAnimateV5图生视频部署:Nginx反向代理配置支持HTTPS与域名访问

EasyAnimateV5图生视频部署:Nginx反向代理配置支持HTTPS与域名访问 你是不是已经成功部署了EasyAnimateV5图生视频模型,但还在用IP地址加端口号的方式访问服务?每次都要输入一长串的http://183.93.148.87:7860,不仅难记&#xff…...

1. 线性回归之 向量矩阵

1. 向量 1.1 向量运算1.2 范数 (Norm)2. 矩阵 2.1 矩阵运算:矩阵的加减法和乘法2.2 矩阵转置以及方阵、对称方阵、单位方阵2.3 矩阵乘法的性质2.4 矩阵转置的性质题目:...

2026届学术党必备的六大AI辅助写作网站实际效果

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 大规模语言模型的核心创新,在DeepSeek系列论文中得到了系统阐述。当中的其一&…...

C++:继承与多态详解

文章目录1. 继承1.1 继承的概念1.2 继承方式1.3 基类和派生类的转换1.4 继承中的作用域1.5 类可以不被继承吗1.6 基类包含static函数1.7 多继承与菱形继承问题1.7 虚继承2. 多态2.1 多态的构成条件2.2 虚函数2.2.1 虚函数的重写/覆盖2.3 析构函数的重写2.4 override 和 final 关…...

双像素深度估计与去模糊:Dual Pixel 传感器 AI 实战

文章目录 双像素深度估计与去模糊:Dual Pixel 传感器 AI 实战 一、原理 二、深度估计 2.1 视差深度公式 2.2 深度估计模型 三、去模糊模型 3.1 数据 3.2 去模糊网络 3.3 训练 3.4 推理 四、结果 五、优势对比 六、适用场景 七、总结 代码链接与详细流程 购买即可解锁1000+YOLO…...

AI代码助手实战指南:从GitHub Copilot到Cursor,提升开发效率

1. 从零到一:构建你的AI代码助手实战指南如果你是一名开发者,最近几个月一定被各种AI编程工具刷屏了。从GitHub Copilot在代码行间弹出的智能建议,到Cursor IDE那种“用对话写代码”的颠覆性体验,再到Claude Code在终端里直接帮你…...

教程太碎总失败?这篇Claude Code配置文:从Node.js到API调用一篇搞定(亲测跑通)(Windows系统)

前言 最近AI代码工具更新太快,很多教程刚出来就过时,尤其是Claude Code这类工具,环境配置和API对接总让新手头疼——不是Node.js版本不对,就是海外接口连不上,折腾半天还是报错。 其实核心问题就两个:一是…...

sklearn多核机器学习性能优化实战指南

1. 为什么需要多核机器学习?在数据科学项目中,我们经常遇到这样的场景:当数据集规模达到GB级别时,使用sklearn的默认设置训练模型就像用老牛拉卡车。我曾经在一个电商用户行为预测项目中,单核训练一个随机森林需要近2小…...

MobileNetV3 医学病理分类:卷积分类头 + 迁移学习

文章目录 MobileNetV3 医学病理分类:卷积分类头 + 迁移学习 一、架构 二、环境 三、数据 3.1 结构 3.2 加载 四、模型 五、训练 六、推理 七、结果 八、卷积分类头 vs 全连接分类头 九、冻结 vs 微调对比 十、总结 代码链接与详细流程 购买即可解锁1000+YOLO优化文章,并且还有…...

机器学习超参数优化:网格搜索与随机搜索对比

1. 函数优化中的搜索策略概述在机器学习和数值计算领域,函数优化是一个基础而关键的问题。我们经常需要找到使目标函数取得最小值或最大值的参数组合。当目标函数的解析性质未知或计算复杂度高时,系统化的参数搜索策略就显得尤为重要。两种最直观的搜索方…...

Arm A-profile架构缓存子系统与写回机制解析

1. Arm A-profile架构缓存子系统深度解析在处理器架构设计中,缓存子系统对系统性能有着决定性影响。Arm A-profile架构作为移动计算和嵌入式领域的标杆,其缓存设计哲学体现了性能与能效的完美平衡。最新发布的Arm Architecture Reference Manual for A-p…...