二维指针初始化_指针初始化和赋值的区别

9.1 变量的声明与定义

变量声明:用于向程序表明变量的类型和名称。通过使用关键字 extern 声明,即不分配存储空间。编译器识别 extern 即知,变量在他处定义。注意:只有当 extern 声明位于函数外部时,才可以被初始化(可初始化说明已分配内存地址,等于变量定义)。

变量定义:用于为变量分配存储空间,还可为变量指定初始值。程序中,变量有且仅有一个定义。当变量定义时,也同时向程序表明了变量的类型和名称,即变量定义可以理解为变量声明+分配内存地址。定义提供了一个变量在程序中的唯一描述,所以在一个程序中,变量只能定义一次(即只分配一次内存地址),但声明可以多次。

#include <iostream> using namespace std; extern float pi = 3.14; //可以被初始化 int main() { cout << "pi=" << pi << endl; //输出:pi=3.14 cout << "&pi=" << &pi << endl; //输出:&pi=00007FF77B03E00C,说明已分配地址 extern int a1; //extern声明但不定义 extern int a1; //多次声明,不会报错 extern int a2=1; //错误C2205:不能对带有块范围的外部变量进行初始化。不能被初始化 cout << "&a1=" << &a1 << endl; //链接器工具错误LNK2001:链接器无法解析对变量的引用 int b; int b; //错误C2086:重定义 cout << "b=" << b << endl; //错误C4700:使用了未初始化的局部变量“b” cout << "&b=" << &b << endl; //输出:&b=000000EF8977F9F4;说明:变量被定义,已分配内存空间 }

9.2 函数的声明与定义

函数声明:是向编译器表明函数名称、参数数量及类型、函数返回类型。声明不会分配内存地址。

函数定义:是为函数分配内存地址,且包含实现函数功能的函数体{ …… }。同样,函数定义只能一次,但可以声明多次。

#include <iostream> using namespace std; int add1(int x, int y); //函数声明 int add2(int x, int y) //函数定义 { return x + y; }; int main() { cout << "add1()地址:" << &add1 << endl; //错误 LNK2019:调用未定义的函数(编译器认为函数存在, 但链接器不能解析对地址的调用) cout << "add2()地址:" << &add2 << endl; //输出:add2()地址:00007FF76ACA1460 }

9.3 引用与指针

指针:是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元(a pointer which point to the address of a variable)。通过地址操纵对象,可以有效地表示复杂的数据结构,用于数组和函数的控制。指针定义的一般格式如下:

数据类型 *变量名1,*变量名2,……,*变量名n;

注意:“ *”是一个标志,表示所定义的变量是一个指针变量,以示与一般变量的区别,定义时星号的位置居左、居中、居右都是正确的(Visual Studio 2022中默认位置居左)。指针变量的类型与其所指向的数据的类型必须相同。

int* p2 = &a1; //指针名是p2,不是* p2, 此处的 * 可理解为定义的标识 cout << "&a1=" << &a1 << endl; //输出:&a1=000000B27CAFFA64 cout << "p2=" << p2 << endl; //输出:p2=000000B27CAFFA64,是a1变量的地址 cout << "*p2=" << *p2 << endl; //输出:*p2=2(a1的值),* 代表解引用,找到指针指向的变量

引用:是变量的一个别名,实质上是同一个地址上存储的变量,对引用的操作与对变量直接操作完全一样。注意:有数据类型(如int& a=b)时,&表示引用,否则&是取地址运算符,如&a表示取a变量的地址。引用时C++对C的一个重要扩展。

int& b2 = a1; cout << "&a1=" << &a1 << endl; //输出:&a1=000000B27CAFFA64 cout << "&b2=" << &b2 << endl; //输出:&b2=000000B27CAFFA64,与a1变量的地址相同

引用和指针的特性:

