精华内容
下载资源
问答
  • Hello 大家好欢迎关注编程猎人本人小白一枚一个立志成为分享编程干货博主一,什么是指针?二,指针的注意事项?三,指针与数组四,指针与函数五,指针与堆空间一,什么是指针?C语言中变量是容器,可看作装酒酒杯...

    Hello      大家好

    欢迎关注编程猎人

    本人小白一枚

    一个立志成为分享编程干货的博主efacc8c964076e451e25145f09b67dc7.png

    5e014bffccafc32bf87ae7d5f5c9618c.png

    一,什么是指针?

    二,指针的注意事项?

    三,指针与数组

    四,指针与函数

    五,指针与堆空间

    一,什么是指针?

    C语言中变量是容器,可看作装酒的酒杯,只不过装的不是酒,是各种内存。

    而指针是一种特殊的变量:因为是变量,所以能保存具体值;特殊之处就在于指针保存的值是内存的地址;

    内存地址:计算机中每个存储单元都有编号,这些编号就是内存地址。

    需要清楚的事实:程序中一切元素都存储在内存中,因此可以通过访问地址来使用元素,而指针的作用就是作为一个容器存储地址,对地址的一切操作都要通过指针来完成。

    如何获取具体地址:

    通过取地址操作符——& 来获得。

    &的作用:可以获取变量,数组,函数的地址。

    确定一个具体的地址是通过:确定起始地址+长度来确定

    各种数据类型长度:

    7dbed35bb2fb693a9015797a33af5af1.png

    指针定义语法:type* pointer;

    type 数据类型,决定访问内存的长度;

    注意:指针的类型统一只占4字节或8字节。

    * 指针访问操作符,标志为指针变量。

    pointer 变量名,遵循C语言命名规则。

    int main(){    char* pChar;    int* pInt;    double* pDouble;        return 0;}
    int var=0 ;            //定义变量var初始值为0;int* pvar=NULL ;       //定义pvar的所占地址的开始值为NULL,即0值;pvar = &var;           //把var变量的地址赋值给pvar.*pvar = var;           //把var的值赋值给*pvar.

    归类:var,*pvar为int类型变量;

               pvar,&var为变量地址;

    二,指针的注意事项

    type* 类型的指针只能存储type类型变量的地址;

    禁止不同类型的指针相互赋值;

    通过指针参数:

    ——能够实现函数交换变量的值;

    ——能够从函数中"返回"多个值;而return只能返回一个值;

    三,指针与数组

    在数组中,元素本身就是地址。所以数组名虽然不是指针,但可以看作指针;

    这样的话,数组元素就可以直接对指针赋值,数组名也可以对指针赋值。

    数组名可直接看作一个指针,表示数组中0元素的地址;

    a等价于&a[0]

    不过&a则表示整个数组的地址,虽然值和0元素的地址一样,但意义不同。

    85fa9e0bdfce332f82208ad0a0046047.png

    ——&a代表数组地址,类型为:int(*)[ ] 

    ——a代表数组0号元素地址,类型为:int*

    看得出两者类型不一致,所以不能相互赋值。

    所以定义:

    指向数组的指针:int (*pName)[ ] = &a;

    指向数组0号元素的指针:int* pName = a; 

    当指针指向数组元素时,可以进行指针移动。

    int a[] = {1, 2, 3, 4, 5};int* pa = a;p = p + 1;             //现在p指向了下一个元素。

    指针与字符串:

    字符串其实就是特殊的数组,特殊在于该数组最后元素的值为'\0'。

    字符串常量就是一种char*类型,一种指针类型,存在的地址为全局变量区。

    使用字符串的时候,其实就是在使用char*类型的数据。

    例如用&对"Hello"取地址,结果为"Hello"在全局变量区的起始地址。

    "Hello"可看作一个地址;

    *"Hello"看作从这个地址中取值;

    四,指针与函数

    函数的本质就是内存中的一段代码:

    d039853365ab612983489972c5e0a8dd.png

    函数的类型,函数类型由返回类型和参数类型列表决定:

    4700296a3704e89515d9e090c75880de.png

    函数名就是函数体代码的起始地址;

    通过函数名调用函数,本质为指定具体地址的跳转执行

    因此,可以通过指针,保存函数入口地址;

    函数指针:

    对于函数为type func (type 1,  type 2)格式的

    指向该函数的指针为:type (*pfunc)(type 1,  type 2) = func/NULL;

    值得注意的是,函数指针只是单纯的保存函数的入口地址,所以只能通过函数指针调用目标函数。

    当数组作为参数时:

    当数组作为参数,会退化成为一个指针;

    int demo(int arr[ ],int len) → int demo(int* arr, int len).

    因此,不包含数组实参的长度信息。使用数组名调用时,传递的是0号元素的地址。

    五,指针与堆空间

    各类内存空间不同,用途不同:

    ——全局数据区:存放全局变量,静态变量;

    ——栈空间:存放函数参数,局部变量;

    ——堆空间:用于动态创建变量

    堆空间的本质:

    • 备用的“内存仓库”,以字节为单位预留可用内存。

    • 程序可在需要时申请借内存。(动态借)

    • 借完后需要及时归还。(动态还)

    问:如何从对卡申请借内存,如何归还呢?

    预备知识——void*

    1. void类型时基础类型,对应指针类型为void*

    2. void*为指针类型,其指针变量能够保存地址

    3. 通过void*指针无法获取内存中的数据(无长度信息)

    4. void*保存的内存有起始地址,但没有长度信息。能够保存任意类型的地址,能转换到其它指针类型的变量。

    5. 不可以用void*指针直接获取内存数据,不过void*与其它数据指针可以相互赋值。

    堆空间的使用原则:

    1. 有借有还。

    2. malloc申请内存后,应该判断是否申请成功。

      =NULL,则申请不成功。
      !=NULL,则申请成功。
    3. free负责释放申请到的内存。

    今天的分享到这里就结束了,不知道大家有没有学废呢?学废的朋友可以把“学废了”敲在留言上,或者和笔者讨论哦。

    da572bcc3838842cc3cdc1f8002d4e01.png

    这是笔者的微信公众号,欢迎关注!

    展开全文
  • 一、前言本文介绍C/C++中的指针,分为两个部分:“引子:指针”与“代码演示”,分别介绍指针概要和指针代码实现。二、引子:指针含义:指针是一个变量,其值为另一个变量的地址,是哪个变量的地址呢?是指针所指向...

    一、前言

    本文介绍C/C++中的指针,分为两个部分:“引子:指针”与“代码演示”,分别介绍指针概要和指针代码实现。

    二、引子:指针

    含义:指针是一个变量,其值为另一个变量的地址,是哪个变量的地址呢?是指针所指向变量的地址。

    使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针(写入地址值)、访问指针变量中可用地址的值(读出地址值)。

    三、代码演示

    3.1 定义一个指针变量

    定义指针变量时,要注意一点,比如int *ip,

    8f26ccf6430cf16d11af799cc593a19f.png

    有图,我将"int *" “double *” “float *” “char *” 用方框号框起来,旨在说明它们是一个整体,一起组成类型名,这是一个指针类型名。

    e4f37c2fd3276899cc024b2b82cc8d4b.png

    3.2 把变量地址赋值给指针(写入地址值)

    定义指针变量后,就要给指针变量赋值了,未赋值的指针变量是随机值,这是非常危险的。

    如何给指针变量赋值?

    首先要明白指针变量的值是什么?指针变量的值实际是地址,记住,

    重点,很重要:所有指针变量的值都是地址。所有的指针变量都是为实际变量保存地址的,不同类型的指针变量只是保存不同实际类型变量的指针而已。int * 保存int类型变量地址,double *保存double类型变量地址,float * 保存float类型变量地址,char *保存char类型变量地址,虽然保存着不同类型变量地址,但都是保存地址,都是保存十六进制的内存地址。

    好了开始看代码:

    #include <iostream>
     
    using namespace std;
     
    int main()
    {
       int  *ip;        // 指针变量的声明   接着使用刚才的int *ip,int*类型变量ip.
       int  var = 20;   // 实际变量的声明   因为是int *类型指针变量,所以自然用int类型的实际变量
     
     
       ip = &var;       // 在指针变量中存储 var 的地址
       //这里,注意,同上ip是指针类型变量名,又因为指针类型变量是用来存放十六进制的地址的,
       //所以这里将实际变量var的地址赋值给指针变量ip,
       //注意:实际变量中使用&取到地址   这里&var
     
        return 0;
    }

    3.3 访问指针变量中可用地址的值(读出地址值)

    既然指针变量中存放的是地址,可以直接访问指针变量名输出地址吗?答案是肯定的。

    代码1——直接访问指针变量名输出地址:

    #include <iostream>
     
    using namespace std;
     
    int main()
    {
       int  *ip;        // 指针变量的声明   接着使用刚才的int *ip,int*类型变量ip.
       int  var = 20;   // 实际变量的声明   因为是int *类型指针变量,所以自然用int类型的实际变量
     
     
       ip = &var;       // 在指针变量中存储 var 的地址
       //这里,注意,同上ip是指针类型变量名,又因为指针类型变量是用来存放十六进制的地址的,
       //所以这里将实际变量var的地址赋值给指针变量ip,
       //注意:实际变量中使用&取到地址   这里&var
     
       cout << "输出实际变量值: ";
       cout << var << endl;    //输出实际变量值
     
     
       cout << "输出实际变量地址: ";
       cout << ip << endl;    //输出实际变量地址
       
       return 0;
    }

    输出1:

    输出实际变量值: 20
    输出实际变量地址: 0x6afee8

    所有指针变量中存放的都是地址,但是指针变量在读出的时候不仅可以读出地址,还可以通过地址找到地址所在内容并输出,且看下面代码。

    代码2——"*指针变量名"得到指针所指地址的内容:

    #include <iostream>
     
    using namespace std;
     
    int main()
    {
       int  *ip;        // 指针变量的声明   接着使用刚才的int *ip,int*类型变量ip.
       int  var = 20;   // 实际变量的声明   因为是int *类型指针变量,所以自然用int类型的实际变量
     
     
       ip = &var;       // 在指针变量中存储 var 的地址
       //这里,注意,同上ip是指针类型变量名,又因为指针类型变量是用来存放十六进制的地址的,
       //所以这里将实际变量var的地址赋值给指针变量ip,
       //注意:实际变量中使用&取到地址   这里&var
     
       cout << "输出实际变量值: ";
       cout << var << endl;    //输出实际变量值
     
     
       cout << "输出实际变量地址: ";
       cout << ip << endl;    //输出实际变量地址
     
     
       cout << "输出实际变量值: ";
       cout << *ip << endl;    //输出实际变量值   使用指针变量通过地址找到实际变量值
       //这里注意   指针变量ip中存放的是实际变量var的十六进制的地址,指针变量可以用"*变量名"获取指针变量所指内存地址的内容
     
        return 0;
    }

    输出2:

    输出实际变量值: 20
    输出实际变量地址: 0x6afee8
    输出实际变量值: 20

    四、尾声

    本节为初识指针,介绍了定义一个指针变量、把变量地址赋值给指针(写入地址值)、访问指针变量中可用地址的值(读出地址值),三个最基本的操作,属于C/C++入门级知识,希望对读者有用。

    天天打码,天天进步!

    展开全文
  • c 不同类型的指针

    2017-05-25 16:41:00
    今天看到了一个问题:c里面,不同类型的指针是否可以互指呢?也就是不同类型的指针之间是否可以互相赋值,我想了想,对于32位机子而言,所有类型的指针都是4Byte(64位就是8Byte,这里只讨论32位),为什么是4Byte呢...

    今天看到了一个问题:c里面,不同类型的指针是否可以互指呢?也就是不同类型的指针之间是否可以互相赋值,我想了想,对于32位机子而言,所有类型的指针都是4Byte(64位就是8Byte,这里只讨论32位),为什么是4Byte呢,原因是32位的机子,内存的地址值就是32位,也就是4Byte,而所有的指针,都是存着内存中某个地址的值的,所以所有类型的指针都是32位。既然如此,理应可以相互赋值啊,于是好奇地敲了两行小代码来尝试一下。首先尝试的代码是这样的:

     1     int *p1 = (int*)malloc(10*sizeof(int));
     2     int i;
     3     for(i = 0; i < 10; ++i){
     4         p1[i] = 1;
     5     }
     6     char *p2 = p1;
     7     printf("p1 = %p, p2 = %p\n", p1,p2);
     8     if(p1==NULL){
     9         printf("NULL\n");
    10     } else {
    11         for (i = 0; i < 10; ++i)
    12         {
    13             printf("%d",*(p1+i));
    14         }
    15         printf("\n");        
    16     }

    结果编译的时候出现了一个warning,p1和p2都是指向相同的地址没问题,输出结果很正常:

    但当我把11行的输出代码换成*(p2+i)的时候,输出结果就不太对了:

    这里的输出为什么是1000100010呢?我猜int是4Byte,char是1Byte,所以int*每次移(++)动都会移动4Byte,而char*每次移动(++)则只会移动1Byte,所以这里的1000应该为原来的一个int类型的1,所以我把代码改了一下来验证我的想法:

     1     int *p1 = (int*)malloc(10*sizeof(int));
     2     int i;
     3     for(i = 0; i < 10; ++i){
     4         p1[i] = 1;
     5     }
     6     char *p2 = p1;
     7     printf("p1 = %p, p2 = %p\n", p1,p2);
     8     if(p1==NULL){
     9         printf("NULL\n");
    10     } else {
    11         for (i = 0; i < 10*4; ++i)  //4个为1组,10个int对于char*来说一共要移动40次
    12         {
    13             printf("%d",*(p2+i));
    14             if((i+1)%4==0){     //每4个换行,方便观察输出而已
    15                 printf("\n");
    16             }
    17         }18     }

    我想结果应该是1000 1000 1000这样的,结果果然是这样:

    因此,我们可以得知,不同类型的指针,虽然都是存放地址,虽然可以互相赋值,但是由于不同类型的大小不同,所以很容易出错,我们还是严格遵循规范比较好。有一个类型就比较特殊,就是void,void*是可以由任意别的类型进行赋值的,我们这里把p2的类型改成void*来进行尝试,发现直接赋值是不会产生任何的warning和error。但是发现,即便取得到地址,也没有办法进行解引用,也就是无法取的这块内存里面存放的值,原因是无法进行类型检测,根本不知道一个数据多大,一跳要跳多少,所以当我们要用void*指针来进行输出,编译时就会出现如下错误:

    转载于:https://www.cnblogs.com/Cccarl/p/6904649.html

    展开全文
  • C++与C的指针不同

    2016-12-24 00:06:00
    只有一点不同:C++的类别控制更为严格, 不允许通过void*来实现不同数据类型的数据之间的相互赋值, 只能显示的cast. 例如: bird *b; rock *r; void *v; v = b; r = v; 类似这种代码在C中可以通过编译, 但在CPP中不行. ...

    只有一点不同:C++的类别控制更为严格, 不允许通过void*来实现不同数据类型的数据之间的相互赋值, 只能显示的cast.
    例如:

    bird *b;
    rock *r;
    void *v;
    v = b;
    r = v;

    类似这种代码在C中可以通过编译, 但在CPP中不行.

    Reference

    • Thinking in C++, 2nd, Chapter 11.

    转载于:https://www.cnblogs.com/dengdan890730/p/6216493.html

    展开全文
  • 指针

    2019-12-06 15:10:33
    不同类型不能相互赋值,如,char和int不能相互赋值.否则属于未定义行为. void类型只有内存地址,无大小.,可以被其他类型赋值,不能被解引用. 空指针NULL(闹),特殊指针. #include <stdio.h> int...
  • STL容器的赋值运算符可以更灵活吗?

    千次阅读 2008-11-12 12:10:00
    (转载请注明来源于金庆专栏)STL容器如果元素类型不同是不能相互赋值的, 即使元素类型是兼容.如两个list, 一个存放基类B指针, 一个存放派生类D指针:class B {};class D : public B {}; std::list lB; std::...
  • c++中void指针和const指针浅析

    千次阅读 2016-03-30 22:30:40
     一般来说,只能用指向相同类型的指针给另一个指针赋值,而在不同类型的指针之间进行赋值是错误的。比如: int a,b; int *p1 = &a,*p2 = p1;//正确 而, int a; int *p1 = &a; double *p2 = p1;//错误 即,...
  • 不同类型的指针之间无法相互转换,也不能相互赋值不同类型的指针不能使用==和!=比较 但Go团队并没有完全没收编程人员操纵指针的自由,提供了unsafe包的unsafe.Pointer类型作为非安全的指针,并提供了少量但足够...
  • 类型的指针变量可以相互赋值,数组不可以,只能一个一个的赋值。 2.存储方式 数组:数组在内存中是连续存放的,开辟一块连续的内存空间。数组是根据数组的下进行访问的,多维数组在内存中是按照一维数组存储的,...
  • C++指针和数组之间的区别 一、数组和指针定义 数组:数组是用于存储多个相同数据类型的... 指针指针变量可以相互赋值。 **三、表示范围的不同** 数组的有效范围就是其空间的范围,数组名使用下标引用元素...
  • 概念: ...与char类型不同,string 不一定使用NULL('\0')结束,不能将string直接赋值给char*. char* : char* 是一个指针,可以指向一个字符串数组,至于这个数组可以在栈上分配,也可以在堆上分...
  • 数组与指针

    2020-06-13 00:02:20
    类型指针变量可以相互赋值 访问数据方式不同: 数组可以直接访问,指针需要先解引用,然后访问指向地址内容 sizeof不同: 数组size与元素类型还有个数有关,而指针变量大小与32 64位操作系统有关。 指针与...
  • #include int main(void) { int **p; int arr[10];  p=&arr;...分析:运行程序后出现错误提示信息:cannot convert from 'int ...即这两个是不同类型的指针,只有相同类型的指针才能相互赋值。所以修改程序如下:  #
  • linux C数组与指针

    2018-03-26 19:39:54
    数组:把具有相同类型的若干变量按有序的形式组织起来,而这些同类数据元素的集合成为数组...数组和结构体虽然有相似之处,但也有明显的不同:数组不能相互赋值或初始化,既然不能相互赋值,也就不能用数组类型作为...
  • Linux C数组与指针

    2018-03-19 21:14:16
    数组与指针1.把具有相同类型的若干变量按有序的形式组织起来。...定义和访问数组数组和结构虽然有很多相似之处,但也有一个显著的不同:数组不能相互赋值或初始化。字符数组:char c[10]="c prog...
  • 第二相同结构的结构体变量是可以相互赋值的,而数组是做不到的,因为数组是单一数据类型的数据集合,它本身不是数据类型(而结构体是),数组名称是常量指针,所以不可以做为左值进行运算,所以数组之间就不能通过...
  • (1)两种不同类型的指针,不能直接相互赋值(涉及void类型的除外) 例1: long *p1; int * p2; p1=p2; 警告:从不兼容的指针类型赋值 (2)void类型的指针,可以接受任意类型的指针。但是,不能直接把void...
  • 结构体类型

    2016-07-31 21:43:39
    第二,相同结构的结构体变量是可以相互赋值的,而数组是做不到的,因为数组是单一数据类型的数据集合,它本身不是数据类型(而结构体是),数组名称是常量指针,所以不可以做为左值进行运算,所以数组之间就不能通过...
  • 尽管在某些上下文中数组和指针相互替换,但在编译器看来二者完全不同,并且在运行时所表达的含义也不同。 当我们说对象或表达式有类型的时候,我们通常想的是定位器值的类型,也叫做左值。当左值有完全non-const...
  • 变量包含两种不同数据类型的值:基本类型和引用类型。 基本类型:简单的数据段,按值访问。如Undefined、Null、Boolean、Number和String。不可添加属性,尽管这样不返回错误但没有意义。赋值到新变量时会复制创建一...
  • 隐式类型转换Boolean Conversions 译为bool转换。当指针、ints和浮点数被赋给一个bool变量时...当不同类型的ints之间相互赋值时,要遵循如下三条规则:1. 如果目的数据类型是signed,那么当源数据超过了目的数据类型
  • c++结构体

    千次阅读 2012-04-04 22:11:09
    结构体就是一个可以包含不同数据类型的一个结构,它是一种可以自己定义的数据类型,它的特点和数组主要有两点不同,首先结构体可以在一个结构中声明不同的数据类型,第二相同结构的结构体变量是可以相互赋值的,而...
  • 第一章 关键字 void关键字 (感言:很多人认为 void无需...举例:如果指针p1 和p2的类型相同,那么我们可以直接在p1和p2间相互赋值;如果p1和p2指向不同数据类型,则必须使用强制类型转换运算符把赋值运算符右边

空空如也

空空如也

1 2 3 4 5 6
收藏数 107
精华内容 42
关键字:

不同类型的指针相互赋值