1 int i; //定义一个int型的变量

  2 int *p; //定义一个指向int的指针

  3 int a[n]; //定义一个数组

  4 int *p[n]; //定义一个指针数组

  5 int (*p)[n]; //定义一个数组指针

  6 int f(); //声明一个返回值为int的函数

  7 int *p(); //声明一个返回值为int*的函数

  8 int (*p)(); //定义一个函数指针

  9 int **p; //定义一个指向int的指针的指针

  &引用运算符:

  1.引用只是变量的别名,而不是指向变量的指针(区别于取址运算符"&")不占内存空间,对变量引用的改变其相应的变量也会改变。

  2.不能对引用使用指针间接运算符“*”进行复引用操作

  3.引用必须在声明时初始化 int &c = count;(c是count的别名)

  指针的算术操作

  和整数的加法,减法,自身的增量、减量

  指针增量后指向下一个与指针基类同型的元素,增减单位是所指类型的长度。

  同类型直接赋值,异类型要进行转换。

  强制转换:可以把表达式结果硬性转换为指定类型

  char * p;(int *)p 把p强制转换为int型,记住转换过程中要注意两个类型的大小,大转小时可能会有数据丢失(如int到double)

  涉及void *的:

  c 中void *类型可赋值给任何类型的指针,反之亦然

  c++ 中都需要强制转换

  void * 可似为无穷大能接纳任何类型赋值,反之不行int * p =9;void * t= p(正确);p=t(错误)

  const 是“最靠近”为原则

  指向整数常量的指针:const int * p;它所指向的值只读不能被修改 *p = 4(错误),p = 5(正确)

  指向一个整数的常量指针:int * const p;不允许修改指针变量的值,*p = 5 (正确),p = 5 (错误)

  指针优点:

  1.为函数提供修改调用变元的手段;

  2.支持C++动态分配子程序

  3.可以改善某些子程序的效率

  4.为动态数据结构(如二叉树、链表)提供支持

  注:指针为程序引入了一层间接性,可以操控指针而不直接操控对象。

  1.可操控指针内含的地址也可操控指针所指的对象2.指针可能并不指向任何对象,写*pi时,可能会使程序在执行期错误,如寻址到某个对象,则提领操作,不指向任何对象,会出错,所以在提领前先确定它的确指向某对象。

  一个未指向任何对象的指针,内含地址为0,有时称为null指针,assert (p != 0)可检测是否分配成功。也可用if (pi),只有在pi含非零值时,才为true.

  引用和指针的比较(1)引用在创建的同时必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化,可以在定义后面的任何地方重新赋值。

  (2)不存在NULL引用,引用必须与合法的存储单元关联;而指针则可以是NULL.

  (3)引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用;而指针在任何时候都可以改变为指向另一个对象。给引用赋值并不是改变它和原始对象的绑定关系。

  (4)引用的创建和销毁并不会调用类的拷贝构造函数

  (5)在语言层面,引用的用法和对象一样;在二进制层面,引用一般都是通过指针来实现的,只不过编译器帮我们完成了转换。

  总的来说:引用既具有指针的效率,又具有变量使用的方便性和直观性。







C++数组速学
1.一维数组的定义与初始化

1.1定义一维数组

int a[3];

该定义表示一个整型数组,共有3个元素,下标分别为[0],[1],[2]。

1.2一维数组初始化

可以用下面几种方式进行初始化。

①在定义数组时分别对数组元素赋初值。

int a[3]={0,1,2};

②只给一部分元素赋值。

int a[3]={0,1};

这表示只给前面两个元素赋初值,后面的元素值默认为0。

③在对全部数组元素赋初值时,可以不指定数组长度。

int a[3]={0,1,2};

可以写成

int a[]={0,1,2};

在第二种写法中,花括号中有3个元素,系统就会据此自动定义a数组的长度为3。但若被定义的数组长度与提供初值的个数不相同,则数组长度不能省略。

2.二维数组的定义与初始化

2.1定义二维数组

int a[3][4];

改定义表示一个3x4(3行4列)的整型数组。可以把该二维数组看作:

|---a[0]:a[0][0],a[0][1],a[0][2],a[0][3]

a |--a[1] :a[1][0],a[1][1],a[1][2],a[1][3]

|--a[2] :a[2][0],a[2][1],a[2][2],a[2][3]

C++中,二维数组种元素排列的顺序是:按行存放,即在内存中先顺序存放第一行的元素,在存放第二行元素,依次往下。

2.2二维数组初始化

可以用下面几种方式进行初始化。

①分行给二维数组赋初值。

int a[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};

②将所有数据写在一个花括号内,按数组排列的顺序对各元素赋初值。

int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

③只对部分元素赋初值。

int a[3][4]={{1},{2},{4}};

1 0 0 0

2 0 0 0

4 0 0 0

int a[3][4]={{1},{0,2},{0,0,4}};

1 0 0 0

0 2 0 0

0 0 4 0

int a[3][4]={{1},{3,2}};

1 0 0 0

3 2 0 0

0 0 0 0

int a[3][4]={{1},{},{9}};

1 0 0 0

0 0 0 0

9 0 0 0

④如果对全部元素赋初值,则定义数组时对第一维长度可以不指定,但第二维长度必须指定。

int a[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};

可以写成

int a[][4]={0,1,2,3,4,5,6,7,8,9,10,11};

在定义时也可以对部分元素赋初值而省略第一维的长度,但应分行赋初值。

int a[][4]={{0,0,1},{},{0,9}};

0 0 1 0

0 0 0 0

0 9 0 0

3.用数组名作函数参数

