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,分别表 ...
随机推荐
- Moscow Pre-Finals Workshop 2016. National Taiwan U Selection
A. As Easy As Possible 每个点往右贪心找最近的点,可以得到一棵树,然后倍增查询即可. 时间复杂度$O((n+m)\log n)$. #include <bits/stdc+ ...
- Leetcode Reverse Words in a String
Given an input string, reverse the string word by word. For example,Given s = "the sky is blue& ...
- YSLOW
什么是YSlow? YSlow是Yahoo发布的一款基于FireFox的插件. 如何安装YSlow? 安装YSlow必须首先先安装 Firebug,然后下载YSlow,再对其安装. YSlow有什么用 ...
- [题解+总结]NOIP动态规划大合集
1.前言 NOIP2003-2014动态规划题目大合集,有简单的也有难的(对于我这种动态规划盲当然存在难的),今天就把这些东西归纳一下,做一个比较全面的总结,方便对动态规划有一个更深的理解. 2.NO ...
- HDU 4722 Good Numbers(DP)
题目链接 脑子有点乱,有的地方写错了,尚大婶鄙视了... 来个模版的. #include <iostream> #include <cstdio> #include <c ...
- CSS3两个动画顺序衔接播放
问题描述: 第一个动画先播放,播放完成后,第二个动画紧接着播放. 解决办法: 1. 将第二个的延迟时间(animation-delay) 设置成第一个的持续时间( animation-duration ...
- border-radius 圆角半径
CSS3属性之一:border-radius 语法: border-radius : none | <length>{1,4} [ / <length>{1,4} ]? 相关属 ...
- 类:String,Math,DateTime,Random随机数,异常保护
String类: 练习: Math类: Random随机数: DateTime类: 异常保护: 练习: 1. 2. 3.方法一: 方法二: 4.人机大战石头剪刀布 5. //请输入你想输入的数字 // ...
- 用一段JS代码来比较各浏览器的极限内存与运算速度
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- Pl/Sql 导入dmp文件时窗口一闪而过
做如下设置: 点击“导入”,ok