C到C++的升级

C和C++的关系

  • C++继承了所有C语言的特性;
  • C++在C的基础上提供了更多的语法和特性,C++语言去除了一些C语言的不好的特性。
  • C++的设计目标是运行效率与开发效率的统一。

变化一:所有变量都可以在使用时定义

C++中更强调语言的实用性,所有的变量都可以在需要使用时定义。我们都知道C语言都必须要在作用域之前的位置定义,否则会报错。

引申概念,什么是作用域?
通常我们在写代码的时候,所用到的名字并不是有效/可用的,限定变量或者函数的名字的可用性的代码范围就叫作用域。全局变量作用域就是整个文件,加了extern声明之后作用域就可以为整个工程空间使用。局部变量的作用域就是本函数内,用完即丢弃。
范例:

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int c = 0;printf("Begin...\n");for(int i=0; i < 10; i++) //在C语言中,变量定义需要在函数开始,不能在使用的地方定义。{for(int j = 0; j < 10; j++){c += i*j;}}printf("c = %d\n", c);printf("End...\n");return 0;
}

C++编译器也可以编译C代码,通过Dev-C++软件分别创建C工程和C++工程,C++工程可以编译pass,C工程报错如下:
在这里插入图片描述
注意,使用ubuntu gcc编译能编译通过,因为Dev-C++ 的C编译器和GUN gcc 编译器遵循的标准不一样。GUN gcc 对标准C进行了扩展。

变化二:register关键字变化

  • C语言中,register这个关键字请求编译器尽可能的将局部变量存在CPU寄存器中,而不是通过内存寻址访问,以提高效率。
    注意是尽可能,不是绝对。因为,如果定义了很多register变量,可能会超过CPU的寄存器个数,超过容量。
    C语言中无法取得register变量地址
  • 在C++中依然支持register关键字。为了兼容C语言特性。
    C++编译器有自己的优化方式,不使用register也可能做优化。
    C++中可以取得register变量的地址,当C++编译器发现程序中需要取register变量的地址时,register对变量的声明变得无效。
    早期C语言编译器不会对代码进行优化,因此register变量是一个很好的补充。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{register int c = 0;printf("Begin...\n");printf("&c = %08X\n", &c);printf("End...\n");return 0;
}

Dev-C++编译器编译C工程报错提示
GUN gcc 编译报错
说明标准C不支持对register取地址。VC++6.0有警告,但是也可以获取寄存地址,只是说明编译器对register变量有处理,申请不掉register变量就变成普通变量。但是标准C是不支持的。
Dev-C++ 编译C++工程可以编译通过,并打印register变量地址

变化三:同名的全局变量处理

  • C语言中,重复定义多个同名的全局变量是合法的,最终会被链接到全局数据区的同一个地址空间上。
  • 在**C++**中,不允许定义多个同名的全局变量,C++拒绝这种二义性的做法。
#include <stdio.h>
#include <stdlib.h>
int c = 1;
int c;//加上extern 关键字,C++可以编译通过,表示在前面定义的。
int main(void)
{printf("Begin...\n");printf("&c = %08X\n", &c);printf("End...\n");return 0;
}

Dev-c++编译报错

变化三 const 常量

  • 在C中,const修饰的变量是不允许再次赋值的,但是可以通过指针操作const变量。const变量是只读变量,有自己的存储空间。
#include <stdio.h>
//const int c = 0;// const修饰全局变量,不可用指针操作修改值,会出现段错误。
int main(void)
{const int c = 0;int *p = (int*)&c;*p = 8;printf("c=%d\n", c);return 0;
}

GUN编译验证结果

  • 在C++中,编译器对const常量处理:
  1. 当碰见const声明时,在符号表中放入常量;
  2. 编译过程中若发现使用常量,则直接以符号表中的值替换;
  3. 编译过程中若发现对const使用了extern或者&操作符,则给对应的常量分配存储空间。
    Notice:C++编译器虽然可能为const常量分配空间,但不会使用其存储空间中的值。
    如果再到上面的代码中插入打印C常量地址操作
