肥宅钓鱼网
当前位置: 首页 钓鱼百科

c基本语法结构(一文掌握C基本语法)

时间:2023-08-18 作者: 小编 阅读量: 1 栏目名: 钓鱼百科

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。一个是乒乓球,一个是男足。因此如果C语言中出现函数重载,那么调用的时候就会查找到两个不同地址,C语言不知道要链接哪一个,因此出错。这个关键字的意思是告诉编译器将该部分按照C语言的规则来进行编译,我们调用C库,当然就要按C的规则来啦。

1. c关键字2. 命名空间

变量、函数和后面要学到的类都是大量存在的,这些变量、函数和类的名称将都存在于全局作用域中,可能会导致很多冲突。

使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突或名字污染,namespace关键字的出现就是针对这种问题的。

2.1 命名空间定义

使用namespace关键字,后面跟命名空间的名字,然后用{}将成员括起来即可,和C语言的结构体类似

存在多个相同的命名空间的时候,编译器编译的时候会把他们合并,如下面

命名空间可以嵌套

PS:命名空间定义了一个新的作用域,命名空间中的所有内容都局限于该命名空间中,但是成员的生命周期没有改变,仍然是全局的。

2.2 命名空间使用

命名空间有3种使用方式

以下均使用该命名空间

1.加命名空间名称及作用域限定符

这种方法每次使用的时候都要进行::限定,比较麻烦

2.使用using将命名空间中成员引入

这样就可以不用::限定命名空间,直接使用b

3.使用using namespace 命名空间名称引入

可以使用所有N中内容,但是需要注意的是这样可能会造成名称冲突

3. C输入&输出

1. 使用cout标准输出(控制台)和cin标准输入(键盘)时,必须包含< iostream >头文件以及std标准命名空间。

2. 使用C输入输出更方便,不需增加数据格式控制

4. 缺省参数

缺省参数就像女神的备胎,当女神有男朋友的时候,备胎被冷落在一旁,当女神分手后,备胎才可以派上用场。

4.1 缺省参数概念

缺省参数是声明或定义函数时为函数的参数指定一个默认值。在调用该函数时,如果没有指定实参则采用该默认值,否则使用指定的实参。

4.2 缺省参数分类

全缺省参数

半缺省参数

注意:

1. 半缺省参数必须从右往左依次来给出,不能间隔着给2. 缺省参数不能在函数声明和定义中同时出现,且应只出现于声明

3. 缺省值必须是常量或者全局变量

5. 函数重载

自然语言中,一个词可以有多重含义,人们可以通过上下文来判断该词真实的含义,即该词被重载了。

比如:有两个体育项目大家根本不用看,也不用担心。一个是乒乓球,一个是男足。前者是“谁也赢不了!”,后者是“谁也赢不了!”

5.1 函数重载概念

函数重载:是函数的一种特殊情况,C允许在同一作用域中声明几个功能类似的同名函数,这些同名函数的形参列表(参数个数 或 类型 或 顺序)必须不同,常用来处理实现功能类似数据类型不同的问题。

下面都是函数重载:

下面这两个不是函数重载!

5.2 名字修饰

那么为什么C支持函数重载而C语言不支持呢?

一个程序要运行起来要经历以下几步:假设有以下文件

f.h f.cpp test.cpp

1.预处理——头文件展开,宏替换,条件编译,去掉注释

生成f.i test.i

2.编译——检查语法,生成汇编代码

生成f.s test.s

3.汇编——把汇编代码转换成二进制的机器码(让CPU能看懂)

生成f.o test.o

4.链接——找调用函数的定义地址,链接对应上,合并到一起

生成a.out可执行程序

在链接阶段,编译器看到test.o调用了哪些函数,就会去f.o的符号表中找对应函数的地址,然后链接在一起,那么要怎么去找呢?C和C语言采用了不同的名字修饰,就会用不同的名字去找

我们发现名字由_Z 函数名长度 函数名首字母 函数按顺序参数首字母,因此支持函数重载(名字不一样,找的对象就不一样)C:

