课程地址: https://www.coursera.org/learn/cpp-chengxu-sheji
文章目录
-
- 1.1 函数指针
-
- 基本概念
- 从qsort库函数看函数指针的作用
- 练习题
- 1.2 命令行参数
-
- 练习
- 2.1 位运算
- 2.2 引用
-
- 练习
- 3.1 const关键字
-
- const定义常量
- const定义指针
- 3.2 动态内存分配
-
- 练习
- 3.3 内联函数,函数重载,参数缺省
-
- 函数重载
- 参数缺省
- 4.1 面向对象的设计方法
1.1 函数指针
基本概念
程序在运行期间,每一个函数都会占用一片连续的内存空间。每一个函数都会有一个起始地址。 那在C语言和C++语言里面,我们可以把一个函数的起始地址赋值给一个指针, 那这样的一个指针就称为函数指针。
- 函数指针定义
例:类型名 (* 指针变量名)(参数类型1,参数类型2)
note:* 指针变量名一定要加括号int (*pf)(int char)
-
函数指针使用
可以用一个原型匹配的函数名字为一个函数指针赋值。
通过函数指针调用指向函数:
note:原型匹配值返回值类型,参数类型和个数都要相同函数指针名(实参表)
从qsort库函数看函数指针的作用
-
qsort函数声明
qsort函数是能对任意类型的数组进行排序的c库函数
void qsort(void *base, int nelem, unsigned int width,
int (* pfCompare)(const void *,const void *));
/*****/
base: 数组的首元素地址
nelem:数组元素的个数
width:每个元素的大小(字节)
pfCompare: 排序规则
-
排序规则编写
格式:
int 比较函数名(const void * elem1,const void * elem2);
如果认为elem1应该排在elem2的前面,函数的返回值就应该是一个负的整数。
如果认为elem1和elem2哪个排在前面都行,那么比较函数的返回值就应该是0。
如果认为elem1应该排在elem2的后面, 比较函数的返回值就应该是一个正整数。
简而言之:
不交换返回负数,交换返回正数,随意返回0
#include <stdio.h>
#include <stdlib.h>
//让数组元素按照个位数大小排序,(从小到大)
int MyCompare(const void * elem1,const void *elem2)
{
unsigned int *p1,*p2;
p1 = (unsigned int *)elem1;
p2 = (unsigned int *)elem2;
return (*p1 % 10)-(*p2 % 10);
}
int main()
{
unsigned int an[5] = {12,34,4,51,3};
qsort(an,5,sizeof(unsigned int),MyCompare);
for(int i=0;i<5;i++)
printf("%d ", an[i]);
}
//运行结果
51 12 3 4 34
总结:函数指针作为参数,可以传递更多的信息。
练习题
答案 B