printf("c address = %08X\n", &c);

最终打印如下:
c=0
c address = EB6F729C

C++编译器处理const常量示意图

  • C中const变量是只读变量,告诉编译器该变量不能出现在赋值符号左边,本质是变量,有自己的存储空间。
  • C++中const 是真正的常量,当const常量为全局,并且有extern关键字,或者使用&操作符取const常量地址时,才会分配地址空间。
    为什么C++还要为const 常量分配地址空间呢?因为为了兼容C。

范例,加强const常量c和c++的理解:

#include <stdio.h>
int main(int argc, char *argv[])
{const int a = 1;const int b = 2;int array[a + b]={0};int i = 0;for (i = 0; i < (a+b); i++){printf("array[%d] = %d\n", i, array[i]);}return 0;
}

分别用gcc 和 g++编译运行结果:
在这里插入图片描述
C编译器直接报错,无法确定数组array的大小,因为const在c中本质是变量,编译器无法知道数组array的大小,变量只有在运行时候才知道值。
C++编译器作为常量处理,直接到符号表中取值,所以array[a+b] 就是array[1+2].
C++中的const小结

  • const常量类似于宏定义,const int c = 0; ≈ #defin c 5
  • c++中的const常量与宏定义不同
    const 常量是由编译器处理的,提供类型检查和作用域检查。而宏定义由预处理器处理,简单的文本替换。

范例:

#include <stdio.h>
void f()
{#define a 3 //本意是想在本函数中使用a,作用域是该函数const int b = 4;//该变量作用域为f函数
}void g()
{printf("a = %d\n", a);//但是预编译器会直接替换掉a.printf("b =d %d\n", b);//编译会报错,因为编译器会对作用域进行检查
}int main(int argc, char *argv[])
{f();g();return 0;
}

在这里插入图片描述

变化四:struct类型的变化

  • C语言的struct定义了一组变量的集合,C编译器并不认为这是一种新的类型。
  • C++中的struct是一个新类型的定义声明。
#include <stdio.h>
struct Student
{const char* name;int age;
};int main(int argc, char *argv[])
{Student s1 = {"Tom", 30};Student s2 = {"Tony", 28};return 0;
}

C和C++编译结果
C编译器认为Student 不是一个类型,所以报错。C++认为是一种新的类型,可以直接赋值。

  • C++中所有的变量和函数都必须要有类型。
  • C语言中的默认类型在C++中是不合法的。
    范例:
#include <stdio.h>
f(i) //C语言默认类型 int f(int i)
{printf("i = %d\n", i);
}
g() //c语言默认类型 int g()
{return 5;
}int main(int argc, char *argv[])
{f(10);printf("g() = %d\n", g());//printf("g() = %d\n", g(1, 2, 3)); //在C中,这里打开也能编译通过。反之在C++中fail。return 0;
}

在这里插入图片描述
在C语言中,f(i) 和g()函数默认为 int f(int i) 和 int g();
g() 函数在C中可以接受任意的参数,所以在调用的地方写g(1,2,3)也能通过,只不过对传入的参数不处理。
如果C语言中想要表示不接受任何参数,则需要在函数括号中加void。

思考,int f();与int f(void); 的区别是什么?

  • C语言中,int f();表示函数可以接受任意的参数,而 int f(void);表示调用时不接受任何参数否则就报错。
  • C++中,int f();和int f(void) 都相同,表示函数不接受任何参数。对类型检测加强。

总结

  • C++ 以C语言为基础,进行了加强。
  • C++更强调实用性,可以在使用的时候声明变量,不需要在函数开头。
  • C++中register只是向C兼容,C++编译器能够进行更好的变量优化。
  • C++中的const是一个真正意义的常量,而不是只读变量。
  • C++更加强调类型,任何函数和变量都必须要指明类型。

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

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