引用被创建时,必须初始化,而指针可以是空值,可在任何时候被初始化。注意:如果指针没有初始化,指向一个未知的地址,在读取数据时,可能会造成程序崩溃。

int& b1; //错误C2530:“b1” : 必须初始化引用 int& b2 = a; //ok int* p1; //ok

引用只能是一级,指针可以有多级。

int&& e1=a; //错误C2440:“初始化”: 无法从“int”转换为“int && ” int** e2; //ok,此处**也是起到标识作用

引用在初始化后不可改变,指针在初始化后可以改变(即指向其它的存储单元)。

int& b2 = a1; //引用 int& b2 = a2; //错误C2374:b2重定义,多次初始化 b2 = a2; //相当于把a2赋值给a1,b2的地址还是与a1的地址相同 int* p2 = &a1; //p2为a1变量的地址 p2 = &a2; //p2变为a2变量的地址

可以用常量或表达式对引用进行初始化,此时须用const作声明。对表达式初始化时,编译系统生成一个临时变量(在内部实现的,用户不能访问),用来存放该表达式的值,引用是该临时变量的别名。通过const声明,不仅可以用表达式对引用进行初始化,还可以用不同类型的变量进行初始化。

int i = 4; const int& f = i + 1; cout << "i=" << i << endl; //输出:i=4 cout << "f=" << f << endl; //输出:f=5 cout << "&i=" << &i << endl; //输出:&i=00000009146FF5D4 cout << "&f=" << &f << endl; //输出:&f=00000009146FF614,与i的地址不同

此外,通过const声明指针时,要注意常量指针、指向常量的指针以及指向常量的常量指针的差别。

int* const pA; //常量指针,不能再指向其他地址,但可以修改pA地址指向的值 const int *pB; //指向常量的指针 , 不能修改指向的值,但可以修改pB的指向 const int* const pC; //指向常量的常量指针

一个指针占据的内存空间大小与其指向的数据类型无关,与计算机类型所能寻址的位数有关。

cout << "int型指针内存占位=" << sizeof(int*) << endl; //int型指针内存占位=8,计算机是64位的 cout << "char型指针内存占位=" << sizeof(char*) << endl; //char型指针内存占位=8 cout << "double型指针内存占位=" << sizeof(double*) << endl; //double型指针内存占位=8 cout << "float型指针内存占位=" << sizeof(float*) << endl; //float型指针内存占位=8

指针重要作用之一是在运行阶段分配未命名的内存以存储数据。C++可使用new运算符来分配内存,运行阶段需要为哪种数据类型分配内存,new找到一个长度正确的内存空间,并返回该内存空间的地址。将该地址赋给一个指针,即可实现对该地址内的值进行操作。该内存地址的数据使用完成后使用delete运算符释放内存地址,释放的内存可供程序的其他部分使用。注意:不要使用delete来释放不是new分配的内存;不要使用delete释放同一个内存块两次;如果使用new为数组分配内存,则应使用delete来释放。

int* p6 = new int; *p6 = 10; cout << "sizeof *p6=" << sizeof(*p6) << endl; //输出:sizeof *p6=4 cout << "*p6=" << *p6 << endl; //输出:*p6=10 cout << "p6=" << p6 << endl; //输出:p6=000002119D016B60 delete p6; //cout << "*p6=" << *p6 << endl; //测试报错:读取访问权限冲突,p6 是 0x8123 cout << "p6=" << p6 << endl; //输出:p6=0000000000008123 int *p7=new int; //指针p7为数组第一个元素的地址,*p7为第一个元素的值 ... delete p7; //释放内存

数组名称是数组第一个元素的指针。使用指针变量指向数组的首地址,即可访问该数组。