这里我们发现C语言则是直接用函数名作为地址查找对象,回想我们的函数指针,是不是函数指针和函数名都可以调用函数呢。因此如果C语言中出现函数重载,那么调用的时候就会查找到两个不同地址,C语言不知道要链接哪一个,因此出错。

5.3 extern “C”

我们知道C语言可以调用C语言的静态库和动态库,C可以调用C的静态库和动态库,那么C能不能调用C的库?C能不能调用C的库?

答案是可以的。

我们先来看C调用C的库,这里我们用C语言实现的栈的代码生成一个静态库

再新开一个项目,调用这个库,这里对新项目的属性进行更改。

然后来看一下现在能否调用

这是不是意味着C不能调用C的库?别急,这时候extern C就登场了

我们发现加了这个关键字后就链接成功了。这个关键字的意思是告诉编译器将该部分按照C语言的规则来进行编译,我们调用C库,当然就要按C的规则来啦。

再来看一下C语言能否调用C的库,我们把后缀名更改一下

(这里是c语言了,因此只能用typedef过的别名,不能再用一个Stack,因为C语言不支持) 好像不行,我们刚刚是在C的部分进行修改,这次我们也在C的部分进行修改,我们来到test_01,对头文件部分的声明进行如下修改。

这样是不是就顺利链接成功了,这里的预编译进行了判断,如果文件是C的,那么就用C的规则进行编译,也可以这么写:

6. 引用6.1 引用概念

引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。

类型& 引用变量名(对象名) = 引用实体;

引用类型必须和引用实体是同种类型的

6.2 引用特性

1. 引用在定义时必须初始化2. 一个变量可以有多个引用3. 引用一旦引用一个实体,再不能引用其他实体

6.3 常引用

这里我们取别名的规则是:

对原引用变量,权限只能缩小,不能放大。这里权限指的是读写权限。

因此对const常量只能进行读,也就只能用const引用。

在下面将double赋给int别名的过程中,编译器会产生“临时变量”,将double d中整数部分赋给临时变量, 这个临时变量再将这个整数赋给另一个int类型的临时变量,最后int把临时变量赋给rd,也就是说rd引用的其实是这个int临时变量,而临时变量具有常属性,因此要用const引用。

6.4 使用场景

1.作函数参数

在学习C语言的时候我们如果要交换两个数,那么就需要传址调用函数,而现在可以直接用引用进行修改,这就是引用做参数的好处,输出型参数另外,如果是传值调用的话,我们知道形参是实参的一个临时拷贝,而传引用的时候并没有拷贝这一步,这就提高了效率

2.作函数返回值

结果是显然的,我们返回的是静态变量n的别名,而出了函数作用域n并没有销毁,那么来看下面这个代码

n和ret地址一样

这里n不再是静态变量了,出了函数作用域后空间返还,而我们的ret是n的别名,这是不是就相当于野指针。因此只有第一次调用函数后ret中的值是1,调用一次函数(函数重载<<)后n的空间被制成随机数,因此剩下两次都是随机数,因此我们用引用作返回值的时候返回的应该是出了函数定义域还存在的变量的引用,否则就应该按值返回,这里和指针是一个道理。

明白了这些下面这个程序的结果就应该很明确了,应该是7

道理是一样的。另外引用作返回值也会提高效率

6.5 传值、传引用效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低。

这里用程序来比较一下

不是很明显的原因是我们计算机的速度实在太快,但是还是有效率差异的。

指针和引用的效率是一样的,因为引用的底层和指针的底层是一样的!

6.6 引用和指针的区别

从语法概念上:引用是别名,没有额外开空间,而指针存储变量的地址,开辟了4/8字节的空间

从底层实现的角度:引用实际上是有空间的,因为引用是按指针的方式来实现的

来看一下指针和引用的汇编

汇编指令完全一样,也印证了底层是一样的

那引用和指针的不同点是什么呢?

1. 引用在定义时必须初始化,指针没有要求

2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体

3. 没有NULL引用,但有NULL指针

4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)

5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小