相关文章

CentOS7 Hadoop3.3.0 安装与配置

一、安装JDK 1、创建文件夹tools和training用于存放压缩包和解压使用&#xff0c;tools存放压缩包&#xff0c;training用于解压后安装jdk和hadoop的路径。 1&#xff09;回到路径为 / 的位置 cd /2) 创建 tools 和 training mkdir toolsmkdir training3) 进入tools文件夹 …

测试工程师的领航指南:《Effective软件测试》

目录 前言一、本书适合对象二、本书大纲第1章&#xff1a;有效和系统的软件测试第2章&#xff1a;基于需求规格的测试第3章&#xff1a;结构化测试与代码覆盖第4章&#xff1a;契约式设计第5章&#xff1a;基于属性的测试第6章&#xff1a;测试替身和模拟对象第7章&#xff1a;…

Python综合案例(基本地图使用)

一、基本地图的使用 基本代码&#xff1a; """ 演示地图可视化的基本使用 """ from pyecharts.charts import Map from pyecharts.options import VisualMapOpts# 准备地图对象 map Map() # 准备数据 data [("北京", 99),("…

【C++进阶(四)】STL大法--list深度剖析list迭代器问题探讨

&#x1f493;博主CSDN主页:杭电码农-NEO&#x1f493;   ⏩专栏分类:C从入门到精通⏪   &#x1f69a;代码仓库:NEO的学习日记&#x1f69a;   &#x1f339;关注我&#x1faf5;带你学习C   &#x1f51d;&#x1f51d; 链表list 1. 前言2. list的使用2.1 list的构造函…

【树形权限】树形列表权限互斥选择、el-tree设置禁用等等

文章目录 一、实现如上树形列表1.1 首先要就是渲染树形列表1.2 然后通过插槽处理头部标题1.3 再通过插槽处理表格body体内容1.4 让body体中的选框和表头中的选框产生关联 二、将 el-tree 整棵树设为禁用状态三、动态表格合并 需求&#xff1a;按照权限管理配置的数据权限树展开…

如何利用客户旅程打造好的用户体验?

在当今竞争激烈的市场中&#xff0c;提供卓越的用户体验已经成为企业脱颖而出的关键因素之一。客户旅程是实现出色用户体验的有力工具之一&#xff0c;而HubSpot的客户旅程规划功能为企业提供了强大的支持&#xff0c;帮助他们更好地理解、管理和改善客户的互动过程。今天运营坛…

【USRP】调制解调系列5:16QAM、32QAM、64QAM、256QAM、1024QAM、基于labview的实现

QAM 正交振幅键控是一种将两种调幅信号&#xff08;2ASK和2PSK&#xff09;汇合到一个信道的方法&#xff0c;因此会双倍扩展有效带宽&#xff0c;正交调幅被用于脉冲调幅。正交调幅信号有两个相同频率的载波&#xff0c;但是相位相差90度&#xff08;四分之一周期&#xff0c…

参编三大金融国标,奇富科技以技术促行业规范化演进

近期&#xff0c;由中国互联网金融协会领导制定的《互联网金融智能风险防控技术要求》《互联网金融个人网络消费信贷信息披露》《互联网金融个人身份识别技术要求》三项国家标准颁布&#xff0c;由国家市场监督管理总局、国家标准化管理委员会发布&#xff0c;奇富科技作为核心…

Flutter 混合开发调试

针对Flutter开发的同学来说&#xff0c;大部分的应用还是Native Flutter的混合开发&#xff0c;所以每次改完Flutter代码&#xff0c;运行整个项目无疑是很费时间的。所以Flutter官方也给我们提供了混合调试的方案【在混合开发模式下进行调试】&#xff0c;这里以Android Stud…

OPENCV实现图像查找

特征匹配+单应性矩阵 # -*- coding:utf-8 -*- """ 作者:794919561 日期:2023/9/4 """ import cv2 import numpy as np# 读图像 img1 = cv2.imread(F:\\learnOpenCV\\openCVLearning\\pictures\\chess