int abc = { 2,3,4,5 }; cout << "abc地址=" << &abc << endl; //输出:abc地址=000000717D36F908,与abc一致 cout << "abc地址=" << &abc << endl; //输出:abc地址=000000717D36F908 cout << "abc地址=" << &abc << endl; //输出:abc地址=000000717D36F90C cout << "abc地址=" << &abc << endl; //输出:abc地址=000000717D36F910 cout << "abc地址=" << &abc << endl; //输出:abc地址=000000717D36F918 int* p3 = abc; for (int i = 0; i < 4; i++) { cout << *(p3++) << " "; //使用指针遍历数组 }

指针可以进行加法+/减法-运算,以及自增++/自减–运算,指针的运算就是地址的运算,指向的对象也相应的改变。此外,两个指针相减能获得两指针地址之间的距离,且分正/负;两指针相加没有意义。注意:C++不会对访问的地址进行检查,通过指针运算,指针访问一块未分配/分配给其他对象的内存,但是没有任何报错,会造成取值的错误。

int nums4 = { 11,22,33,44,55,66,77 }; int* p4 = nums4; int* p5 = nums4 + 3; cout << "*(nums4 + 2)=" << *(nums4 + 2) << endl; //输出:*(nums4 + 2)=33 cout << "*(p4 + 2)=" << *(p4 + 2)<< endl; //输出:*(p4 + 2)=33 cout << "p4 =" << p4 << endl; //输出:p4 =00000027D334F618 cout << "(p4 + 1)=" << p4 + 1 << endl; //输出:(p4 + 1)=00000027D334F61C;加了4个字节 cout << "(p4 + 2)=" << p4 + 2 << endl; //输出:(p4 + 2)=00000027D334F620;了8个字节 cout << "(++p4)= " << ++p4 << endl; //输出:(++p4)= 00000027D334F61C,与p4+1地址一致 cout << "(--p4)= " << --p4 << endl; //输出:(--p4)= 00000027D334F618 cout << "p5 - p4 =" << p5 - p4 << endl; //输出:p5 - p4 =3 cout << "p4 - p5 =" << p4 - p5 << endl; //输出:p4 - p5 =-3 cout << "(p4 +10)=" << p4 + 10 << endl; //输出:(p4 +10)=000000F73A2FF730 cout << "*(p4 +10)=" << *(p4 + 10) << endl; //输出:*(p4 +10)=-858993460

表示不确定的类型的用void型指针,void型指针是一种通用型指针,任何类型的指针值都可以赋给void类型的指针变量。但对已赋值的void型指针,如再对其输出或者传递指针值等操作时,则必须显式类型转换,否则会出错。

void* p7; int m = 99; char n = 'a'; p7 = &m; cout << "p7=" << p7 << endl; //输出:p7=000000292B8FFAB4 //cout << *p7 << endl; //错误E0852:表达式必须是指向完整对象类型的指针 cout << "*(int*)p7=" << *(int*)p7 << endl; //输出:*(int*)p7=99 p7 = &n; cout << "p7=" << p7 << endl; //输出:p7=000000292B8FFAD4 cout << "*(char*)p7= " << *(char*)p7 << endl; //输出:*(char*)p7= a

指针的值(即地址)的四种状态:指向一个对象的地址;指向紧邻对象所占空间的下一个位置;没有指向任何对象(空指针,指针变量赋值为nullptr,在C++中,NULL表示0,程序数据不会存储在地址为0的内存中);无效指针(未经初始化的指针就是个无效指针,为避免出现无效指针,在不知指针指向时,使用nullptr进行赋值)。

二维指针初始化_指针初始化和赋值的区别

二维指针初始化_指针初始化和赋值的区别

测试程序如下:

