C++程序设计(一)
1. 函数指针
- 程序运行期间,每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址(也称“入口地址”)。我们可以将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。然后通过指针变量指向该函数。这种指向函数的指针变量称为“函数指针”。
- 定义形式:
类型名(*指针变量名)(参数类型1,参数类型2,...)
- 可以用一个原型匹配的函数的名字给一个函数指针赋值;
调用时: 函数指针名(实参表)
#include <stdio.h> void PrintMin(int a, int b) { if (a < b) printf("%d", a); else printf("%d", b); } int main() { void(*pf)(int, int); , y = ; pf = PrintMin; pf(x, y); ; } - 指针函数的作用:以C语言快速排序库函数为例
void qsort(void* base, int nelem, unsigned int width, int(*pfCompare)(const void*, const void*))
该函数可以对任意类型数组进行排序。
而对一个数组进行排序,需要知道:
1)数组起始地址
2)数组元素的个数
3)每个元素的大小
4)元素谁在前谁在后的规则
pfCompare:函数指针,它指向一个“比较函数”。该比较函数应为以下形式:int 函数名(const void*elem1, const void* elem2);
比较函数是程序员自己编写的:

实例:下面的程序,功能是调用qsort库函数,将一个unsigned int数组按个位数从小到大进行排序。比如8,23,15三个数,按个位数从小到大排序,就应该是23,15,8#include<iostream> using namespace std; int MyCompare(const void* elem1, const void* elem2) { unsigned int *p1, *p2; p1 = (unsigned int *)elem1; p2 = (unsigned int *)elem2; ) - (*p2 % ); } #define NUM 5 int main() { unsigned , , , , }; qsort(an, NUM, sizeof(unsigned int), MyCompare); ; i < NUM; i++) { cout << an[i] << " "; } ; }
2. 命令行参数
int main(int argc, char* argv[])
{
......
}
argc: 代表启动程序时,命令行参数的个数。C/C++语言规定,可执行程序程序本身的文件名,也算一个命令行参数,因此,argc的值至少是1。
argv: 指针数组,其中的每个元素都是一个char* 类型的指针,该指针指向一个字符串,这个字符串里就存放着命令行参数。
例如,argv[0]指向的字符串就是第一个命令行参数,即可执行程序的文件名,argv[1]指向第二个命令行参数,argv[2]指向第三个命令行参数……。
3. 位运算
位运算:用于对整数类型(int,char, long 等)变量中的某一位(bit),或者若干位进行操作。比如:
1) 判断某一位是否为1
2) 只改变其中某一位,而保持其他位都不变
C/C++语言提供了六种位运算符来进行位运算操作:
& 按位与(双目) | 按位或(双目) ^ 按位异或(双目) ~ 按位取反(单目) << 左移(双目) >> 右移(双目)
- 按位与“&”
通常用来将某变量中的某些位清0且同时保留其他位不变。也可以用来获取某变量中的某一位。
例如,如果需要将int型变量n的低8位全置成0,而其余位不变,则可以执行:n = n & 0xffffff00;
如何判断一个int型变量n的第7位(从右往左,从0开始数)是否是1 ?
只需看表达式 “n & 0x80”的值是否等于0x80即可。 - 按位或“|”
按位或运算通常用来将某变量中的某些位置1且保留其他位不变。
例如,如果需要将int型变量n的低8位全置成1,而其余位不变,则可以执行:
n |= 0xff;
- 按位异或“^”
只有对应的两个二进位不相同时,结果的对应二进制位才是1,否则为0。
按位异或运算通常用来将某变量中的某些位取反,且保留其他位不变。
例如,如果需要将int型变量n的低8位取反,而其余位不变,则可以执行:n ^= 0xff;
异或运算的特点是:
如果 a^b = c, 那么就有 c^b = a 以及 c^a = b. - 按位非“~”
按位非运算符“~”是单目运算符。其功能是将操作数中的二进制位0变成1,1变成0。
- 左移运算符“<<”
a << b
将a各二进位全部左移b位后得到的值。左移时,高位丢弃,低位补0。a 的值不因运算而改变。
实际上,左移1位,就等于是乘以2,左移n位,就等于是乘以$2^n$。而左移操作比乘法操作快得多。
- 右移运算符“>>”
a >> b
将a各二进位全部右移b位后得到的值。右移时,移出最右边的位就被丢弃。 a 的值不因运算而改变。
实际上,右移n位,就相当于左操作数除以$2^n$,并且将结果往小里取整。#include "stdio.h" using namespace std; int main() { ; ; unsigned short n3 = 0xffe0; ; n1 = n1 >> ; n2 >>= ; n3 >>= ; c >>= ; printf("n1=%d, n2=%x, n3=%x, c=%x", n1, n2, n3, c); ; }// 输出结果是:n1=3,n2=fffffffe,n3=ffe,c=1
思考题:有两个int型的变量a和n(0 <= n <= 31),要求写一个表达式,使该表达式的值和a的第n位相同。
(a >> n) &
4. 引用
下面的写法定义了一个引用,并将其初始化为引用某个变量。
类型名 & 引用名 = 某变量名 ; int &r = n;// r引用了变量n,r的类型是 int &
某个变量的引用,等价于这个变量,相当于该变量的一个别名。
注意:
1) 定义引用时一定要将其初始化成引用某个变量
2)初始化后,它就一直引用该变量,不会再引用其他变量了
3)引用只能引用变量,不能引用常量或表达式
例子:
// 交换两个数
void swap( int &a, int &b)
{
int tmp;
tmp = a; a = b; b = tmp;
}
int n1, n2;
swap(n1,n2) ; // n1,n2的值被交换
// 引用作为返回值
;
int & SetValue() {return n; }
int main()
{
SetValue() = ;
cout << n;
;
} //输出:40
常引用:定义引用时,前面加const关键字,即为“常引用”
; const int &r = n;
r的类型是 const int &, 不能通过常引用去修改其引用的内容
; const int & r = n; r = ; //编译错 n = ; // 没问题