【HTML5高级第一篇】Web存储 - cookie、localStorage、sessionStorage

文章目录 一、数据存储1.1 cookie1.1.1 概念介绍1.1.2 存储与获取1.1.3 方法的封装1.1.4 总结 1.2 localstorage 与 sessionstorage1.2.1 概述1.2.2 操作数据的属性或方法1.2.3 案例-提交问卷1.2.4 Web Storage带来的好处 附录&#xff1a;1. HTML5提供的数据持久化技术&#x…

万里路,咫尺间:汽车与芯片的智能之遇

目前阶段&#xff0c;汽车产业有两个最闪耀的关键词&#xff0c;就是智能与低碳。 在践行双碳目标与产业智能化的大背景下&#xff0c;汽车已经成为了能源技术、交通技术、先进制造以及通信、数字化、智能化技术的融合体。汽车的产品形态与产业生态都在发生着前所未有的巨大变革…

Hadoop的概述与安装

Hadoop的概述与安装 一、Hadoop内部的三个核心组件1、HDFS&#xff1a;分布式文件存储系统2、YARN&#xff1a;分布式资源调度系统3、MapReduce&#xff1a;分布式离线计算框架4、Hadoop Common&#xff08;了解即可&#xff09; 二、Hadoop技术诞生的一个生态圈数据采集存储数…

C语言:递归思想及实例详解

简介&#xff1a;在计算机科学中是指一种通过重复将问题分解为同类的子问题而解决问题的方法。通过函数的自调用化繁为简。 递归可以说是编程中最神奇的一种算法。因为我们有时候可能不能完全明晰代码的运行过程&#xff0c;但是我们却知道代码可以跑出正确的结果。而当我们使…

qt day 6

登录界面 #include "window.h" #include<QDebug> #include<QIcon> Window::Window(QWidget *parent) //构造函数的定义: QWidget(parent) //显性调用父类的构造函数 {//判断数据库对象是否包含了自己使用的数据库Student.dbif(!db.contains(&…

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证

微波系统中散射参量S、阻抗参量Z及导纳参量Y之间的关系及MATLAB验证 用HFSS设计了一微波元件&#xff0c;仿真出了其散射参量S、阻抗参量Z及导纳参量Y&#xff0c;用MATLAB验证他们之间的关系 HFSS设计螺旋线圈 用HFSS设计了一个螺旋线圈&#xff0c;如上图所示。 进行仿真&…

8K视频来了,8K 视频编辑的最低系统要求

当今 RED、Canon、Ikegami、Sony 等公司的 8K 摄像机以及 8K 电视&#xff0c;许多视频内容制作人和电影制作人正在认真考虑 8K 拍摄、编辑和后期处理&#xff0c;需要什么样的系统来处理如此海量的数据&#xff1f; 中央处理器&#xff08;CPU&#xff09; 首先&#xff0c;…

Spring Security安全登录的调用过程以及获取权限的调用过程

1.第一次登录时候调用/user/login整个流程分析 (0)权限授理 首先调用SecurityConfig.java中的config函数将jwtAuthenticationTokenFilter过滤器放在UsernamePasswordAuthenticationFilter之前 Override protected void configure(HttpSecurity http) throws Exception{......…

FinClip 支持创建 H5应用类小程序;PC 终端 优化升级

FinClip 的使命是使您能够通过小程序解决关键业务流程挑战&#xff0c;并完成数字化转型。不妨让我们看看本月产品与市场发布亮点&#xff0c;是否有助于您实现目标。 产品方面的相关动向&#x1f447;&#x1f447;&#x1f447; FinClip 支持创建 H5应用类小程序 近期我们…

MongoDB常用的比较符号和一些功能符号

比较符号 results collection.find({age: {$gt: 20}})功能符号 results collection.find({name: {$regex: ^M.*}})