//自学 C++ 第 9 课 声明与定义、引用与指针 #include <iostream> using namespace std; extern float pi = 3.14; int add1(int x, int y); int add2(int x, int y) { return x + y; }; void swap1(int xx, int yy) { int temp = xx; xx = yy; yy = temp; } void swap2(int* xx, int* yy) { int temp = *xx; *xx = *yy; *yy = temp; } int main() { cout << "pi=" << pi << endl; cout << "&pi=" << &pi << endl; int a1; int a2 = 2; //cout << "a=" << a << endl; //错误提示:使用了未初始化的局部变量“a”; cout << "&a1=" << &a1 << endl; //输出结果:&a=000000EF8977F9F4;说明:变量声明后,内存空间已分配; a1 = 1; //int a; //int& b1; //错误C2530:“b1” : 必须初始化引用 int& b2 = a1; //"引用"就是变量的别名,对"引用"操作与对变量直接操作完全一样。 b2 = a2; int* p1; p1 = &a1; p1 = &a2; int* p2 = &a1; //p2 = &a2; cout <<"a1=" << a1 << endl; cout << "a2=" << a2<< endl; cout << "&a1=" << &a1 << endl; cout << "&a2=" << &a2 << endl; cout << "*(&a1)=" << *(&a1) << endl; cout << "b2=" << b2 << endl; cout << "&b2=" << &b2 << endl; cout << "*(&b2)=" << *(&b2) << endl; cout << "p1=" << p1 << endl; cout << "p2=" << p2 << endl; cout << "*p1=" << *p1 << endl; cout << "*p2=" << *p2 << endl; cout << "&(*p2)=" << &(*p2) << endl; const char* c = "hello"; //hello在内存是怎么存储的?占几个字节? cout << "c=" << c << endl; cout << "&c=" << &c << endl; //是首地址还是整个hello单词的地址? extern int d1; //extern声明但不定义。 //extern int d2=1; //错误C2205:不能对带有块范围的外部变量进行初始化 //cout << "&d=" << &d << endl; //链接器工具错误LNK2001:链接器无法解析对变量的引用。 extern int d1; int x = 1, y = 2; cout << "x+y=" << add2(x,y) << endl; //cout << "add1()地址:" << &add1 << endl; 错误 LNK2019:调用未定义的函数(编译器认为函数存在, 但链接器不能解析对地址的调用) cout << "add2()地址:" << &add2<< endl; //int&& e1 = a;//错误C2440:“初始化”,无法从“int”转换为“int && ” int** e2; int i = 4; const int& f = i + 1; cout << "i=" << i << endl; cout << "f=" << f << endl; cout << "&i=" << &i << endl; cout << "&f=" << &f << endl; cout << "int型指针内存占位=" << sizeof(int*) << endl; cout << "char型指针内存占位=" << sizeof(char*) << endl; cout << "double型指针内存占位=" << sizeof(double*) << endl; cout << "float型指针内存占位=" << sizeof(float*) << endl; int abc = { 2,3,4,5 }; cout << "abc地址=" << &abc << endl; cout << "abc地址=" << &abc << endl; cout << "abc地址=" << &abc << endl; cout << "abc地址=" << &abc << endl; cout << "abc地址=" << &abc << endl; int* p3 = abc; for (int i = 0; i < 4; i++) { cout << *(p3++) << " "; } cout << endl; int nums4 = { 11,22,33,44,55,66,77 }; int* p4 = nums4; int* p5 = nums4 + 3; cout << "*(nums4 + 2)=" << *(nums4 + 2) << endl; cout << "*(p4 + 2)=" << *(p4 + 2)<< endl; cout << "p4 =" << p4 << endl; cout << "(p4 + 1)=" << p4 + 1 << endl; cout << "(p4 + 2)=" << p4 + 2 << endl; //cout << "(p4++)= " << p4++ << endl; cout << "(++p4)= " << ++p4 << endl; //cout << "(p4++)= " << p4++ << endl; cout << "(--p4)= " << --p4 << endl; cout << "p5 - p4 =" << p5 - p4 << endl; cout << "p4 - p5 =" << p4 - p5 << endl; cout << "(p4 +10)=" << p4 + 10 << endl; cout << "*(p4 +10)=" << *(p4 + 10) << endl; int xx = 8; int yy = 80; swap1(xx, yy); //运行结果并没有交换,值传递是把参数进行拷贝,把xx拷贝,yy拷贝,交换的是拷贝,原值没有影响;形参的改变无法引起实参的改变,交换的仅仅是形参。 cout << "xx = " << xx << " yy = " << yy << endl; swap2(&xx, &yy); //运行结果进行了交换,实参传递的是地址,形参是指针变量,通过指针的方式来交换实参 cout << "xx = " << xx << " yy = " << yy<< endl; int* p6 = new int; *p6 = 10; cout << "sizeof *p6=" << sizeof(*p6) << endl; cout << "*p6=" << *p6 << endl; cout << "p6=" << p6 << endl; delete p6; //cout << "*p6=" << *p6 << endl; cout << "p6=" << p6 << endl; void* p7; int m = 99; char n = 'a'; p7 = &m; cout << "p7=" << p7 << endl; //cout << *p7 << endl; //报错 cout << "*(int*)p7=" << *(int*)p7 << endl; p7 = &n; cout << "p7=" << p7 << endl; cout << "*(char*)p7= " << *(char*)p7 << endl; return 0; }