5. 常量
- 定义常量
; const double Pi = 3.14; const char *SCHOOL_NAME = "Pekong University";
- 定义常量指针
// 不可以通过常量指针修改其指向的内容 int m, n; const int *p = &n; *p = ; // 编译出错 n = ; // ok p = &m; // ok, 常量指针的指向可以变化
// 不能把常量指针赋值给非常量指针,反过来可以 const int* p1; int* p2; p1 = p2; //ok p2 = p1; //error p2 = (int* ) p1; //ok,强制类型转换
// 函数参数为常量指针时,可避免函数内部不小心改变参数指针所指地方的内容 void MyPrintf( const char * p ) { strcpy( p,"this"); //编译出错 printf("%s",p); //ok } - 定义常引用
// 不能通过常引用修改其引用的变量 intn; const int& r = n; r = ; //error n = ; //ok
- 常量指针和指针常量
* (指针)和 const(常量) 谁在前先读谁 ;*象征着地址,const象征着内容;谁在前面谁就不允许改变。
; ; ; int const *p1 = &b;//const 在前,定义为常量指针 int *const p2 = &c;//*在前,定义为指针常量
常量指针p1:指向的地址可以变,但内容不可以通过p1重新赋值,内容的改变只能通过修改地址指向后变换。
p1 = &a是正确的,但 *p1 = a是错误的。
指针常量p2:指向的地址不可以重新赋值,但内容可以改变,必须初始化,地址跟随一生。
p2= &a是错误的,而*p2 = a 是正确的。
6. 动态内存分配
- 分配一个变量
T *P = new T;
T是任意类型名,P是类型为T *的指针。
动态分配出一片大小为sizeof(T)字节的内存空间,并且将该内存空间的起始地址赋值给P。比如:int* pn; pn= new int; * pn= ;
- 分配一个数组
T* P = new T[N];
T是任意类型名,P是类型为T *的指针,N 是要分配的数组元素的个数,可以是整型表达式。
动态分配出一片大小为sizeof(T*N)字节的内存空间,并且将该内存空间的起始地址赋值给P。比如:int* pn; inti= ; pn= ]; pn[] = ; pn[] = ; //编译没问题。运行时导致数组越界
- 用delete运算符释放动态分配的内存
用“new”动态分配的内存空间,一定要用“delete”运算符进行释放。
int* p = new int; * p = ; delete p; delete p;//导致异常,一片空间不能被delete多次
用“delete”释放动态分配的数组,要加“[]”
]; p[] = ; delete [ ] p;
7. 内联函数inline
函数调用是有时间开销的。如果函数本身只有几条语句,执行非常快,而且函数被反复执行很多次,相比之下调用函数所产生的这个开销就会显得比较大。
为了减少函数调用的开销,引入了内联函数机制。编译器处理对内联函数的调用语句时,是将整个函数的代码插入到调用语句处,而不会产生调用函数的语句。
inline intMax(inta,intb)
{
if( a > b) return a;
return b;
}
在声明时就实现的函数自动成为内联函数。
内联函数的实现写在了源文件中并且在这个源文件以外的文本文件中调用了此内联函数,那么编译可以通过,但是链接器会报“无法解析的外部符号”的错误。
8. 函数重载
一个或多个函数,名字相同,然而参数个数或参数类型不相同,这叫做函数的重载。

