函数重载
使用同一函数名定义多个函数,但必须参数个数不同或类型不同(比如说<int>或<double>的a,b比大小)
int min(int a, int b,int c) {
if (a>b)a=b;
if(a>c)a=C;
return a;
}
long long min(long long a,long long b, 1ong long c) {
//与上面那个函数的差别是参数的类型不同
if (a>b)a=b;
if (a>C)a=C;
return a;
double min(double a, double b) {
//这个函数与以上的差别是只有2个参数
if (a-b>(1e-5) )a=b;
return a;
}
函数模板
建立通用函数
template<typename T>
T min (T a, T b, T c) {
}
sizeof和strlen的区别
(1) strlen()是函数,在运行时才能计算。参数必须是字符型指针( char*), 且必须是
以'\0'结尾的。当数组名作为参数传人时,实际上数组已经退化为指针了。它的功能是返回
字符串的长度。
(2) sizeof() 是运算符,而不是一个函数,在编译时就计算好了,用于计算数据空间的字节数。因此,sizeof 不能用来返回动态分配的内存空间的大小。sizeof 常用于返回类型和静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系。
char a[10] = "hello"
sizeof(a) 10
strlen(a) 5
数组与指针
int *p;
int a[10];
p = a 等价于 p = &a[0]
可以通过 *(p + i) 或者 *(a + i) 访问 a[i]
- 数组指针/行指针
int (*p)[n] p是一个指向一位数组的步长为n的行指针
int a[3][4];
int (*p)[4]; 该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; 将该二维数组的首地址赋给p,也就是a[0]或&a[0] [0]
P++; 该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1] []
所以数组指针也称指向一维数组的指针,亦称行指针。
- 指针数组
int *p[n]
p[0] = &a;
int *p[3]
int a[3][4]
for (unsigned int i = 0; i < 4; ++i) {
p[i] = a[i];
}
刚开始我对p[i] = a[i]表示困惑.为什么左侧是一个指针的值右侧也是一个值,
(在我看来右侧应该为一个地址),然后发现a是二维数组,a[i]表示行数组的首地址
表示a[i][j]
*(*(p[i]) + j)
p[i][j]
*(*(p + i) + j)
(*(p + i))[j]
函数指针
#include<iostream>
using namespace std;
int Mmin(int x, int y) {
if (x<y) return X;
return y ;
}
int Mmax(int X, int y) {
if(x>y) return X;
return Y ;
}
int main() {
int (*f)(int x, int y);
int a=10,b=20;
f=Mmin;
//把Mmin函数的入口地址赋给f
cout << (*f) (a,b)<<endl;
f=Mmax;
//把Mmax函数的入口地址赋给f
cout << (*f) (a,b)<<endl ; ;
return 0;
}
注意(*f)的括号
共用体
使用union关键字定义.在一个共用体里定义多种不同的数据类型,这些数据共享一段内存,所有的数据成员具有相同的起始地址
union StateMachine
{
char character;
int number;
char *str;
double exp;
};
一个union 只配置一个足够大的空间以来容纳最大长度的数据成员
-
使用Union判断系统是大端还是小端
int a = 0x01 00 00 04
大端模式(高地址对应低字节)
小端模式(高地址对应高字节)
高地址与低地址
高字节与低字节
如int a=16777220,化为十六进制是0x01 00 00 04则04属于低字节,01属于高字节(就像单片机里常说的高八位和低八位)
union Test
{
/* data */
short s;
char c[sizeof(short)];
};
int main() {
Test tst;
tst.s = 0x0102;
if (tst.c[0] == 0x02 && tst.c[1] == 0x01) {
cout << "Little endian." << endl;
}
else if (tst.c[0] == 0x01 && tst.c[1] == 0x02) {
cout << "Big endian." << endl;
}
else {
cout << "unknown." << endl;
}
}
16进制的一位表示两个字节有什么问题?
用 2 Bytes的short存储0x0102 2 Bytes * 4 = 8 Bytes不会溢出吗?
2 * 4前面那个 2 是16进制有16 ÷ 8(位1字节) = 2(字节),后面的 4 指的是有 4 位,合起来就需要8个字节
- 这样的思路是错误的
通过位表示的数不是线性增长而是指数增长的
最后一位是2 ^ 4,表示4 bit,0x0102需要的内存应该为
4 bit * 4 = 16 bit = 2 Bytes
参考资料
https://blog.csdn.net/oqqhutu12345678/article/details/82823890
https://www.cnblogs.com/fightformylife/p/4160247.html
枚举
enum 枚举类型名 {枚举常量表列};
枚举相当于定义了一种新的类型,这种类型下的值只有枚举常量表列里的值.
enum weekday{ sun, mou, tue, wed, thu, fri, sat};
enum weekday a, b, c;
a = sun;
强制类型转换,因为2不是枚举元素
a = {enum weekday} 2;
共用体内存占用
union A{
int a[5] ;
char b;
double C;
};
sizeof(A) 24
sizeof(int) * 5 = 20 不为sizeof(double) 8 的倍数
预处理
宏定义
#define PI 3.1415926
注意误用
#define N 2+9
N * N == 2+9*2+9
带参数的宏定义误用
#define area(x) x*x
area(2+2) == 2+2*2+2
#define area(x) (x)*(x)
area(2+2)/area(2+2) == (2+2)*(2+2)/(2+2)*(2+2)
所以应该按如下定义
#define area(x) ((x)*(x))
条件编译
#define _DEBUG_
#ifdef 标志符 倘若宏定义了此标志符,则进行程序段1,否则进行程序段2
程序段1
#else
程序段2
#endif
extern "C"块的应用
#ifdef __cplusplus
extern "c" {
#endif
程序段
#ifdef __cplusplus
}
#endif
C语言无法区分重载函数的不同,在C/C++混合编程的环境下,extern "C" 告诉C++编译器这段代码按C标准编译