数组和字符串

指针的使用

指针的应用场景

1.函数返回多个值时,某些值只能通过指针返回,而传入函数的参数,实际上是需要保存带回的结果的变量

2.函数返回运算的状态,指针返回函数运算的结果

数组作为函数参数

1.数组作为函数参数时可被看作指针,数组变量就是特殊的指针

2.数组变量本身表达地址,可不用&,但是数组的单元表达的是变量,须用&

3.[]运算符也可以对指针做,*也可以对数组做

1
2
p[0]<==>a[0]
*a=25

4.数组变量是const的指针,所以不能被赋值

1
int a[]<==>int * const a

指针与const

指针是const

指针不能指向其他变量

1
2
3
int* const q = &i;
*q = 26; OK
q++; ERROR

所指是const

不能通过指针修改变量

1
2
3
4
const int* p = &i;
*p = 26; ERROR
i =26; OK
p = &j; OK

const指针做函数参数时,函数内定义的非const的参数的值会被转换成const的值

数组与const

const数组表示数组内的单元变量都是const,不能被修改,且只能用如下方式初始化

1
const int a[] = {1,2,3,4,5,6}

const数组作为函数参数时可以保护数组值不被修改

指针运算

给一个指针加1表示要让指针指向下一个变量,指针指向的应是一片连续分配的空间,如数组,否则没有意义

1
2
3
int a[10];
int* p = a;
*(p+1)->a[1];

指针还可以用+, +=, -, -=, —, ++

还可以让两个指针相减,结果为几个sizeof相对应的类型,sizeof(int)为4,结果若是5,就是两个地址相距20个字节

*p++可以先取结果后挪地址,适用于数组的连续操作,运行也更快

0地址

一般写为NULL,NULL表示0地址更通用,0地址不能随便碰,如果给指针赋值0,一旦对该指针修改就会崩溃,

指针的类型转换

void型的指针可以说是不指向什么地方的指针

指针也可以转换类型,下例为q通过p看i,q认为i是void型,i其实还是int型的

1
2
int *p=&i;
void *q=(void*)p;

动态内存分配

变量可以向malloc申请以字节为单位的空间

malloc用到的头文件是#include,返回的结果是void*,需要转换为自己需要的类型,用完还要用free把空间还给内存,换错了会报错,计算机可是认识变量的。。。

1
2
3
a=(int*)malloc(num*sizeof(int));
......
free(a);

以后使用时要把结构先处理好,方便找位置free

字符串操作

putchar与getchar

1
int putchar(int c);

向标准输入写一个字符,返回写了多少个字符,返回-1(EOF)表示写失败,EOF定义在stdio.h内,值为-1

1
int getchar(void);
1
2
3
while((ch=getchar())!=EOF){
......
}

上面的框架可用于多组输入,在没有失败时,程序会等我们下一次输入,如果失败了,就会跳出循环

getchar()读取一个字符后会先putchar(ch),输出到缓冲区,缓冲区接受到回车时会把一系列字符变为一起字符串输出(提高效率),如果没有缓冲区,我们一输入就会输出,word输出就成了wwoorrdd,在输入和输出之间有一个shell帮我们处理缓冲区

字符串数组

1
2
3
4
5
char *a[]={
"Hello"
"World"
"abcdefghijk"
}

字符串数组的每一个单元都是一个指针,指向一个存放字符串的地方,有时可以代替switch case

程序函数

1
int main(int argc,char const *argv[]);

main()括号里其实是有参数的,argv[0]是命令本身,具体以后碰到再说