3.1一维数组名作函数参数

数组名代表数组首元素的地址,并不代表数组中的全部元素。因此用数组名作函数参数时,是将实参数组首元素的地址传递给形参。形参可以是数组名,也可以是指针变量,它们用来接收实参传来的地址。如果形参是数组名,它代表的是形参数组首元素的地址。

在调用函数时,将实参数组首元素的地址传递给形参数组名。这样,实参数组和形参数组共占同一段内存单元。形参数组中各元素的值如果发生变化就意味着实参数组元素的值发生变化。这一点区别于变量作函数参数的情况。在变量作函数参数时,只能将实参变量的值传递给形参变量,在调用函数过程中如果改变了形参的值,对实参没有影响,即实参的值不因形参的值的改变而改变。

实际上,声明形参数组并不意味着真正建立一个包含若干元素的数组,在调用函数时也不对它分配内存单元,只是用array[]这样的形式表示array是一维数组名,以接受实参传来的地址。因此array[]中方括号内的数值并无实际作用,编译系统对一维数组方括号内的内容不予处理。函数定义中的形参数组可以写元素个数,也可以不写。

以下几种写法都是正确的。

void select_sort(int array[10],int n){…}

void select_sort(int array[],int n){…}

void select_sort(int array[5],int n){…}

C++实际上只把形参数组名作为一个指针变量来处理,用来接收从实参传过来的地址。

3.2二维数组名作函数参数

如果是二维数组名作为实参和形参,在对形参数组声明时,必须指定第二维(列)的大小,且应与实参的第二维的大小相同。第一维的大小可以指定,也可以不指定。

下面两种写法都是正确的。

void max_value(int array[3][4]{…}

void max_value(int array[][4]){…}

不能把第二维的大小省略是因为,二维数组是由若干个一维数组组成的,在内存中数组是按行存放的,因此在定义二维数组时必须指定列数。假如一个二维数组有12个元素,可以是2x6,3x4,4x3,等不同的形式,如果指定了列数有4,则只有一种形式3x4。

形参数组的列(第二维)定义必须与实参数组的列(第二维)定义相同,但行(第一维)定义可以不同。

//实参

int array[3][4]

//形参

int array[3][4]

int array[8][4]

4.字符数组

4.1字符数组的定义与初始化

可以这样定义:

char c[10];

c[0]='I';c[1]=' ';c[2]='a';c[3]='m';c[4]=' ';

c[5]='h';c[6]='a';c[7]='p';c[8]='p';c[9]='y';

也可以:

char c1[10]={'I',' ','a','m',' ','h','a','p','p','y'};

如果花括号提供的初始个数(即字符个数)大于数组长度,则按语法错误处理。如果初值个数小于数组长度,则只将这些字符赋给数组中前面的元素,其余的元素自动定为空字符(即’’)。

如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。如,

char c1[]={'I',' ','a','m',' ','h','a','p','p','y'};

数组c的长度自动设定为10。

4.2字符数组的赋值与引用

只能对字符数组的元素赋值,而不能用赋值语句对整个数组赋值。

char c[5];

c={'C','H','I','N','A'};//error

c[0]='C';c[1]='H';c[2]='I';c[3]='N';c[4]='A';//ok

如果已定义了a和b是具有相同类型和长度的数组,且b数组已被初始化,

a=b;//error

a[0]=b[0];//ok

4.3 字符串和字符串结束标志

对于,

char str[12]={'I',' ','a','m',' ','h','a','p','p','y'};

字符串str只有10个字符,所以系统会对字符数组最后两位自动填补’’,这是“字符串结束标志”。在上面的数组中,第11个字符为’’,就表明字符串的有效字符为其前面的10个字符。也就是说,遇到字符’’就表示字符串就此结束。

对一个字符串常量,系统会自动在所有字符的后面加一个’’作为结束符。例如字符串”I am happy”共有10个字符,但内存中它共占11个字节,最后一个字节’’是系统自动加上的。

在程序中往往依靠检测’’的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。

下面用字符串常量来初始化字符数组,

char str[]={"I am happy"};

也可以

char str[]="I am happy";

注意字符串的两端是用双引号而不是单引号。这里str数组的长度为11,因为系统在最后自动加上一个’’。上面的初始化等价于

char str[]={'I',' ','a','m',' ','h','a','p','p','y', ''};

而不等价于

char str[]={'I',' ','a','m',' ','h','a','p','p','y'};

需要说明的是,字符数组并不要求它的最后一个字符为’’。下面的写法是合法的(最后没有’’),

char str[5]={'C','H','I','N','A'};

char str[]={'C','H','I','N','A'};

是否加’’是选择性的,而C++编译系统会对字符串常量自动加一个’’,因此为了使处理方法一致,便于测定字符串的实际长度,推荐人为加上’’,即

char str[6]={'C','H','I','N','A',''};

char str[6]={'C','H','I','N','A'};

char str[]={'C','H','I','N','A',''};

5.字符串数组

string name[5];//定义一个字符串数组,包含个字符串元素

string name[5]={"Jeff","Tom","Ada","Mike","Bill"};//定义一个字符串数组并初始化

每个字符串元素中只包含字符串本身的字符而不包括’’;

在本例中,就是把字符串”Jeff”的地址存放在name[0], 把字符串”Tom”的地址存放在name[1], 把字符串”Ada”的地址存放在name[2], 把字符串”Mike”的地址存放在name[3], 把字符串”Bill”的地址存放在name[4]。

posted on 2010-05-29 11:52  蓝牙  阅读(908)  评论(0编辑  收藏  举报