C和C++常见误区以及问题整理
c和c++的关系
c是面向过程的语言,c++是在c的基础上扩展的面向对象的编程语言。
c++具备c的所有功能,对c的库完全兼容。
c++的标准在98年确定,在那之前已经有一些库大量使用。
新标准中,推出了名称空间的概念,既是为了方便人们使用新标准的同时,不用大量修改之前的代码,对之前的代码兼容,同时可以有效的避免名称冲突。
旧标准中以.h结尾
新标准没有.h
旧标准中可以直接包含c的库文件,编译器会附带c的兼容库实现
新标准中有一样的c库子模块支持,命名方式变更为:原stdio.h,新cstdio,即前面+c,后面去掉.h
C++标准库(C++ Standard Library),是类库和函数的集合。
C++编译器厂商根据C++标准委员会官方的ISO规范并将其转化为代码。
C++编译器厂商在实现C++标准库过程中必须依赖其不同操作系统所提供的系统调用接口,因此每个平台都有其自己的C++标准库实现。
C++标准库的特点如下:
A、C++标准库不是C++语言标准的一部分,由类库和函数库组成。
B、C++标准库中定义的类和对象都位于std命名空间中。
C、C++标准库的头文件都不带.h后缀。
D、C++标准库涵盖了C库的功能
E、C++标准库中包含一个涵盖C库功能的子库,通常头文件以c开头,如#include <cmath>
,#include <cstring>
等。
如何理解名称空间
命名空间存在的目的是为了解决源代码中的重名问题。比如你写代码的时候需要用到矩阵计算,于是你定义了一个类,叫做Matrix。然后你引入的第三方库中,也有一个叫做Matrix的类,于是乎就重名了。为了解决这个问题,只需要把它们放在不同的命名空间里,比如你的叫做foo::Matrix, 第三方库的叫做third_party::Matrix,这样它们就有了不同的名字,编译器就可以正确识别出你在代码中用的Matrix是哪一个。
这个时候如果你同时使用了using namespace foo,using namespace third_party,就又会使这两个不同的类具有相同的标识符。因此在良好的编程风格中,尽可能的避免使用using namespace,或者仅在翻译单元(可以理解为是一个cpp文件)内、函数内、类内使用(using具体的对象、函数)。
第二个问题是是不是所有的程序名字都要在std中。恰恰相反,C++标准禁止用户自己扩充std命名空间,所以用户的代码应该是处于非std空间中,例如默认命名空间:: 。但是,事实上每一个编译器都支持用户在std空间中定义自己的类、函数、对象,因此在std实现自定义类的哈希函数也是可以编译通过的,尽管这是一个违背标准的行为。
在刷算法时,可以随意一点,按照这种方式使用
using namespace std; // avoid as too indiscriminate(随意)
严谨一点可以这样,最大限度地避免冲突的产生
using std::cin;
using std::cout;
using std::endl;
int x;
cin >> x;
cout << x << endl;
或者这样
int x;
std::cin >> x ;
std::cout << x << std::endl;
However,
using namespace std;
is considered a bad practice because you are practically importing the whole standard namespace, thus opening up a lot of possibilities for name clashes. It is better to import only the stuff you are actually using in your code, like
using std::string;
字符串类型
C语言不支持真正意义上的字符串,但可以使用字符数组和一组函数实现字符串操作。C语言不支持自定义类型,因此也不能定义字符串类型。
C++语言可以自定义类型,可以通过类完成字符串类型的定义,但C++语言也没有原生的字符串类型。C++语言通过C++标准库提供的string类型实现对字符串类型的支持。string类的特性如下:
A、string直接支持字符串连接
B、string直接支持字符串的大小比较
C、string直接支持子串查找和提取
D、string直接支持字符串的插入和替换
变量声明与定义
extern int i; //声明,不是定义
int i; //声明,也是定义
定义只能出现在一处。也就是说,不管是 int a 还是 int a=0 都只能出现一次,而 extern int a 可以出现很多次。
当你要引用一个全局变量的时候,你就要声明 extern int a 这时候 extern 不能省略,因为省略了,就变成 int a 这是一个定义,不是声明。
前缀指定基数:
- 0x 或 0X 表示十六进制,
- 0 表示八进制,
- 0b表示二进制
- 不带前缀则默认表示十进制
后缀是 U 和 L 的组合,U 表示无符号整数(unsigned),L 表示长整数(long)。后缀可以是大写,也可以是小写,U 和 L 的顺序任意。
结构数据类型
结构数据类型允许构造由多个基础数据类型组合而成的复杂结构,结构数据类型为面向对象的蓝本。以下的结构数据类型通过指针实现了二叉树结构
typedef struct Bintree {
int data;
struct bintree *lchild; // left child of the node
struct bintree *rchild; // right child of the node
} bintree; // 自定义 bintree 类型
&&,||,&,|
&&:逻辑与,前后条件同时满足表达式为真
||:逻辑或,前后条件只要有一个满足表达式为真
&:按位与
|:按位或
&&和||是逻辑运算,&与|是位运算
*,&
*
的作用
1.乘号(Multiply)
2.声明指针(Pointer Statement)
//就是声明变量a是5,把a的地址附到指针ptr上
int a =5; int* ptr=&a;
3.解引用 (Dereference)
*ptr 单独拿出来就是找出 ptr指针指向的值,按照第二点的说法就是5
&
的作用
&叫做取地址符号
一般指针只能接受一个内存地址而不能接受一个值
//错误表达,指针不能接受一个值
int a =5; int* ptr=a;
//正确表达,把a的地址给指针ptr
int a =5; int* ptr=&a;
案例:
数据结构伪代码理解
比如定义链表时:
typedef struct Node{
}Node,*Linklist;
在创建函数时候这样,
int creatlist(Linklist &L){}
用这个函数时候需要这样写
creatlist(L);
而定义顺序表时
typedef struct{
}List;
创建函数时候
int creatlist(List *l){}
用函数的时候
creatlist(&l);
解答
不关引用和题主C语言不好的事,事情应该是这样的:
并不是你的教材和你的老师讲错了,这样的代码是有意为之。但是程序又跑不起来,那问题出在哪呢。问题就在于大多数数据结构教材一开始就告诉了你,
本书的算法都是用类C语言伪码实现的,并非是严格意义上的C语言。在创建函数时候这样,
int creatlist(Linklist &L){}
用这个函数时候需要这样写creatlist(L);
为什么这么创建(定义)函数呢?因为编书人想告诉你的是函数的参数并非变量本身,而是存放变量的地址(有些答主学了C++,看到&就是引用,真的,你太敏感了)。
为什么要这么调用呢?因为函数的定义,函数调用需要传一个地址进去,那么传一个指针进去是理所当然的。再来看这段代码。而定义顺序表时
typedef struct{
}List;
创建函数时候
int creatlist(List *l){}
用函数的时候
creatlist(&l);
WTF?看起来跟上面的定义和调用格式都完全不一样哎,又懵逼了...其实是这样的:为什么这样创建(定义)函数呢?和上其实同理,如果这样写,typedef struct{
}List;
int creatlist(List l){}就是在说你只是传了一个结构体进去。所以作者加个*,是想告诉你这里传进去的是个顺序表。
为什么这么调用呢?还是因为定义,函数需要一个地址,那么我们就传一个地址进去。综上所述,这几段代码肯定是跑不起来的,因为根本不是C语言代码,只是伪代码而已,那作者是吃多了才这么写么?不是。作者只是想简化用来实现算法的语言,因为数据结构中选用的语言根本不是重点,重点是各种数据结构的思想。换句话说作者没想让你把程序跑起来,作者只是想让你能更容易懂。说到这里我想你应该很明白了,程序跑不起来书和老师都没有错(也不是某些答主说的C++中的引用或者你的C语言学得不好),既然作者已经将语法简化得不能再简化了,何妨不将教材上的伪代码充分理解,然后选取一门语言自己实现它呢?或许作者选用伪代码来讲述也有这一层原因(逼你自己动手)吧。
参考链接:请问 C 语言中 & 和 * 的用法? - 陈思定的回答 - 知乎
gcc,g++,gdb,cc
gcc and g++ are compiler-drivers of the GNU Compiler Collection (which was once upon a time just the GNU C Compiler).Even though they automatically determine which backends (cc1 cc1plus ...) to call depending on the file-type, unless overridden with -x language, they have some differences.The probably most important difference in their defaults is which libraries they link against automatically.According to GCC's online documentation link options and how g++ is invoked, g++ is equivalent to gcc -xc++ -lstdc++ -shared-libgcc (the 1st is a compiler option, the 2nd two are linker options). This can be checked by running both with the -v option (it displays the backend toolchain commands being run).
GCC: GNU Compiler Collection
- Referrers to all the different languages that are supported by the GNU compiler.
gcc: GNU C Compiler
g++: GNU C++ Compiler
The main differences:
- gcc will compile: *.c , *.cpp files as C and C++ respectively.
- g++ will compile: *.c , *.cpp files but they will all be treated as C++ files.
- Also if you use g++ to link the object files it automatically links in the std C++ libraries (gcc does not do this).
- gcc compiling C files has fewer predefined macros(预定义宏命令).
- gcc compiling *.cpp and g++ compiling *.c/*.cpp files has a few extra macros.
C和C++常见误区以及问题整理的更多相关文章
- NODE.JS学习的常见误区及四大名著
NODE.JS学习的常见误区及四大名著 前段时间由于不满于社区里很多人对于NODE.JS的种种误解而写了一篇文章名为: NODE.JS之我见:http://www.cnblogs.com/pugang ...
- 绝对定位常见误区:position:absolute相对于谁定位、及当溢出时怎么隐藏
1.绝对定位元素溢出父元素,怎么隐藏问题? 通常,为了让DIV子元素超出部分隐藏,都是在父元素设置overflow:hidden,这样即可防止子元素撑开父元素,使子元素能够溢出隐藏! 但是,对于pos ...
- nginx反向代理跨域基本配置与常见误区
最近公司前后端分离,前端独立提供页面和静态服务很自然的就想到了用nginx去做静态服务器.同时由于跨域了,就想利用nginx的反向代理去处理一下跨域,但是在解决问题的同时,发现网上有些方案的确是存在一 ...
- 【原创】C语言和C++常见误区(一)
本文仅在博客园发布,认准原文地址:https://www.cnblogs.com/jisuanjizhishizatan/p/15414469.html 问题1:int类型占几个字节? 常见误区:占4 ...
- JavaScript的一些常见误区
原文出处: 色拉油的博客 接触JavaScript两年多遇到过各种错误,其中有一些让人防不胜防,原来对JavaScript的误会如此之深,仅以此文总结一下常见的各种想当然的误区. String r ...
- oc常见误区
1.同步请求可以从因特网请求数据,一旦发送同步请求,程序将停止用户交互,直至服务器返回数据完成,才可以进行下一步操作, 2.异步请求不会阻塞主线程,而会建立一个新的线程来操作,用户发出异步请求后,依然 ...
- 也许是关于C#的一些常见误区
写这点东西主要是看到知乎上有人在讨论相关的问题,但是有不少人都在说一些不严谨,甚至是完全错误 但是流传甚广的东西,甚至是一些大神都在说,以下根据我的回答总结. 一个很常见又很低级的误区是:认为引 ...
- Lodop客户端本地角色注册号常见误区
之前写过一篇关于Lodop和c-lodop注册号的区别:LODOP.C-LODOP注册号的区别第一种角色客户端本地打印角色是最常见的角色,最常见的场景,关于c-lodop云打印,它的第一种角色是取代L ...
- Java的常见误区与细节
网上转来的 昨天整整一天,我都都呆在图书里.本打算找一些书学习“正则表达式”,很失望,没找到有这部分的内容的书.发现了一本<Java深入解析>,其中涉及了很多平时没有注意的一些误区,也许开 ...
随机推荐
- 【Git】本地分支
[Git]本地分支 转载:https://www.cnblogs.com/yangchongxing/p/10221382.html 目录 ============================== ...
- 【Java Web开发学习】Spring MVC 使用HTTP信息转换器
[Java Web开发学习]Spring MVC 使用HTTP信息转换器 转载:https://www.cnblogs.com/yangchongxing/p/10186429.html @Respo ...
- python基础实战之猜年龄游戏
目录 一.Python基础实战之猜年龄游戏 给定年龄,用户可以猜三次年龄 年龄猜对,让用户选择两次奖励 用户选择两次奖励后可以退出 age = 18 # 答案 count = 0 # 游戏次数控制 p ...
- 《Java基础知识》Java数据类型以及变量的定义
Java 是一种强类型的语言,声明变量时必须指明数据类型.变量(variable)的值占据一定的内存空间.不同类型的变量占据不同的大小. Java中共有8种基本数据类型,包括4 种整型.2 种浮点型. ...
- python基础知识第四篇(元组)
元组 list列表 li[11,22,33,44]列表和元组的区别:元素不可被修改,不可被增加或者删除(一级元素),列表则相反 tuple元组 tu=(111,222,333,444) 支持索引取值 ...
- go 1.13编译遇到xxx/go.mod malformed record data 问题
背景: 公司在做自己的发布平台,需要自动化编译go 工程,大部分开发使用的都是go 1.12 版本 由于go mod的机制,有很多包需要代理才能进行下载,而自动化编译频繁的进行代理切换就很麻烦. 所以 ...
- JS---封装缓动(变速)动画函数---增加任意多个属性&增加回调函数
封装缓动(变速)动画函数---增加任意多个属性&增加回调函数 回掉函数fn,在所有元素到达目的位置后,判断是否传入一个函数,有就调用 if(fn){fn()}; 这样一次点击,产生多个动画 & ...
- IntelliJ IDEA 安装、配置和使用Lombok插件
Lombok 可用来帮助开发人员消除 Java 的重复代码,尤其是对于简单的 Java 对象(POJO),比如说getter/setter/toString等方法的编写.它通过注解实现这一目的.官网: ...
- 13-Node.js学习笔记-MongoDB
数据库相关概念 在一个数据库软件最终可以包含多个数据仓库,在每个数据仓库中可以包含多个数据集合,每个数据集合中可以包含多条文档(具体的数据) database: 数据库,mongoDB数据库软件中可以 ...
- global、nonlocal关键字
一:global:在函数内部引用/声明全局变量 在自定义函数时,有时候需要引用函数外的一些全局变量,如果不需要修改全局变量的内容,则可以直接引用,像下面这样: c = 999 def func(): ...