9. 函数的缺省参数
C++中,定义函数的时候可以让最右边的连续若干个参数有缺省值,那么调用函数的时候,若相应位置不写参数,参数就是缺省值。
void func( intx1, intx2 = 2, intx3 = 3) { }
func( ) ; //等效于func(10,2,3)
func(,) ; //等效于func(10,8,3)
func(, , ) ; //不行,只能最右边的连续若干个参数缺省
函数参数可缺省的目的在于提高程序的可扩充性。
即如果某个写好的函数要添加新的参数,而原先那些调用该函数的语句,未必需要使用新增的参数,那么为了避免对原先那些函数调用语句的修改,就可以使用缺省参数。
C++程序设计(一)的更多相关文章
- HTML5 程序设计 - 使用HTML5 Canvas API
请你跟着本篇示例代码实现每个示例,30分钟后,你会高喊:“HTML5 Canvas?!在哥面前,那都不是事儿!” 呵呵.不要被滚动条吓到,很多都是代码和图片.我没有分开写,不过上面给大家提供了目录,方 ...
- 解析大型.NET ERP系统 单据标准(新增,修改,删除,复制,打印)功能程序设计
ERP系统的单据具备标准的功能,这里的单据可翻译为Bill,Document,Entry,具备相似的工具条操作界面.通过设计可复用的基类,子类只需要继承基类窗体即可完成单据功能的程序设计.先看标准的销 ...
- java基础学习03(java基础程序设计)
java基础程序设计 一.完成的目标 1. 掌握java中的数据类型划分 2. 8种基本数据类型的使用及数据类型转换 3. 位运算.运算符.表达式 4. 判断.循环语句的使用 5. break和con ...
- CWMP开源代码研究5——CWMP程序设计思想
声明:本文涉及的开源程序代码学习和研究,严禁用于商业目的. 如有任何问题,欢迎和我交流.(企鹅号:408797506) 本文介绍自己用过的ACS,其中包括开源版(提供下载包)和商业版(仅提供安装包下载 ...
- 《JavaScript高级程序设计(第3版)》笔记-序
很少看书,不喜欢看书,主要是上学时总坐不住,没有多大定性,一本书可以两天看完,随便翻翻,也可以丢在角落里几个月不去动一下. 上次碰到了<JavaScript高级程序设计(第3版)>感觉真的 ...
- 《JavaScript高级程序设计(第3版)》阅读总结记录第一章之JavaScript简介
前言: 为什么会想到把<JavaScript 高级程序设计(第 3 版)>总结记录呢,之前写过一篇博客,研究的轮播效果,后来又去看了<JavaScript 高级程序设计(第3版)&g ...
- 【实战Java高并发程序设计 7】让线程之间互相帮助--SynchronousQueue的实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计6】挑战无锁算法:无锁的Vector实现
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计 5】让普通变量也享受原子操作
[实战Java高并发程序设计 1]Java中的指针:Unsafe类 [实战Java高并发程序设计 2]无锁的对象引用:AtomicReference [实战Java高并发程序设计 3]带有时间戳的对象 ...
- 【实战Java高并发程序设计 4】数组也能无锁:AtomicIntegerArray
除了提供基本数据类型外,JDK还为我们准备了数组等复合结构.当前可用的原子数组有:AtomicIntegerArray.AtomicLongArray和AtomicReferenceArray,分别表 ...
随机推荐
- 【Oracle】使用Oracle的v$sql视图查看近段时间执行的SQL语句
SELECT * FROM v$sql ORDER BY first_load_time DESC;
- 【Linux程序设计】之进程控制&守护进程
这个系列的博客贴的都是我大二的时候学习Linux系统高级编程时的一些实验程序,都挺简单的. 实验题目:Linux环境下的进程控制 实验目的:熟悉并掌握Linux环境下进程的相关函数的应用:守护进程的概 ...
- gulp顺序执行任务
gulp的任务的执行是异步的. 所以,当我写完一系列的任务,准备一股脑地执行. # gulp.task('prod', ['clean', 'compass', 'image', 'style', ' ...
- Android 插件开发,做成动态加载
为什么需要插件开发: 相信你对Android方法数不能超过65K的限制应该有所耳闻,随着应用程序功能不断的丰富,总有一天你会遇到一个异常: Conversion to Dalvik format fa ...
- 新提交审核app保留检查更新入口将被拒绝(读取App Store 版本号的)
3月起要求关闭所有App内的检查更新功能,苹果App Store将向用户自动提示更新,新版本提交审核版本如果保留检查更新入口,审核时,将被拒绝. 以上拒绝的方案: 读取App Store的版本号. 替 ...
- [WP8.1UI控件编程]Windows Phone自定义布局规则
3.2 自定义布局规则 上一节介绍了Windows Phone的系统布局面板和布局系统的相关原理,那么系统的布局面板并不一定会满足所有的你想要实现的布局规律,如果有一些特殊的布局规律,系统的布局面板是 ...
- 【POJ】3648 Wedding
http://poj.org/problem?id=3648 题意:n对人(编号0-n-1,'w'表示第一个人,'h'表示第二个人),每对两个,人坐在桌子两侧.满足:1.每对人中的两个人不能坐在同一侧 ...
- GO语言练习:map基本用法
1.代码 2.运行 1.代码 文件:map.go package main import "fmt" type PersionInfo struct{ ID string Name ...
- NodeJS优缺点及适用场景讨论
概述:NodeJS宣称其目标是“旨在提供一种简单的构建可伸缩网络程序的方法”,那么它的出现是为了解决什么问题呢,它有什么优缺点以及它适用于什么场景呢? 本文就个人使用经验对这些问题进行探讨. 一. N ...
- poi excel导入
poi.jar包 import java.io.File;import java.io.FileInputStream;import java.io.IOException; import org.a ...