指针是一种用于存放另外一个变量地址的变量。ANSIC中用类型void*代替char*作为通用指针的类型。
一个单元可表示一个字符,一对相连的存储单元可表示一个短整数,相邻的四个字节则构成一个长整数
指针由存放一个地址的一组存储单元(通常有两个或四个字节)构成。
取地址运算符&只能用于内存中的对象(变量与数组),它不能对表达式、常量、或者寄存器变量进行操作。
一元运算符*是间接或间接引用运算符,当它应用于指针时,它将访问指针所指向的对象。
一个指针只能指向一个特定类型的对象:每个指针对象也有一确定的数据类型。(例外:指向void类型的指针可转换成指向任何对象类型的指针,但它不能间接引用它自身)
数组下标所能完成的任何运算都可以用指针来实现,指针的运算比数组下标运算的速度快。
”指针加1“的意思是pa+1指向pa所指对象的下一个对象。相应地,pa+i指向pa所指对象之后的第i个元素。
一个类型为数组的变量或表达式的值是该数组第0个元素的地址。故pa=&a[0]
一个用数组和下标实现的表达式可等价地用指针和偏移量来实现。
指针和数组名字之间的区别:指针是变量,数组名字不是变量。
/*strlen :返回字符串S的长度*/
int strlen(char *s)
{
int n;
for(n=0;*s != '\0'; s++)
n++;
return n;
}
引用数组边界之外的对象是非法的。
指针的地址算数运算:如果p是一个指向数组某个元素的指针,那么p++对p进行加一运算使它指向下一个元素,而
p+=i对p进行增量运算使它指向指针p当前所指向的元素之后的第i个元素。
基本的存储分配程序:两个函数(alloc,afree)
第一个函数alloc(n)返回一个指向n个连续字符存储单元的指针,allox函数的调用者可;利用该指针来存储字符序列;
第二个函数afree(p)释放已经分配的存储空间。对afree的调用必须以与调用alloc函数相反的次序进行。
最简单的实现方法:让alloc函数对一个大字符数组allocbuf中的空间进行分配。该数组是alloc和afree
的私有数组。
由于函数alloc和free处理的对象是指针而不是数组下标,其他函数无需知道该数组的名字。所以可以再包含
alloc和free的源文件中将该数组说明为static类型。使得它对外不可见。实际实现时,这个数组最好没有名字,它通过
调用malloc函数或者向操作系统申请一个指向无名存储区的指针来得到。
另外一个需要知道的信息是allocbuf中的空间当前已经使用了多少。使用allocp指向allocbuf数组中下一个空闲单元。
当向alloc申请n个字符的空间时,alloc检查allocbuf数组看有没有足够的剩余空间用于分配。如果有足够的空闲空间,alloc就返回allocp
的当前值(。即自由块的开始位置)。然后将allocp加n使它指向下一个空闲区域。
如果空闲空间不够,则alloc返回0。如果p在allocbuf的边界之内,affree仅将allocp的值设置为p.
#define ALLCOCSIZE 10000
static char allocbuf[ALLOCSIZE];
static char *allocp = allocbuf;
char *alloc(int n)
{
if(allocbuf+ALLOCSIZE-allocp >= n){
allocp += n;
return allocp - n;
} else
return 0;
}
void afree(char * p)
{
if(p >= allocbuf && p < allocbuf + ALLOCSIZE)
allocp = p;
}
//------------------------------------------------------------------------------------------------------------------------------------
static char * allocp - allocbuf;将allocp定义为字符类型指针,并将它初始化为allocbuf的起始地址,该起始地址是程序开始运行时的
下一个空闲位置。
0值的返回表示一个异常事件。
指针和整数不能相互转换,但0例外:常量0可以赋给指针,指针也可以和常量0进行比较。
程序中经常用符号常量NULL代替常量0,常量0是指针的一个特殊值。
1、某些情况下对指针可以进行比较运算:例如指针p和q指向同一数组的成员,那么它们之间可以进行关系比较运算。
任何指针与0进行相等或不等的比较运算都有意义的。但对指向不同数组成员的指针之间的算数或者比较运算,
其执行行为没有定义。(特例:指针的算数运算中可使用一个数组的第一个元素的地址)
2、指针可以与整数进行相加相减运算。
p - n 表示指针p当前所指对象之后的第n个对象的地址。在计算p+n时,n根据p所指对象的大小按比例缩放,而p所指对象的大小决定于p的
说明。例如:一个整数占四个字节的存储空间,那么int对应的n就按4的倍数来计算。
3、指针的算数运算具有一致性:例、如果处理的是比字符类型占据更多存储空间的浮点类型,并且p是一个指向浮点类型的指针
,那么执行p++后p就指向下一个浮点数的地址。所有的指针运算都会自动考虑它所指对象的大小。
有效的指针运算包括:相同类型指针之间的赋值运算;指针值加或减一个整数值的运算;
指向相同数组元素的指针之间的减或比较运算;将指针赋0或指针与0之间的比较运算。所有其它
形式的指针运算均非法。
字符串常量最常见的用处就是用函数变元:
字符串常量可通过一个指向其第一个元素的指针来访问。
char *pmessage;
pmassage = "now is the time";
把一个指向该字符数组的指针赋值给指针变量pmessage,其中并未进行字符串的赋值。只涉及到指针的操作。
C语言中没有提供将一个完整的字符串作为一个整体处理的运算符。
char amessage[] = ""now is the time;
char *pmassage = "now is the time";
amessage是一个足以存放字符串初值和空字符‘\0’的一维数组,可以更改数组中的单个字符,但amessage
是一个不可改变的常量,它总是指向同一存储区。
pmessage是一个指针,其初值指向一个字符串常量,之后它可以被修改指向其他地址,但如果试图修改字符串内容,结果将不确定。
/*strcpy :数组下标版本*/
void strcpy (char *s, char *t)
{
int i;
i = 0;
while(s[i] = t[i] != '\0')
i++;
}
/*strcpy:指针方法版本*/
void strcpy(char *s, char *t)
{
while((*s = *t) != '\0'){
s++;
t++;
}
}
/*strcpy:指针方法*/
void strcpy(char *s, char *t)
{
while((*s++ = *t++) != '\0')
;
}
/*strcpy 指针方法*/
void strcpy(char *s, char *t)
{
while(*s++ = *t++)
;
}
/*strcmp*/
int strcmp (char *s, char *t)
{
int i;
for(i = 0; s[i] == t[i]; i++)
if(s[i] == '\0')
return 0;
return s[i] - t[i];
}
/strcmp:指针方法*/
int strcmp(char *s, char *t)
{
for(; *s == *t; s++, t++)
if(*s == '\0')
return 0;
return *s - *t;
}
指针数组对于二维数组的一个重要优点是数组的每一行可以有不同的长度。
命令行变元:在程序开始执行时将命令行变元或参数传递给程序。
调用主函数时它带有两个变元:第一个变元(习惯上称作argc,用于变元计数)
的值为程序执行时命令行中变元的数目,第二个变元(称为argv,用于变元变量)
是一个指向字符串数组的指针。
argv[0]的值为调用相应程序的命令名,因此argc的值至少为1.如果argc的值为1
,那么命令名后面没有命令行变元。
函数本身不是变量,但是可以定义指向函数的指针,这种指针可以被赋值,
存放于数组之中,传递给函数及作为函数返回值等等。