1.什么是指针
2.使用指针来操作基础数据类型
3.使用指针来操作字符串
4.使用指针来操作字符串
5.使用指针来操作结构体
6.函数中的指针
1.什么是指针
我在看视频学习C的过程中,看到
李明杰老师说,学习C语言,没学会指针,就相当于没学过C语言。这句话我很赞同,指针是C语言的一大特色,功能十分强大,一定好好好学会。
那么什么是指针呢?
按我的理解:一般变量在内存中声明后都有一个变量名来对应,使用该变量名即可查看修改该变量,但同时,也可以通过变量的地址来查看修改该变量,而指针就是用来保存该变量的地址的。
2.使用指针来操作基础数据类型
C语言的指针是用来指向各个变量的地址的,虽然C语言有多种数据类型,但这些类型的地址格式都是一致的,因此指向这些类型的指针都是四个字节大小(以win7
32位系统为例)。
如下是C语言的数据类型图:
基础数据类型的指针定义方法如下,其中 * 是得到地址对应的变量,
& 是得到变量的地址:
char c = ‘a’;
char *pc = &c;
int a = 1;
int *pa = &a;
以此类推。。。
使用基础数据类型的指针方法如下:
char c = ‘a’;
char * pc =
&c;//让指针指向同一基础类型的变量
*pc = ‘b’;
printf(“c=%c,*pc=%c\n”,c,*pc);
输出结果:c=b,*pc=b
使用注意:
1.
声明方式可以char * pc = &c;或者 char *pc;
pc=&c;
但是不可以 char *pc; *pc=&c;
2.同一种类型的指针只能指向相同类型的变量。
3.不可以把地址直接赋值给指针变量:
char * pc;
pc = 1000;//错误写法,不能直接赋值地址。
3.使用指针来操作字符串
C语言中,没有String
类型,字符串可以有2种表示方式:
1. char * pname = “xiaohong”,
2. char name[] = “xiaohong”;
第一种方式就是采用指针方式来实现的,这2种方式有如下差别:
1. sizeof(pname)结果是
4,sizeof(name)
结果是9,因为对指针求sizeof()得到的只会是指针的字节数,永远都是4。而对数组用sizeof()则得到的数组的字节数。
2. 使用指针指向的字符串无法被修改值,只能读取,不能使用*(p+1)=’x’的方式修改值,会报错。
使用数组存储的字符串可以修改字符串的字符,如 name[1]=’x’。
4.使用指针来操作数组
定义一个数组并赋值:
int ages[] = {10,3,1,99,0,8}
可以使用指针指向这个数组:
int *page;
指向方之一:
page =
ages;//指向数组名
指向方式二:
page =
&ages[0];//指向数组首个元素
通过指针操作数组元素:
读取:printf(“%d\n”,*(page+1));
修改:*(page+1)=99; printf(“%d\n”,*(page+1));
注意:使用指针指向数组中的不同元素时 *(p+1) 中加1
指的是向后移动一个元素的位置,而非指针地址移动一个字节!
5.使用指针来操作结构体
结构体如下:
structstudent{
intid;
char*pname;
intscore;
};
可以直接定义结构体变量,也可以使用指针操作结构体
struct student std,*pstd;
pstd =
&std;//指向结构体变量
变量操作结构体内容:
std.id = 1;
std.name = “xiaohong”;
std.score = 90;
指针操作结构体内容:
pstd->id =
2;//指针可以采用-> 的形式访问成员变量
(*pstd).name =
“xiaoming”;//指针也可以采用
. 的方式访问成员变量。
pstd->score = 60;
注意:指针指向结构体变量时,只能指向结构体变量的名字,不能指向结构体中的成员变量。
6.函数中的指针
指针在函数中的用途很广泛,其中最常用的就是解决了函数参数传递时基础类型参数是值传递的问题。
如:
#include
int * chuanzhi(int i,int *j){
i= 100;
*j= 100;
}
void main(){
inti = 0;
intj = 0;
int* jj = NULL;
jj=
chuanzhi(i,&j);//比较值传递和指针传递的不同。
printf("i=%d,j=%d,jj=%d\n",i,j,*jj);
}
输出结果:
以上的例子显示了值传递与地址传递的不同,同时显示了函数也能返回指针类型的值。
注意:
1.除了基本类型是值传递外,如果在函数中传递类似结构体、数组、字符串等变量的名字也是属于指针传递。
总结:如上列出的是平时使用较多的关于指针的知识,C语言中的指针博大精深,还有很多用法,例如指向函数的指针,指向指针的指针等等。好好学习C中的指针对于将来的学习大有裨益。
对全局变量和局部变量的作用
1.全局变量和局部变量的差别
2.加上static
、 extern后分别对全局变量、局部变量、函数的影响。
变量的作用域小结:
变量的作用域可分为全局变量和局部变量
1.全局变量
a.定义:在函数外面定义的变量。
b.作用范围:从变量定义哪一行开始,到本文件的结尾。
c.生命周期:从变量定义哪一行开始得到分配的存储空间,直到程序运行结束了,内存空间才被回收。
2.局部变量
a.定义:在函数(代码块)中定义的变量。
b,作用范围:从变量定义的哪一行开始,到该代码块的结束。
c.生命周期:从变量定义的哪一行开始得到分配的空间,直到该代码块结束,内存空间被回收。
如上全局变量和局部变量概念一般很好理解,就不举例子了。下面重点要讲解C中的static
、extern关键字分别对全局变量、局部变量、函数的影响。
需要注意的是,作为原本学习java的程序员,习惯了public、protected、friendly、private等等作用范围的修饰符,而C中没有这里,却有
static 、 extern
的关键字,理解清楚这2个关键字对于C中变量的作用范围的影响很重要。
1.全局变量搭配static后,可分为2种
a外部变量:定义的变量能被本文件和外部文件访问的变量。(默认的全局变量就是外部变量)
b内部变量:定义的变量只能被本件访问,不能被其他文件访问。(使用static修饰)
如:
static int a; 定义的全局变量只能在本文件中使用。
int a ; 定义的全局变量默认就是外部变量。
加上关键字 extern int a; 意思就是声明了一个外部变量。
2.局部变量搭配static后,可分为2种
a不加static修饰,函数或者代码块中的变量在函数或者代码块执行完毕后就直接回收销毁了。每次执行都会重新分配内存,每次都会销毁。
b加上static修饰,函数或者代码块中的变量在函数或者代码块执行第一次初始化时分配内存后,就算函数或者代码块执行完了,该变量也不会被回收销毁,直到程序结束static变量才会被回收。
局部变量使用static的例子:
#include
voidshow();
voidmain()
{
show();
show();
show();
}
voidshow(){
inta=0;
staticb=0;
printf("a=%d,b=%d\n",a++,b++);
}
运行结果:
函数的作用域小结:
对于函数而言,C中没有public、protected、friendly、private的修饰符,只有static、extern的修饰符。因此,重点要关注这2个修饰符对函数的影响。
函数搭配static后,可分为2种
1.外部函数:
定义的函数能被本文件和其他文件访问,默认情况下所有函数都是外部函数。
2.内部函数:
定义的函数只能被本文件访问,外部文件无法访问。
例子:
//定义一个外部函数
//方法一:
voidshow(
)//默认就是extern的形式。{
}
//方法二:externvoidshow( )
{
}
// 声明一个外部函数
// 方法一:
voidshow();默认就是extern形式
// 方法二:
externvoidshow();
//定义一个内部函数
static void show( )//此时该函数就不能被外部文件访问了。{
}
//声明一个内部函数
static void show();