c++Note-1

c++笔记

  • 对函数的引用其实就是对函数返回值的引用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    #include<stdio.h>

    #include<iostream.h>

    double d=1;
    int n=2; //定义全局变量d和n



    double& f1() { printf("f1();\t"); return d;} //函数调用f1()等价于变量d

    int& f2() { printf("f2();\t"); return n; } //函数调用f2()是变量n的替身

    void main(void)

    { /*vc6.0上程序交互运行输出结果:*/

    cout<<f1()<<"___"<<f2()<<endl; /* f2(); f1(); 1__2 */

    cin>>f1()>>f2(); /* f2(); f1(); 3 4( */

    cout<<d<<"___"<<n<<endl; /* 3__4 */

    scanf("%lf %d",&f1(),&f2()); /* f2(); f1(); 5 6( */

    printf("%f%s%d\n",d,"__",n); /* 5.000000__6 */

    }
  • exit()

作者:pansz
链接:https://www.zhihu.com/question/20808023/answer/16250818
来源:知乎
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

C 语言的设计之初就是为 Unix
系统设计的,而这个系统是『很多程序互相配合』搭配成一个系统。每个运行着的程序都是进程,而进程就会有父进程,父进程通常是直接启动你的进程,父进程死亡的进程会被
init 收养,其父进程变为 init,而 init 的父进程是进程 0,进程 0 则是系统启动时启动的第一个进程。exit()
里面的参数,是传递给其父进程的。对父进程来说,你的进程仿佛是一个函数,而函数可以有返回值。所以回答第一个问题:exit()
的参数,是给自己的父进程使用的。通常一个程序的父进程可能是任何进程,因此我们无法预期我们的父进程是否规定必须要有这个返回值,那么我们应当提供这个返回值,以保证不同的父进程的需求得到满足。一个典型的例子是
make,Makefile 对于一个 target 下面有多条顺序执行的语句,而 make 作为父进程,会检查每个语句的返回值是否为 0 ,遇到任何一个非
0 值,都会停止当前 rule 的执行。而我们知道,make 实际上可以执行任何命令任何程序,因而任何被 make
调用的程序必须有正确的返回值。另外一个问题,为什么要使用 exit() 函数?答:是历史原因,虽然现在大多数平台下,直接在 main() 函数里面
return 可以退出程序。但是在某些平台下,在 main() 函数里面 return
会导致程序永远不退出(因为代码已经执行完毕,程序却还没有收到要退出的指令)。换句话说,为了兼容性考虑,在特定的平台下,程序最后一行必须使用 exit()
才能正常退出,这是 exit() 存在的重要价值。

  • exit()参数

exit退出程序,里面的参数表示退出的状态。 一般情况下用exit(0)表示正常退出 用exit(1)或者exit(-1)表示不正常退出
但其实退出参数的具体值由程序员自己控制的

  • 动态创建二维数组

C++中用new动态创建二维数组的格式一般是这样:

1
TYPE (*p)[N] = new TYPE [][N]

其中,TYPE是某种类型,N是二维数组的列数。采用这种格式,列数必须指出,而行数无需指定。在这里,p的类型是TYPE*[N],即是指向一个有N列元素数组的指针。
还有一种方法,可以不指定数组的列数:

1
2
3
4
5
6
7
8
9
10
11
int **p;

p = new int*[10]; //注意,int*[10]表示一个有10个元素的指针数组

for (int i = 0; i != 10; ++i)

{

p[i] = new int[5];

}

这里是将p作为一个指向指针的指针,它指向一个包含10个元素的指针数组,并且每个元素指向一个有5个元素的数组,这样就构建了一个10行5列的数组。

当数组使用完毕,释放空间的代码是:

1
2
3
4
5
6
7
8
9
for(int i = 0; i != 5; i++)

{

delete[] p[i];

}

delete[] p;

