C语言指针的初始化和赋值

1、指针的初始化指针初始化时,“=”的右操作数必须为内存中数据的地址,不可以是变量,也不可以直接用整型地址值(但是int*p=0;除外,该语句表示指针为空)。此时,*p只是表示定义的是个指针变量,并没有间接取值的意思。例如:inta=25;int*ptr=&a;intb[10];int*point=b;  int*p=&b[0];

大家好,又见面了,我是你们的朋友全栈君。

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即是一个指向指针的指针,下图表示了这些对象:

                          C语言指针的初始化和赋值

i的地址为108,pi的内容就是i的地址,而pi的地址为104,ppi的内容即是pi的地址。对ppi解引用照常会得到ppi所指的对象,所获得的对象是指向int型变量的指针pi。想要真正地访问到i.,必须对ppi进行两次解引用,如下面代码所示:

printf(“%d”, i );

printf(“%d”, *pi );

printf(“%d”, **ppi );

以上三条语句的输出均为5000。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/125959.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 备份集中的数据库备份与现有数据库不同 3154错误

    备份集中的数据库备份与现有数据库不同 3154错误本文转自【https://www.cnblogs.com/worfdream/articles/2174785.html】

  • mmse评估量表_MMSE评估评分指导[通俗易懂]

    简易智能精神状态检查量表(MMSE)操作说明I、定向力(最高分:10分)1、每答对一题得1分星期几?几号?几月?什么季节?哪一年?2、每答对一题得1分省?市?区或县?什么地方?第几层楼?II、记忆力(最高分:3分)告诉被测试者您将问几个问题来检查他的记忆,然后清楚、缓慢的说出3个相互无关的东西的名称(大约1秒钟说1个),说完所有的3个名称后,要求被测试者重复它们。被测试者的得分取决于他们首次重复的…

  • ping和tracert都是利用_tracert超时

    ping和tracert都是利用_tracert超时windows中的tracert使用的icmp,linux中使用的traceroute是udp报文和icmp返回(??)windows为例:tracert用法一般直接使用tracerthostname[ip]即可tracertbaidu.comtracert39.156.69.79需要快速完成命令可以不将地址解析成主机名并设置超时时间tracert-d-w200baidu.com第一列是条数,第2-4是每次返回的时延(每个地址会请求三…

  • echarts的grid属性详解

    echarts的grid属性详解grid配置项:图标离容器的距离show:是否显示直角坐标系网格———–值:true?falseleft:图表离容器左侧的距离—————–值:number?百分比top:图表离容器顶部的距离—————–值:number?百分比right:图表离容器右侧的距离—————值:number?百分比bottom:图表离容器底部的距离————值:number?百分比backgroundColor:网格背景色—

  • pycharm激活码2021年3月最新在线激活[通俗易懂]

    pycharm激活码2021年3月最新在线激活,https://javaforall.cn/100143.html。详细ieda激活码不妨到全栈程序员必看教程网一起来了解一下吧!

  • web前端开发面试中常见的算法题(JS)

    web前端开发面试中常见的算法题(JS)前言最近在准备秋招,做过了大大小小的公司的面试题,发现除了基础知识外,算法还是挺重要的。特意整理了一些常见的算法题,添加了自己的理解并实现。除此之外,建议大家还可以刷刷《剑指offer》(但我还没刷完?,任重道远呐)。此外,左神在牛客网上也有算法课程,听了基础班的感觉还不错,起码让我这个算法小白也能快速地理解了很多问题,知识付费的时代,这个真的是良心课程了。就我个人而言的话,平时为了解决一…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号