每课三题:

① delete和delete的区别?

答:delete只会调用一次析构函数,而delete会调用每个成员的析构函数;用new分配的内存用delete释放,用new分配的内存用delete释放。

② 什么是野指针?

答:野指针是未初始化或未释放的指针,其指向的内存地址非程序员所需的,可能指向了受限的内存。

③ 链表和数组的区别?

答:一是存储形式,数组是一块连续的空间,链表是不连续的动态空间,每个结点要保存相邻结点的指针。二是数据查找方式,数组查找使用地址偏移,速度快,链表需要按顺序检索结点,效率低。三是数据的插入或删除,链表可以快速插入和删除结点,而数组则可能需要大量的数据移动。四是越界问题,链表不会越界,数组存在越界的可能。(第2~4点的不同皆因第1点存储形式不同造成的)

自学 C++ 第 1 课 数字大小排序

自学 C++ 第 2 课 数组包含关系

自学 C++ 第 3 课 正整数反序输出

自学 C++ 第 4 课 计算体积及表面积

自学 C++ 第 5 课 杨辉三角

自学 C++ 第 6 课 二维数组找最值

自学 C++ 第 7 课 跳跃游戏

自学 C++ 第 8 课 数据合并排序

本文【二维指针初始化_指针初始化和赋值的区别】由作者: Web服务 提供,本站不拥有所有权,只提供储存服务,如有侵权,联系删除!
本文链接:https://www.cuoshuo.com/blog/4130.html

(0)
上一篇 2023-03-09 08:24:55
下一篇 2023-03-09 08:33:58

