没有合适的资源?快使用搜索试试~ 我知道了~
C++基础知识梳理
需积分: 15 2 下载量 54 浏览量
2012-06-03
07:46:16
上传
评论 7
收藏 302KB DOCX 举报
温馨提示
试读
11页
一开始学习C/C++的时候会以为,这个语言很严谨,在编码上不容许有任何闪失,不然编译肯定不通过。但其实和后续的C#和java等等语言相比,C/C++的规范还是非常非常宽松的。至少在指针类型各种转换中就能体现出来,让开发人员收益匪浅。但这也严格要求着C/C++程序员,在代码逻辑上面不能犯一点错误。哪怕一个小小的内存溢出,在反复的分配释放中就会造成严重的后果,甚至会导致程序直接崩溃。所以小徐现在在做程序的时候都习惯做内存溢出检测,1个字节的溢出都会导致我强制对之前写过的代码下断点跟踪。
资源详情
资源评论
资源推荐
一开始学习 C/C++的时候会以为,这个语言很严谨,在编码上不容许有任何闪失,不然
编译肯定不通过。但其实和后续的 C#和 java 等等语言相比,C/C++的规范还是非常非
常宽松的。至少在指针类型各种转换中就能体现出来,让开发人员收益匪浅。但这也严格
要求着 C/C++程序员,在代码逻辑上面不能犯一点错误。哪怕一个小小的内存溢出,在
反复的分配释放中就会造成严重的后果,甚至会导致程序直接崩溃。所以小徐现在在做程
序的时候都习惯做内存溢出检测,1 个字节的溢出都会导致我强制对之前写过的代码下断
点跟踪。
C++的数据类型有以下几种:
int 整型
short 短整型
long 长整型
oat 浮点数
double 双精度浮点数
char 字符
在不同的平台上(32/64)上,以上类型的长度有所不同。目前最广泛的还是在 32 位平台上。
在 VC 系列的编译器中为例:
int 4byte
short 2byte
long 4byte
oat 4byte
double 8byte
char 1byte
跟大家说说小徐对这些数据类型的理解。事实上数据类型是一种抽象的概念,我们都知道
不管是什么样的数值什么样的字符,在内存中都是 1 和 0。不同的是存储的方法和呈现的
方法不一样而已,并且我们不需要关心这些在操作平台底层进行的动作,我们只需要把它
们放在表达式里面计算出结果,并把经过送入操作平台让其呈现出来就可以了。
我们可以这么做:
char c = 'A';
int a = (int)c;//或者直接 int a = c;都可以,编译器会对存储方法进行隐式转换
printf("%c",(char)a);
其结果一样会输出字符 A。printf 的第一个参数是输出样式,%c 说明随后的第一个参数是
char 类型的数据,向后读取一个字节即可,然后呈现。我们在屏幕上看到输出的 A,可是
告诉大家其实 char 可以理解为 short short int,即只有一个字节的短短整形。我们也可
以对 char 进行加减乘除等等各种操作。只不过在输出的时候我们告诉操作平台,要将该
整数当做字符输出。
众所周知的 UNICODE 字符,即双字节字符,在 Windows 中定义为 wchar_t,其实它是
一个 unsigned short int,即 2byte 短整型。小徐在学习字符的时候也很困惑,为什么
字符可以用 short 来表示,那 char 又代表了什么?其实他们都是整型而已,只是呈现的
方式和其他的整型不一样。
short a = 65;
wchar_t w = L'A';
wprintf(L"%c %c",a,w);//printf 的宽字符版本
输出的两个字符都是一样的。用 unsigned 和 signed 修饰的数据类型其存储形式是一样
的。所以输出一致。
数组可以认为是一串相同类型的数据,亦称线性空间。指编译器按照定义分配一段定长的
内存空间供数组使用。C/C++对数据下标的访问没有作出限制,只要是整型就可以。但是
在定义数组的时候一定要用常量定义。
int a = 4;
int b[a];
这种定义是不对的。
在用下标访问数组的时候,编译器是默认处理成如下形式的:
定义 int a[5];
a[2]编译器处理成*(a+2)
a 的类型是 int [],a 表示了数组的起始地址,int 类型的长度是 4byte,a+2 的意思就是
从 a 开始向后偏移(2*4)个字节
那么多维数组是怎么处理的呢。
定义 a[2][3];
a[1][2]编译器处理成*(*(a+1)+2)
a 的类型是 int [][2],可以理解成是 int **二维指针。但是和指针略显不同。最里面的
*(a+1)是这么做地址偏移的:对类型 int[][2]进行的地址偏移运算,int [2]的长度是
2*4=8byte,那么 a+1 实际上是在起始地址 a 向后偏移了 8 个字节,在数组矩阵中就是
向下偏移了一行,*(a+1)返回的类型是 int [],然后再进行的偏移计算就和上面的一维数组
相同啦。多维数组依次类推。
下午在群里有人问过处理不定大小的二维矩阵应该怎么办。这个我会在下篇日志在对指针
进行阐述的时候讲到。
字符串是什么呢?字符串就是一串字符。但是字符串并不是字符数组,而是字符数组负责
存储字符串。
char c[] = {'a','b','c','\0','d'};
其中 abc\0 组成的叫做字符串,字符串是以'\0'(值为 0)字符结尾的一串字符。在 printf 输
出的时候会从起始地址向后查找每一个字符并输出,遇到'\0'结束。所有操作字符串的函数
比如 strlen,strcpy,都是以'\0'字符串结束为基准的。而字符串的长度是不计入'\0'的,
所以在用字符数组存储字符串的时候要给'\0'留下空间。
题外话:
int * p;
int a[5];
sizeof(p)是 4byte,因为 32 位的指针是 4 字节的。
sizeof(a)是多少?答案是 4*5 = 20byte,即数组占用的空间大小。这是小徐的残念啊,
面试的时候想都没想就写 5 了。。。what a fucking day!他居然还要我了!谢特。。
程序结构。C/C++的程序结构就这么几种,地球人都知道:if for while switch,及控制
其他们的关键字,构成了程序的逻辑结构。其中我只想讲 for 循环。
for 循环由以下几个部分组成:
for([循环初始化];[循环条件];[一次循环结束后进行的操作])
[循环体]
用 if goto 来表示就是:
[循环初始化]
begin: if([循环条件] == false) goto end;
[循环体]
[一次循环结束后进行的操作]
goto begin;
end:
//.....
[循环体]可以是一条以;结束的语句,也可以是由{}包裹的局部代码。
灵活应用 for 循环会让你的逻辑形式变得非常轻巧,因为你可以在初始化,条件,操作三
个表达式用写各种乱七八糟人神共愤的代码,可以搭配()括号表达式和,逗号表达式最大程
度的发挥 for 循环的潜力哦。
好啦今天先讲这么多,剩下的在下篇日志里面再讲。也许是明天,也许是后天 0 0
初篇里面我说过程序是一门艺术。我看过一本古老的关于设计模式的书,书的开篇就用非
常形象的语言描述程序员的心里。
程序是什么?简单的说,就是一些数据,一些逻辑。它们组合在一起,组合成了上万行功
能各不相同的代码。再往下说,在机器层面,上万亿个 1 和 0 通过不同的组合完成了各式
各样的功能。它们组成了图片,组成了各种视频播放器,组成了浏览器,组成了游戏,组
成了互联网。所以对于程序员来说,编程已经不仅仅是一门艺术,而变成了一种魔力。当
看到自己编写的代码在屏幕呈现出华丽的时候,那种成就感的满足是其他职业所理解不了
的。有很多人说程序员很累很辛苦,青春饭。可是这只是程序员们在工作之余无关紧要的
牢骚。
程序员们,我们都知道彼此的内心,很快乐,很享受,不是么?
与诸君共勉。
函数是个很有趣的东西。通常我们会重复很多次的逻辑或者算法,就会被编入一个函数供
我们调用。就像数学里的函数一样,定义 f(x) = 2*x+1,然后在公式中直接调用 f(2)或
者 f(3.4)就可以了。如何将代码合理的分割成函数以减少代码复杂度和清晰度只是经验之
谈,这也是程序员代码风格的必修课之一。
函数分为两个部分:声明和定义,或是声明和实现。如果要调用一个函数,那么在调用代
码之前一定要在合理的域中声明此函数。换言之,要声明函数的入口地址。
//code
f(2,3);
int f(int 2,int 3)
{
BBBBB //...
}
像这样,在调用 f(2,3)的时候,编译器向上查找,却找不到函数的声明,不知道函数的起
始点在哪里,于是就会报编译时的错误。
剩余10页未读,继续阅读
gkxawy
- 粉丝: 0
- 资源: 11
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功
评论0