19、定义一个int类型的指针:
int count = 10;
int *intPtr;
intPtr = &count;
然后就可以引用这个指针:
x = *intPtr;
带着间接寻址运算符*号才是指针的完整表达形式。
20、&号是取出它标示的变量的地址,*号是把它标示的变量的值当做地址去寻找内容。
注意指针名里面存的是地址。所以用&把某个变量的地址读出来之后,应该是赋给指针的变量名,这时候不能有*号;然后指针的变量名里存有了某个变量的地址,这时候给指针变量名加上*号,加上了寻址功能,那么整个(*指针变量名)就是读取到某个变量的地址里面存储的那个值了。
21、但是可以在定义指针的时候同时给它赋值,那么这时候可以写成:
int *intPtr = &count;
正常情况下,如果是分开写,应该遵循这么个原则:有*无&,有&无*。
22、指针的值即是它所指向的那个变量的值,所以在19中,其实*intPtr就是count,count就是*intPtr,是同一个地址存储的内容。
23、指针也可以指向结构,假如有某指针XPtr,某结构变量YStruct,YStruct内有一int元素名为z,通过:
XPtr = &YStruct;
定义了(*XPtr)的值,那么访问YStruct内的值z可以表示为:
(*XPrt).z
由于成员点运算符(.)的优先级比间接寻址运算符(*)高,所以要加上括号。而且这个表达式可以表示为:
XPtr->z
注意不要有空格,同时XPtr前没有*号。
24、如果使用某个指针作为一个函数的参数,那么在调用这个函数的时候,传参传进去的应该是指针的名字里的那个地址,而不应该是整个指针,即是在参数哪里写上指针的名字即可,不用加上星号。比如将19的指针作为某个函数fx(int *ptr)的参数,那么调用方式应该是:
fx( intPtr );
或者:
fx( &count );
传地址进去即可。
25、定义指向数组的指针的时候,不能把指针的类型定义为“数组指针”,而应该把它的类型定义为数组里元素的类型。
26、如果xArr是元素类型为xTpye的数组,而指针xPtr是一个xTpye类型的指针,i和n都是整数常量,则定义数组指针的格式如下:
xType *xPtr;
xPtr = xArr; //这个语句相当于xPtr = &xArr[0];
可以注意到,第二个语句中xArr前不需要加上&号,因为编译器已经把没有加上下标的数组名看做了数组第一个元素的地址。
那么这时候*xPtr就相当于xArr[0],同时还有以下情况:
*(xPtr + i)相当于xArr[i]
xPtr += n相当于在数组内把指针向后移动n位,指向n位后的那个值。
27、如果将txtPtr定位为某类型的指针,并把它指向这个类型的数组中的某个元素,那么:
++txtPtr会指向数组中的后一个字符,
--txPtr会指向数组中的前一个字符。
其实即是地址的加减,地址加1即是后一位,地址减1即是前一位。
28、可以比较两个指针变量,一般用在比较指向同一个数组的两个指针的大小。这个比较其实就是比较两个地址的前后关系。越大越后。
29、使用数组作为函数的参数,在调用这个函数进行传参的时候,传进去的数组的名称即可,不需要任何修饰,就和指针一样。比如将char xArray[ ]作为某个函数fx(char arr[ ])的参数,那么调用方式应该是:
fx( xArray );
这意味着,在调用函数的时候,传递给函数的其实这个数组的指针。
30、其实char类型的数组的数组名称就是一个char类型的指针,指向数组第一个元素。
31、如果使用字符串作为函数的参数来调用函数,实际上传递的是指向该字符串的指针,所以29的函数fx(char arr[ ])可以用一个字符串作为参数。比如:
fx( “So this is.” );
32、在字符串前加@号,其实是创建了一个常量字符串对象。仅仅使用双引号括起来的只是一个C样式字符串,它们不是对象。
33、如果txtPtr是一个char类型的指针,txt[80]是一个char类型的数组,那么:
txtPtr = “Yes this is”; //注意,没有&号
会将txtPtr设为指向这个字符串常量的指针,但是txt=“Yes this is”这一种就不合法了。只有在数组初始化的时候,编译器才允许数组这样赋值:
char txt[80] = “Yes this is”;
34、如下的前缀运算:
j = ++i;
相当于:
++i;
j = i;
前缀会导致i先自增,然后再赋值给j;另一种情况:
j = i++;
相当于:
j = i;
++i;
后缀会导致i先赋值给j,然后才自增。这两种情况要区分。
35、两个相同类型的指针相减,得出的结果它们之间相差的元素个数。
36、函数指针的基本模板:
int (*funcPtr) (void); //表示指针funcPtr指向一个返回值为int并且没有参数的函数
int func(void); //声明函数
funcPtr = func; //可以加上&,没有也可
主要注意的是:
(1)、第一个语句中*号和指针两边的括号不能省略,不然编译器会理解为这是一个返回值类型为(int *)的函数;
(2)、在执行第三句之前,第二句必须得先声明;
(3)、第三句在func前可以加&,不加效果也没影响;
(4)、函数指针一般是用在将它作为参数传给其他函数,或者用在存储了很多函数的数组中(分派表),由于函数本身不能保存在数组元素中,所以代替地将函数指针存储进去。
37、main函数的参数列表(int argc, char *argv[])中,argc是从命令行输入的参数个数,argv是一个字符指针数组,包含了arvc个字符指针。
数组argv中最后一个指针atgv[argc]规定为空。
38、几个事实:
(1)、对象实际上是结构,结构中的成员是实例变量。结构中继承的成员之一是名为isa的保护成员,它是用来确定对象所属的类的;
(2)、对象变量实际上是指针,比如定义Fraction类的对象变量的时候:
Fraction *myFrac;
实际上是定义了一个名为myFrac的指针变量,这个指针的类型是Fraction;
(3)、方法就是函数。编译器会根据类名和方法名的组合给每一个函数分配一个单独的名称;
(4)、id类型是通用指针类型,所以id类型存储的其实是这个对象的地址。由于对象总是携带着isa成员,所以最终编译器可以通过isa成员判断这个对象所属的类。
39、typedef和#define的区别:
(1)、typedef只是为了增加程序可读性而为标识符另起的新名称,所以功能还是完全相同的,只是换了个名字。而#define原本只是为了定义常量,这个关键字执行的只是简单的查找替换;
(2)、typedef是编译过程的一部分,而#define作为预处理过程,在编译前就已经替换完成了;