6. 有多级指针,但是没有多级引用

7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理

8. 引用比指针使用起来相对更安全

7. 内联函数

7.1 概念

以inline修饰的函数叫做内联函数,编译时C编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。

在学习C语言的时候,我们遇到函数体短小且频繁调用的函数的时候,采用的优化方式是使用宏进行替换,但是宏太繁琐啦,难以看懂,因此c就产生了内联函数。

那么内联函数是如何进行优化的呢?来看代码。

当我们不用inline定义函数的时候,函数是怎么调用的呢?

进行函数压栈,然后用call指令调用。那么用了inline后呢

我们发现在汇编代码中直接对函数调用的代码进行了替换,没有压栈和call调用指令。

7.1 特性

1. inline是一种以空间换时间的做法,省去调用函数额开销。所以代码很长或者有循环/递归的函数不适宜使用作为内联函数。

2. inline对于编译器而言只是一个建议,编译器会自动优化,如果定义为inline的函数体内有循环/递归等等,编译器优化时会忽略掉内联。

3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。

例如如果在.h和.cpp文件中分别声明和定义内联函数,那么在链接的时候就会出现错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用

那么内联函数相比宏有哪些优点?

1.内联函数在debug版本下支持调试,而宏不支持

2.内联函数就是普通函数的写法,解决了宏晦涩难懂的问题

8. auto关键字(C11)

8.1 auto简介

在早期C/C中auto的含义是:使用auto修饰的变量,是具有自动存储器的局部变量

C11中,标准委员会赋予了auto全新的含义即:auto不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto声明的变量必须由编译器在编译时期推导而得。

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种“类型”的声明,而是一个类型声明时的“占位符”,编译器在编译期会将auto替换为变量实际的类型。

8.2 auto的使用细则

1.用auto声明指针类型时,用auto和auto*没有任何区别,但用auto声明引用类型时则必须加&

2. 在同一行定义多个变量当在同一行声明多个变量时,这些变量必须是相同的类型,否则编译器将会报错,因为编译器实际只对第一个类型进行推导,然后用推导出来的类型定义其他变量。

8.3 auto不能推导的场景

1. auto不能作为函数的参数

2. auto不能直接用来声明数组

3. 为了避免与C98中的auto发生混淆,C11只保留了auto作为类型指示符的用法4. auto在实际中最常见的优势用法就是C11提供的新式for循环,还有lambda表达式等进行配合使用。

9. 基于范围的for循环(C11)9.1 范围for的语法

for循环后的括号由冒号“ :”分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围。

范围for循环与普通循环类似,可以用continue来结束本次循环,也可以用break来跳出整个循环。

9.2 范围for的使用条件

1. for循环迭代的范围必须是确定的对于数组而言,就是数组中第一个元素和最后一个元素的范围;对于类而言,应该提供begin和end的方法,begin和end就是for循环迭代的范围。

2. 迭代的对象要实现和==的操作。

10. 指针空值nullptr(C11)10.1 C98中的指针空值

