C语⾔指针的初始化和赋值
1、指针的初始化
指针初始化时,“=”的右操作数必须为内存中数据的地址,不能够是变量,也不能够直接⽤整型地址值(可是int*p=0;除外,该语句表⽰指针为空)。此时,*p仅仅是表⽰定义的是个指针变量,并没有间接取值的意思。
⽐如:
int a = 25;
int *ptr = &a;
int b[10];
int *point = b;
int *p = &b[0];
假设:int  *p;
*p = 7;
则编译器(vs2008)会提⽰The variable 'p' is being used without being initialized.即使⽤了未初始化的变量p。
由于p是指向7所在的地址,*p = 7给p所指向的内存赋值,p没有赋值,所以p所指向的内存位置是随机的,没有初始化的。
int k;字符常量怎么表示
int *p;
p = &k;  //给p赋值
*p = 7; //给p所指向的内存赋值,即k= 7
2、指针的赋值
int *p;
int a;
int b[1];
p = &a;
p = b;
指针的赋值,“=”的左操作数能够是*p,也能够是p。
当“=”的左操作数是*p时,改变的是p所指向的地址存放的数据;
当“=”的左操作数是p时,改变的是p所指向的地址。
数组的变量名b表⽰该数组的⾸地址,因此p=b;也是正确的
同类型的指针赋值:
int val1 = 18,val2 = 19;
int *p1,*p2;
p1 = &val1;
p2 = &val2;
p1 = p2;  //注意啦,p1指向了val2,⽽没有指向val1
备注:字符串与指针的初始化和赋值
初始化:
char *cp = "abcdefg"; //这个初始化过程,是将指针cp指向字符串的⾸地址,⽽并⾮传递字符串的值。由于,在C语⾔⾥⾯,没有总体处理⼀个字符串的机制
赋值:
cp = "abcdefg";
*cp=”abcdefg” ;//错误!字符串常量传递的是它的⾸地址,不能够通过*cp改动该字符串的值,由于该字符串为常量,⽽它仅仅是简单的将指针指向该字符串常量
3、指针常量
在C语⾔中没有⼀种内建(built-in)的⽅法去表⽰指针常量,所以当我们使⽤它的时候通常先写成整型
常量的形式,然后再通过强制类型转换把它转换成对应的类型,如:int * , double * , char *等。所以后⾯所看到的的做法是不⾏的: int *p = 0x12345678 ; 正确的⽅式应为:int *p = (int *) 0x12345678; 要注意指针中仅仅能存放地址,不能将⼀个⾮0值整型常量表达式或者其它⾮地址类型的数据赋给⼀个指针,原因就在此。在⼤多数计算机中,内存地址确实是以⽆符号整型数来表⽰的,并且多以16进制表⽰,但我们在C语⾔中不能⽤整型数去表⽰地址,仅仅能⽤指针常量来表⽰,由于它是被⽤来赋给⼀个指针的。
对于这个赋值问题还能够换⼀个⾓度去理解,在C语⾔中,使⽤赋值操作符时,赋值操作符左边和右边的表达式类型应该是同样的,假设不是,赋值操作符将试图把右边表达式的值转换为左边的类型。所以假设写出int *p = 0x12345678 ; 这条语句编译器会报错:'=' : cannot convert from ' const int ' to ' int * ' ,由于赋值操作符左边和右边的表达式的类型应该同样,⽽0x12345678是int型常量,p是⼀个指向int型的指针,两者类型不同,所以正确的⽅式是:int *p = (int *) 0x12345678 ;
4、指针初始化补充
ANSI C定义了零指针常量的概念:⼀个具有0值的整形常量表达式,或者此类表达式被强制转换为void *类型,则称为空指针常量,它能够⽤来初始化或赋给不论什么类型的指针。也就是说,我们能够将0、0L、'/0'、2–2、0*5以及(void *)0赋给⼀个不论什么类型的指针,此后这个指针就成为⼀个空指针,由系统保证空指针不指向不论什么对象或函数。
ANSI C还定义了⼀个宏NULL,⽤来表⽰空指针常量。⼤多数C语⾔的实现中NULL是採⽤后⾯这样的⽅式定义的:#define  NULL  ((void *)0)。
对指针进⾏初始化时经常使⽤的有下⾯⼏种⽅式:
1.採⽤NULL或空指针常量,如:int *p = NULL;或 char *p = 2-2; 或float *p = 0;
2.取⼀个对象的地址然后赋给⼀个指针,如:int i = 3;  int *ip = &i;
3.将⼀个指针常量赋给⼀个指针,如:long *p = (long *)0xfffffff0;
4.将⼀个T类型数组的名字赋给⼀个同样类型的指针,如:char ary[100]; char *cp = ary;
5.将⼀个指针的地址赋给⼀个指针,如:int i = 3;  int *ip = &i;int **pp = &ip;
6.将⼀个字符串常量赋给⼀个字符指针,如:char *cp = “abcdefg”;
对指针进⾏初始化或赋值的实质是将⼀个地址或同类型(或相兼容的类型)的指针赋给它,⽽⽆论这个地址是怎么取得的。要注意的是:对于⼀个不确定要指向何种类型的指针,在定义它之后最好把它初始化为NULL,并在解引⽤这个指针时对它进⾏检验,防⽌解引⽤空指针。另外,为程序中不论什么新创建的变量提供⼀个合法的初始值是⼀个好习惯,它能够帮你避免⼀些不必要的⿇烦。
5、void *型指针
ANSI C定义了⼀种void *型指针,表⽰定义⼀个指针,但不指定它指向何种类型的数据。void *型指针作为⼀种通⽤的指针,能够和其他不论什么类型的指针(函数指针除外)相互转化⽽不须要类型强制转换,但不能对它进⾏解引⽤及下标操作。C语⾔中的malloc函数的返回值就是⼀个void *型指针,我们能够把它直接赋给⼀个其他类型的指针,但从安全的编程风格⾓度以及兼容性上讲,不妨将返回的指针强制转换为所需的类型,另外,malloc在⽆法满⾜请求时会通过返回⼀个空指针来作为“内存分配失败”的信号,所以要注意返回值指针的判空。
6、指向指针的指针
在指针初始化的第5种⽅式中提到了⽤⼀个指针的地址来初始化⼀个指针。回顾⼀下上⼀讲的内容:指针是⼀种变量,它也有⾃⼰的地址,所以它本⾝也是可⽤指针指向的对象。我们能够将指针的地址存放在还有⼀个指针中,如:
int i = 5000;
int *pi = &i;
int **ppi = π
此时的ppi即是⼀个指向指针的指针,下图表⽰了这些对象:
i的地址为108,pi的内容就是i的地址,⽽pi的地址为104,ppi的内容即是pi的地址。对ppi解引⽤照常会得到ppi所指的对象,所获得的对象是指向int型变量的指针pi。想要真正地訪问到i.,必须对ppi进⾏两次解引⽤,如以下代码所看到的:
printf("%d", i );
printf("%d", *pi );
printf("%d", **ppi );
以上三条语句的输出均为5000。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。