答案:C
1.2 命令行参数
我们在命令行执行程序的时候是可以带参数的,那么我们的程序怎么接收参数呢?
-
传参数
直接在可执行程序后面输入参数就行,两个参数之间用空格隔开
例:a.exe程序输入help和in、out三个参数
note:如果要输入带有空格的参数,则需要加双引号a.exe help in out
a.exe "hello world"
- 接受参数
int main(int argc, char * argv[])
argc: 代表程序启动的时,命令行参数的个数。c/c++规定,可执行程序本身也是一个参数。因此,argc的值至少是1。
argv: 指针数组,其中的每一个元素都指向一个参数(字符串)。
#include <stdio.h>
int main(int argc, char * argv[])
{
printf("the numbers of param: %d \n",argc);
for(int i=0; i<argc; i++)
printf(" %s ",argv[i]);
}
执行:
a.exe help in out
输出:
the numbers of param: 4
a.exe help in out
note: 在程序启动的时候,操作系统就已经把用户在命令行敲进去的参数,存在了某个地方了。操作系统在调用程序的时候再把命令行参数传进去。
练习
答案:A
2.1 位运算
嵌入式里面需要对寄存器进行操作时,用的比较多
c/c++提供了六种位运算符
TYPE | 描述 |
---|---|
& | 按位与(双目) |
| | 按位或(双目) |
^ | 按位异或(双目) |
~ | 按位非(单目) |
<< | 左移(双目) |
>> | 右移(双目) |
-
按位与&
功能:
1.将变量中的某一位清0,同时其他位保持不变;
2.获取变量中的某一位;
例:将int型变量n的低八位全部清零,其他位不变:
例:判断int型变量的第3位(从右往左,从0开始数)是否为1?n = n & 0xffffff00;
if (n & 0x08 == 0x08)
因为0与任何数与都是0,1与任何数与都是任何数。所以我们要将特定数取出就用1去与就行。
当然如果要将具体位取出还要依赖于移位操作
-
按位或 |
功能:
用来将变量中的某些位置1
-
按位异或 ^
两位相异,结果为1
两位相同,结果为0
1 ^ (任何数) =》 取反
0 ^ (任何数) =》 不变
功能:
1.可以将变量中的某些位取反,而保留其他位不变
2.可以实现最简单的加密和解密
特点:
如果 a^b=c,则 c^b=a 及 a^c=b
, 用此特点可以实现最简单的加密和解密
例:a是要加密的数据,b是密钥。c是加密后的数据。
3.不通过临时变量,交换两个变量的值
这是利用了功能2,以及任何数异或自己等于0,0异或任何数不变,
int a=5,b=8;
a = a^b;
b = a^b;
a = a^b;
printf("%d, %d \n",a,b);
-
左移运算符 <<
左移1位,就是乘以2,左移n位,就是乘以2^n
-
右移运算符 >>
note: 对于有符号的数,右移时候,符号位也会跟着一起移动。在大多数C和C++编译器中处理右移:如果原来的那个符号位为1,那右移的时候左边补充进来的那个高位就都是1, 如果被右移的数符号位是0, 那右移的时候,左边补充出来的那些位就都是0. 大多数编译器都是这么规定的。
右移1位,就是除以2,右移n位,就是除以2^n。
并且最后结果是往小里取整(规律,不是规定)
-25 >> 4 = -2
2.2 引用
类型名 & 引用名 = 某变量名
某个变量的引用,等价与这个变量,相当于这个变量的别名。
note:
1.定义引用时一定要将其初始化成引用某个变量
2.初始化之后,它就一直引用该变量,不会再引用别的变量了。
3.引用只能引用变量,不能引用常量和表达式
- 引用作为函数返回值
int n=4;
int & SetValue() {return n;}
int main()
{
SetValue() = 40;
cout << n;
}
-
常引用
不能通过常引用去修改其引用的内容
int n=100;
const int &i=n;
r = 200; //编译出错
n = 200; //编译正确
-
常引用和非常引用的转换
设T是变量类型,
const T & 和 T & 是不同的类型 !!!
T & 类型的引用或T类型的变量可以用来初始化const T&类型的引用。
const T类型的常变量和const T&类型的引用则不能用来初始化T &类型的引用,除非进行强制类型转换
练习
答案 C
3.1 const关键字
const定义常量
const double pi = 3.1415926;
double const pi = 3.1415926;
这两种定义方式都是一样的含义
在c++里面尽量用const替代#define,const有类型检查。
const定义指针
- 指针本身是不可改变的
指针本身不可以改变char a = 'a'; char *const pContent = &a;
char b = 'b';pContent = &b;
错
但是指向的内容是可以改变的
对*pContent = 'b';
- 指向的内容不可改变 (常量指针)
指向的内容不可通过指针改变const char * pContent; pContent = &a;
*pContent = 'b';
错
但是可以通过变量自身改变
a = 'b';
对
note:不能把常量指针赋值给非常量指针 (可以强制类型转换)
-
const char * const pContent
3.2 动态内存分配
按需分配内存
new的两种用法
note:用new定义出来的数组编译时候不会有越界警告
用delete释放new出来的数组的时候加[]
char *p = new char[10];
delete[] p;
练习
答案B
答案C
3.3 内联函数,函数重载,参数缺省
一般子函数在编译的时候都只会将调用指令编译进去,随之而来的就是参数入栈,压栈,弹栈等工作。inline关键字的作用就是将整个子函数的内容都编译进去。
inline在返回值类型前面
函数重载
一个函数,函数名字相同,参数类型和参数个数不一样就行
note:不能按照返回值类型区分函数重载,
因为就算有返回值的函数在调用的时候也可以不接收返回值
答案D
参数缺省
c++中,在定义函数的时候,可以让最右边的连续多个参数有缺省值。那么在调用函数的时候,若相应的位置不写参数,则对应的参数就是缺省值。
函数参数可缺省的目的在于提高程序的可扩充性。
如:在增加某项功能的时候,需要给函数新增参数,那么原来调用这个函数的代码也要增加参数,这样就就会带来不兼容。有了函数缺省就能将这两种需求结合起来。
答案C
4.1 面向对象的设计方法
结构化程序设计的四大问题:
- 理解难
- 修改难
- 查错难
- 重用难