相关推荐

  • access端口和trunk端口_access端口和trunk端口的区别

    近日看到一个VLAN图,为了验证交换机与路由器这个箭头所指接口,到底是配成Access类型,还是Trunk类型,特地做了个实验。 使用模拟器,搭建了下面这个环境,如图所示。 这个图也是我们中小企业,常用的网络拓扑图。 对于路由器RouterB做了如下配置。 <RouterB>DIS CU # sysname RouterB # undo info…

    2023-03-19
    000
  • 服务器管理器添加角色和功能

    操作步骤 一、如何打开控制面板以及启用、关闭windows功能 1、通过打开运行界面输入“control”打开控制面板; 2、在程序和功能界面,找到启用或关闭Windows功能,点击该功能后会弹出windows功能窗口,具体添加看具体需求,以下添加Telnet客户端功能为例,如下图所示: 二、如何打开服务器管理器以及添加、删除角色功能 1、如何打开服务器管理…

    2023-03-14
    200
  • 腾讯待遇好还是华为好_腾讯和华为哪个工资高

    一份公务员的工作,和去腾讯公司上班的工作,你会选哪个? 看到网上有一些朋友说自己考上了公务员,同时也通过腾讯的面试,很纠结,不知道应该去哪里,如果做公务员,比较稳定,工资也就那样子,收入相对来说肯定是没有在腾讯里工作的工资那么高的,所以有的人就纠结了,我们来分析一下,当公务员和在腾讯里上班有什么不一样? 选择当公务员如何? 假如你选择了一份公务员的工作,你就…

    2023-03-09
    800
  • 百分比换算成小数要怎么换算(百分比如何换成小数点)

    分数化小数: 也就是用分子除以分母,得出的即是小数。 小数化为百分数: 也就是让小数乘上100,再在其后面加上个%号。 比如:1/4化为小数,就是1除以4=0.25 就是小数,再化成百分数就是 0.25×100=25 再加上% 即25%。若把25%化成小数即去掉百分号现除以100 25÷100=0.25,0.25化成分数即25/100再化简得1/4。 百分数…

    2023-03-14
    200
  • html具体含义(html叫什么中文)

    1 什么是HTML HTML 是用来描述网页的一种语言。HTML 是一种在 Web 上使用的通用标记语言。HTML 允许你格式化文本,添加图片,创建链接、输入表单、框架和表格等等,并可将之存为文本文件,浏览器即可读取和显示。 HTML 指的是超文本标记语言: HyperText Markup Language HTML 不是一种编程语言,而是一种标记语言 标…

    2023-03-21
    000
  • 播放器代码错误是什么意思

    今天小米电视/小米盒子播放视频提示错误码600,1000怎么办?盒子不能播放了,提示错误代码600.1000这是什么情况?所有视频都无法进行播放,提示播放出错!错误码(600,1000)。经过一轮折腾,楼主分享3个解决方法。 播放出错!小米电视/小米盒子错误码600,1000原因分析 首先分析下小米电视/盒子播放出错!错误码(600,1000)的原因,这个是…

    2023-03-17
    100
  • php文件用什么软件打开

    做技术的应该都知道,大部分文本类文件都可以用记事本打开,比如js文件、php文件、log文件、py文件、json文件、xml文件等等。但是你需要先“鼠标右键”,然后找到“打开方式”,才能找到“用记事本打开”,下面教大家直接把它给添加到右键中: 新建一个txt文件,复制下方的代码到其中,然后保存关闭。 Windows Registry Editor Versi…

    2023-03-14
    300
  • shell脚本基础教学

    用途:完成特定的、较复杂的系统管理任务 格式:集中保存多条Linux命令,普通文本文件 执行方式:按照预设的顺序依次解释执行 shell脚本在测试过程中一般的作用: 1. 自动布署环境 2. 自动批量生成测试数据 3. 利用相关命令监控系统和平台资源 一、解释器 #!/bin/bash echo "Hello World !" 执行:ba…

    2023-03-09
    600
  • rar是什么格式怎么解压

    rar格式的文件是一种压缩包文件,它能压缩文件占用空间的大小及提高文件的安全性(加密)。有一些刚接触电脑的小伙伴不知道电脑rar文件怎么打开,下面小编就来告诉你rar格式的文件怎么打开。 工具/原料 系统版本:windows 7 系统 品牌型号:宏碁传奇X 方法 1、鼠标右键点击需要解压的文件,可以选择“解压到”、“解压到当前文件夹”等。 2、第一种可以自行…

    2023-03-13
    200
  • ftp教程ubuntu ubuntu开启ftp

    FTP(文件传输协议)是一种标准网络协议,用于在远程网络之间传输文件。 有许多可用于 Linux 的开源 FTP 服务器。最流行和使用最广泛的是PureFTPd 、ProFTPD 和vsftpd 。在本教程中,我们将安装 vsftpd(非常安全的 Ftp 守护程序)。它是一个稳定、安全、快速的 FTP 服务器。我们还将向您展示如何配置 vsftpd 以将用户…

    2023-03-16
    200

发表回复

登录后才能评论
返回顶部
错说博客上线啦!