处理二维数组,可以用降维或是二维法。
降维法是用一位数组来接受二维数组,将二维元素的首地址&a[0][0]作为参数,传递给函数,函数用int *接受。
二维法就直接用二维数组来接受,但是需要指定列数。

  • 使用字元阵列来储存格式字串
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#include "stdafx.h"
#include<stdio.h>

int main(int argc, char* argv[])

{

char format[] = { 'T','h','e',' ','s','c','o',

'r','e',' ','i','s',' ','%',

'd','\n','\0' };

int score; /* 成绩 */

score = 100; /* 设定成绩内容 */

printf("使用正常的格式化字符串\n"); /* 印出结果 */

printf("The score is %d\n",score);

printf("使用字符数组的格式化字符串\n");

printf(format,score);

return 0;

}
  • 遍历字符串数组简单方式

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    char *strcat(char *str1,char *str2)

    {

    int i,j;

    for ( i = 0; str1[i] != '\0'; i++); /* 找字串str1结束 */

    for ( j = 0; str2[j] != '\0'; j++) /* 拷贝字串内容 */

    str1[i+j] = str2[j];

    str1[i+j] = '\0'; /* 设定字串结束 */

    return str1;

    }
  • 整型的每一种都有无符号和有符号两种类型(浮点float和双精度double总是带符号的),在默认情况下声明的整型变量都是有符号的类型(字符char有点特别),如果需声明无符

char,short ,int ,long,long long,unsigned long long数据范围

速查表:

类型 范围
char -128 ~ +127 (1 Byte)
short -32767 ~ + 32768 (2 Bytes)
unsigned short 0 ~ 65535 (2 Bytes)
int -2147483648 ~ +2147483647 (4 Bytes)
unsigned int 0 ~ 4294967295 (4 Bytes)
long == int
long long -9223372036854775808 ~ +9223372036854775807 (8 Bytes)
double 1.7 * 10^308 (8 Bytes)
unsigned int 0~4294967295
long long 的最大值:9223372036854775807
long long 的最小值:-9223372036854775808
unsigned long long 的最大值:18446744073709551615
__int64 的最大值:9223372036854775807
__int64 的最小值:-9223372036854775808
unsigned __int64 的最大值:18446744073709551615

详细教程:

符号属性 长度属性 基本型 所占位数 取值范围 输入符举例 输出符举例
char 8 -2^7 ~ 2^7-1 %c %c 、 %d 、 %u
signed char 8 -2^7 ~ 2^7-1 %c %c 、 %d 、 %u
unsigned – char 8 0 ~ 2^8-1 %c %c 、 %d 、 %u
[signed] short [int] 16 -2^15 ~ 2^15-1 %hd
unsigned short [int] 16 0 ~ 2^16-1 %hu 、 %ho 、 %hx
[signed] – int 32 -2^31 ~ 2^31-1 %d
unsigned – [int] 32 0 ~ 2^32-1 %u 、 %o 、 %x
[signed] long [int] 32 -2^31 ~ 2^31-1 %ld
unsigned long [int] 32 0 ~ 2^32-1 %lu 、 %lo 、 %lx
[signed] long long [int] 64 -2^63 ~ 2^63-1 %I64d
unsigned long long [int] 64 0 ~ 2^64-1 %I64u 、 %I64o 、 %I64x
– – float 32 +/- 3.40282e+038 %f 、 %e 、 %g
– – double 64 +/- 1.79769e+308 %lf 、 %le 、 %lg %f 、 %e 、 %g
– long double 96 +/- 1.79769e+308 %Lf 、 %Le 、 %Lg