在传统头文件中有如上定义,我们发现在C中Null被宏替换为0,而如果我们要对一个指针赋空值,仍采用NULL的话有些不妥,因为0毕竟是一个数字,而不是指针类型,因此C11引入了nullptr,其实也就相当于(void*)0。

    推荐阅读
  • 美团外卖红包怎么退回去(美团外卖红包怎么退还)

    美团外卖兑换的红包怎么取消兑换?美团外卖的会员红包能兑换商家红包,兑换以后不想购买了,想换回会员红包,该怎么操作呢?下面我们就来看看美团撤回兑换商家红包的技巧下面将介绍美团外卖兑换了商家红包怎么撤回。在美团首页点击图标。

  • 什么软件可以消除美颜(什么软件能去除美颜)

    以Primo为例,Primo软件可以消除美颜。能还原各种软件修图前的效果,一秒消除磨皮、美瞳、瘦脸等美颜效果,展现拍摄者原始的脸部状态。软件是一系列按照特定顺序组织的计算机数据和指令的集合。一般来讲软件被划分为系统软件、应用软件和介于这两者之间的中间件。系统软件是负责管理计算机系统中各种独立的硬件,使得它们可以协调工作。

  • 大豆油花生油玉米油哪个口感好(花生油大豆油玉米油)

    玉米油热稳定性强,几乎适用于所有的烹饪方式,没有明显的缺点。经常更换食用油的品种,能够满足人体对营养更全面的需要。植物油相比动物油,普遍饱和脂肪酸含量低,不饱和脂肪含量高3、最好6个月内吃完一桶油。食用油会有保质期,会变质,放得越久过氧化物越多,影响健康。

  • 送男友什么生日礼物好(送男友的生日礼物)

    送男友什么生日礼物好键盘。如果你的男朋友是一名程序员,键盘绝对是最好的礼物,没有程序员能够拒绝女朋友送的键盘了。对于初入职场的男生,手表是最百搭的配饰。另外情侣之间送手表的意义也非常好,代表着长长久久,表达心意。如果要说成熟男人的必需品,剃须刀应该是比较合适的答案。几乎每天都会使用,并且是肌肤之亲,是送男朋友非常好的礼物之选。

  • 王者荣耀公孙离和裴擒虎cp吗(王者荣耀公孙离的CP是谁)

    虽然公孙离一直都暗恋着苏烈,但这个问题其实苏烈自身根本就不知道,因为公孙离从来没有对苏烈表白过,所以他两人并不是CP关系。公孙离和盾山很多玩家也大单猜测过公孙离的CP其实是盾山,因为在公孙离的秘闻中就有提到过,公孙离的CP是长城守卫军中的一员,而盾山也是长城中的一员。嗯,没想到公孙离的CP竟然是它。

  • 有苏东和谭加一是什么电视剧(有苏东和谭加一的电视剧介绍)

    下面希望有你要的答案,我们一起来看看吧!有苏东和谭加一是什么电视剧有苏东和谭加一是电视剧《金牌律师》。《金牌律师》原名《离不离律师事务所》,该剧是律政职场情感大戏,由傅东育执导,朱丹、周一围、张铎、黄小蕾、张志坚、是安,和朱佳煜等共同主演。该剧讲述的都是婚恋官司,为了将男男女女们从情感纠葛中解决出来,剧中的律师们各显神通,但是最后的结局往往让人瞠目结舌。该剧已于2014年6月27日首播。

  • 香椿树皮能有什么功效(在农村随手扔的香椿树皮作用大)

    香椿树皮里面含有香精,对蚊虫和蚂蚁有刺激的作用,可以起到驱赶蚊虫蚂蚁的效果。孕妇不可食用香椿皮香椿树皮是一种凉性的食材,同时也是一味中药,切记不可食用太多,尤其是感冒的人更不要吃,会加重感冒,如果身体无恙,建议煮菜、熬汤的时候适当放入一些即可。

  • 怎么戴红领巾(红领巾怎么戴)

    以下内容希望对你有帮助!怎么戴红领巾把红领巾铺平,把最长的一边往有顶角的一边对折,一直对折到只留下一个小三角。把红领巾放到脖子上,相互交叉,下面的那条要比上面的那条稍微长一些。然后把长的一边绕过短的一边再绕到里面往下塞进去。抽出拉直,稍微整理一下就好了。

  • 黑暗之魂3结局触发条件(黑魂3结局触发条件教学)

    打完最终BOSS后,篝火旁边出现防火女的召唤印记,召唤她。在篝火路半边寨和亚斯特拉的安利对话,获得契约青之守护者。

  • 气象学的冬天的定义是什么(气象学的冬天是怎么定义的呢)

    气象学的冬天的定义是平均气温连续5天低于10℃冬天指冬季,四季之一,传统上是以二十四节气“立冬”作为冬季的开始,今天小编就来聊一聊关于气象学的冬天的定义是什么?冬天指冬季,四季之一,传统上是以二十四节气“立冬”作为冬季的开始。冬天季节,生气闭蓄,万物进入休养、收藏状态。