第1章 C++编程常用技术

函数重载

使用同一函数名定义多个函数,但必须参数个数不同或类型不同(比如说<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标准编译

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。