几点说明:

  1. 注意 ! 表中的每一行,代表一种基本类型。 “[]” 代表可省略。
    例如: char 、 signed char 、 unsigned char 是三种互不相同的类型;
    int 、 short 、 long 也是三种互不相同的类型。

  2. char/signed char/unsigned char 型数据长度为 1 字节;
    char 为有符号型,但与 signed char 是不同的类型。
    注意 ! 并不是所有编译器都这样处理, char 型数据长度不一定为 1 字节, char 也不一定为有符号型。

  3. 将 char/signed char 转换为 int 时,会对最高符号位 1 进行扩展,从而造成运算问题。
    所以 , 如果要处理的数据中存在字节值大于 127 的情况,使用 unsigned char 较为妥当。
    程序中若涉及位运算,也应该使用 unsigned 型变量。

  4. char/signed char/unsigned char 输出时,使用格式符 %c (按字符方式); 或使用 %d 、 %u 、 %x/%X 、 %o ,按整数方式输出; 输入时,应使用 %c ,若使用整数方式

, Dev-C++ 会给出警告,不建议这样使用。

  1. int 的长度,是 16 位还是 32 位,与编译器字长有关。
    16 位编译器(如 TC 使用的编译器)下, int 为 16 位; 32 位编译器(如 VC 使用的编译器 cl.exe )下, int 为 32位。

  2. 整型数据可以使用 %d (有符号 10 进制)、 %o (无符号 8 进制)或 %x/%X (无符号 16 进制)方式输入输出。 而格式符 %u ,表示 unsigned ,即无符号 10 进制方式

  1. 整型前缀 h 表示 short , l 表示 long 。
    输入输出 short/unsigned short 时,不建议直接使用 int 的格式符 %d/%u 等,要加前缀 h 。这个习惯性错误,来源于 TC 。
    TC 下, int 的长度和默认符号属性,都与

short 一致,于是就把这两种类型当成是相同的,都用 int 方式进行输入输出。

  1. 关于 long long 类型的输入输出:
    “%lld” 和 “%llu” 是 Linux 下 gcc/g++ 用于 long long int 类型 (64 bits) 输入输出的格式符。
    而 “%I64d” 和 “%I64u” 则是 Microsoft VC++ 库里用于输入输出 __int64 类型的格式说明。

Dev-C++ 使用的编译器是 Mingw32 , Mingw32 是 x86-win32 gcc 子项目之一,编译器核心还是 linux 下的 gcc 。
进行函数参数类型检查的是在编译阶段, gcc 编译器对格式字符串进行检查,显然它不认得 “%I64d” ,
所以将给出警告 “unknown conversion type character `I’ in format” 。对于 “%lld” 和 “%llu”
, gcc 理所当然地接受了。

Mingw32 在编译期间使用 gcc 的规则检查语法,在连接和运行时使用的却是 Microsoft 库。
这个库里的 printf 和 scanf 函数当然不认识 linux gcc 下 “%lld” 和 “%llu” ,但对 “%I64d” 和 “%I64u”
,它则是 乐意接受,并能正常工作的。

  1. 浮点型数据输入时可使用 %f 、 %e/%E 或 %g/%G , scanf 会根据输入数据形式,自动处理。
    输出时可使用 %f (普通方式)、 %e/%E (指数方式)或 %g/%G (自动选择)。

  2. 浮点参数压栈的规则: float(4 字节 ) 类型扩展成 double(8 字节 ) 入栈。
    所以在输入时,需要区分 float(%f) 与 double(%lf) ,而在输出时,用 %f 即可。
    printf 函数将按照 double 型的规则对压入堆栈的 float( 已扩展成 double) 和 double 型数据进行输出。
    如果在输出时指定 %lf 格式符, gcc/mingw32 编译器将给出一个警告。

  3. Dev-C++(gcc/mingw32) 可以选择 float 的长度,是否与 double 一致。

  4. 前缀 L 表示 long ( double )。
    虽然 long double 比 double 长 4 个字节,但是表示的数值范围却是一样的。
    long double 类型的长度、精度及表示范围与所使用的编译器、操作系统等有关。

  • 求数组长度的简易方法
1
2
long   a[]={1,2,3,4};         // sum(q,n-1)求区间{2,3,4}的和9
const int n=sizeof(a)/ sizeof(*a); // sum(&a[2],n-2) 求区间{3,4}的和7
-------------本文结束感谢您的阅读-------------