*pa将a该为0,可以看到内存中也发生了相应的改变。...我们也可以用例子证明这句话: 前面的文章中我们说过,创建数组的时候数组长度只能为大于0的整型常量或整型常量表达式,不能包含变量。...因为上篇文章我们刚了解了一点指针,知道通过指针的解引用操作可以间接地去找到、操作一些值,那这里能不能创建一个指针变量pa,将变量a的地址存到pa中,再解引用pa来实现间接改变a的值呢?...上面代码中改变pa的值事实上是改变了指针变量pa的指向,也就是此时指针变量pa里面存的是变量b的地址。...还有,当 “ * ” 的左边和右边都有const修饰的时候,*pa和pa都具有常量属性,都不能改变。 如果觉得我的文章还不错,请点赞、收藏 + 关注支持一下,我会持续更新更好的文章。
内存单元可以用一个通俗的例子来说明 它们之间的 到银行去存取款时, 银行工作人员将根据我们的帐号去找我们的存款单, 取款的金额。在这里,帐号就是存单的指针, 存款数 是存单的内容。...因为指针变量是指向一个变量的地址,所以将一个变量的地址值 赋值给这个指针就 "指向" 了该变量 例如:将变量 i 的地址值赋值给指针变量 p 中,p 就指向 i,其关系如下所示↓ 在程序代码中是通过... 变量名 对 内存 单元进行存取操作的,但是代码经过编译后已经将变量名转换为该变量在内存中存放的地址,对变量值的存取都是通过地址进行的。...printf("改变的:%d\n", *pa);//解引用操作符是可以改变取地址原来的值的!...另外,指针变量和一般变量一样,存放在它们之中的值是可以改变的,也就是说可以改变它们的指向。
但是呢,问题就来了:为什么我们运行ls这些指令可以直接敲对应的指令直接执行,而我们自己生成的可执行程序运行要加./呢? 为什么呢? 如果我想让我们自己的可执行程序也可以不加..../的定位方式其实是相对路径,那用绝对路径是不是也可以执行这个可执行文件? 这当然也是可以的。 但是它为什么就不能像ls哪些基本命令那样无需指明路径直接执行呢?...比如我们把自己写的可执行程序的路径添加到了PATH环境变量中,使得我们运行自己的可执行程序时可以像基本命令ls那样无需指定完整路径,直接可以运行。 但是呢?...那bash就会把这个环境变量及其赋值作为一个字符串添加到环境变量表的指针数组中。...我们也可以用echo 变量名打印它的值,只是它没有被添加到环境变量表里面,子进程不会继承,获取不了。 但是,你不觉得奇怪吗?
野指针就是指针指向的位置是不确定的,下面来看看常见的野指针出现的成因 1.2野指针出现的几种原因 1.2.1指针并没有初始化 这个很好解释,我们每次设置指针变量的时候,指针指向的地址是有的,但是如果我们并没有指定它指向的地址具体是什么...,当我们出函数的时候会让形参释放(销毁),所以吗,在我们传值调用的时候,在交换后形式参数已经被销毁了,所以形式参数的改变不会影响到实际参数,可能有的人会说,为什么不在函数内部打印呢?...因为我们在这里想要做到的是完全交换,意是在出函数的时候,我们也可以做到两个数是完全改变的,所以来说,在这个时候,我们的主角,传址调用它就来了,若想完全做到交换,让地址交换,那么内容也随之变换,具体的代码如下...,两个数的值完美的发生了改变,所以,传址调⽤,可以让函数和主调函数之间建立真正的联系,在函数内部可以修改主调函数中的变量;所 以未来函数中只是需要主调函数中的变量值来实现计算,就可以采⽤传值调⽤。...如果函数内部要修改 主调函数中的变量的值,就需要传址调用。
通过错误提醒可以知道,自加运算符 ++ 需要一个左值,虽然数组名是数组第一个元素的地址,但是他是不可变的,不满足左值的要求,即不是一个左值。...但是指针是一个左值,所以我们只需要初始化一个指针为数组第一个元素的地址,就可以解决这个问题,具体代码如下 ?...如果忘记了可以回顾一下之前的文章《我真的快学不动了,怎么办?》中的 “自增自减运算符” 内容。 上面这段代码是不是和 《我真的快学不动了,怎么办?》 部分 指针的运算 很相似。...但是对于直接用数组形式定义的数组,由于数组名虽然和数组中第一个元素的地址相等,但是并不是一个左值,所以只可以数组的形式访问数组中元素,不可以使用指针的形式访问,除非向上面那样新定义一个指针。...我们将指针数组中的每个元素初始化为一个字符串,这里之所以可以这样写是因为一个指针可以使用 char *p = "sss" 的方式进行初始化,所以如果想初始化一个指针数组,就可以通过上面的方式进行。
因此查阅了一下相关资料,发现指针和数组名是不能混用的。 ### 指针和数组名的区别 > 数组名代表了存放该数组的那块内存,它是这块内存的首地址。...**不是数组名这个符号的值是那块内存的首地址,而是数组名这个符号本身就代表了首地址这个地址值,它就是这个地址**。这就是数组名属于符号常量的意义所在。...关于这段话的理解,我觉得引入编译知识比较好理解,数组名是一个符号,和枚举符号一样,有其自身的值,数组名的值就是数组的首地址。在编译的过程中,这些符号常亮会被替换为地址符号。...而指针是一个普通的变量,变量的值存放的是数组的地址。虽然数组名和指针都可以进行元素访问,但是其本质是有很大区别的!...这是一个正常工作过程,链接出来的可执行文件至少在对于该数组的引用部分将工作得很好。
一、动态内存管理的意义 在我们敲代码的时候,是否会有着这样的想法,为什么我创建的这个数组arr[10]它就只能存储10个元素呢,它为什么不能在程序的运行时跟随我们的需要,扩大它对应的空间呢?...可能有的小伙伴不是很理解为什么会造成浪费,举个例子,我有一个能存放100个整型的数组,但我只放了10个元素进去,但计算机它已经把这400个字节的空间分配给了这个数组,这400个字节的空间在这个数组销毁之前...有联想能力的小伙伴恐怕就想到了,那如果我写了个循环一直在开辟空间,且我通过特殊的方式让程序无法结束,那是否会占用计算机的大量内存,是的,这可能会使计算机没法正常工作。...a = NULL; //a此时是野指针,安全起见,给它变为空指针 } 后面的空间充足,地址不变 后面的空间不足,地址改变 计算机没法给那么大的空间 三、柔性数组...;//打印出来 } free(x);//释放x的空间 x = NULL; //将野指针置为空指针,避免在后面使用 } 3.指针可以替代柔性数组的作用 #include #
数组是存储在连续内存位置的项目的集合。这个想法是将多个相同类型的项目存储在一起。这使得通过简单地将偏移量添加到基值,即数组的第一个元素的内存位置(通常由数组的名称表示)来更容易地计算每个元素的位置。...基值是索引 0,两个索引之间的差值是偏移量。 为简单起见,我们可以将数组视为一组楼梯,其中每一步都放置了一个值(假设您的一个朋友)。在这里,您可以通过简单地知道他们所走的步数来识别任何朋友的位置。...数组的大小 在 C 语言中,数组具有固定大小,这意味着一旦给定了大小,它就无法更改,即您不能缩小它,也不能扩展它。...原因是为了扩展,如果我们改变大小,我们不能确定(每次都不可能)我们是否可以免费获得下一个内存位置。收缩将不起作用,因为数组在声明时会静态获取内存,因此编译器是唯一销毁它的人。...1.检查堆栈下溢 2.将顶部减 1 所以我们正在做的是,指向最顶层元素的指针是递减的,这意味着我们实际上只是限制了我们的视图,如果您有任何原始数据类型,则元素停留在那里谈论内存空间,那么它可能没问题,
如果一个指针变量的值是NULL,那么去访问这个指针指向的变量的时候一定会报错。 多个指针指向同一个变量,修改其中一个所有指针指向的值都会改变。因为多个个指针指向的是同一块地址。...指针为什么要分类型? 多级指针 一个指针变量中存储的是一个一级指针的地址,那么它就是二级指针,一个指针变量中存储的是一个二级指针的地址,那么它就是三级指针。...最后1次执行完毕之后,p1指针指向数组外面去了,p1就不再执行数组中的任何元素了。 注意: 数组名代表数组的地址,而数组一旦创建,数组的地址就确定了,不能改变。...所以,我们不能为数组名赋值也不能修改数组名的值,但是可以使用数组名的值。...当我们以字符指针的形式要将字符串数据存储到常量区的时候,并不是直接将字符串存储到常量区,而是先检查常量区中是否有相同内容的字符串,如果有,直接将这个字符串的地址拿过来返回,如果没有,才会将这个字符串数据存储到常量区中
/article/37516.htm 好久没有用过C/C++的二级指针了,总觉的它就是指针的指针,没什么大不了的,但是今天看到一道面试题,感觉自己对二级指针的理解还是不够深刻。...但是只是形参的指向改变了,实参str仍然指向NULL,并没有改变。因此,程序达不到题目的要求,而且运行时会出现错误,由于str一直指向NULL,执行strcop时,会出现错误,提示某某内存不能写入。...而调用GetMemory函数时,传递的是str的地址,p是一个二级指针,*p是一个指针。因此,将str的地址赋给临时变量p,则*p就是指针str的值,改变*p的值就相当于改变str的值。...,因为一般数组声明时,不允许下标是变量,所以如果想动态决定数组各维的大小,最好这样做。...只是把第一个链表的地址赋值给了pp,,但是并没有改变*p的指向 下面的pp->pNext = last;只是给pp赋了新值 就如同 #include"stdio.h" #include"stdlib.h
return 0; } pa 通过解引用找到 a 并将他的值改成 0 ,就好像通过门牌号找到特定酒店房间里的特定物品,并将其替换了,但这是就会产生一个疑惑,为什么不直接通过对 a 进行赋值改变它的值,...int const p = &a const 放在 * 的右边做修饰 const如果放在*的左边,修饰的是指针指向的内容 保证指针指向的内容不能通过指针来改变,但是指针变量本身的内容可变 即 a...=10 这个值不能改变,变量 p 指向 a 可以改成指向别的变量 const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改 但是指针指向的内容,可以通过指针改变 即 a=10...这个值能改变,变量 p 指向 a 不可以改成指向别的变量 6.指针运算 6.1指针 ± 整数 比如打印数组可以用指针打印,更加清晰有效 #include int main()...+整数 } return 0; } 具体的分析在我“打印数组的多种方式”的一篇博客有提到 传送门:打印数组的多种方式 6.2指针 - 指针 代替 strlen 函数(计算字符或字符串长度),
指针的介绍 在程序中,我们声明一个变量(int a = 1),将数据1存到变量a中,计算机内部会将这个数据存到内存(RAM)中,那么,数据存到某个地方,就会涉及地址。...是的,可以,这个变量就是指针,指针它就是存储另一个变量的内存地址的一种数据类型,即指针的内容就是另一个变量的内存地址。...,但是把数组的内容换一下就不会是一样了,如果是改成(*p) + 1,那么就是(*p) + 1 = a[0] + 1 = 2,同理可以改成p+2、p+3.........前面有讲到,指针也是一种数据类型,是一种变量,也有自己的地址,所以既然有地址,而指针就是存放另一个变量的地址的呀,那为什么不能再用一个指针存放这个指针的地址呢,对吧!...数组指针:指针在后,说明它就是个指针,所以数组指针指向的是数组,相当于一次声明了一个指针。从前面就已经知道,二维数组a[3][2]中,a实质上就是一个数组指针。
: 从内存窗口我们可以看到: 对于char*类型的指针p1,在通过解引用将地址中存储的值改为0时,p1改变了1个字节的内容;对于short*类型的指针p2,在通过解引用将地址中存储的值改为0时,p2改变了...2个字节的内容;对于int*类型的指针p3,在通过解引用将地址中存储的值改为0时,p3改变了4个字节的内容;对于long long*类型的指针p4,在通过解引用将地址中存储的值改为0时,p4改变了8个字节的内容...12.3 const修饰指针变量 为了能够在拿到变量地址后也无法修改变量的值,我们可以通过const对指针进行修饰。但是应该如何修饰呢?...p,即无法对指针p指向的对象进行修改,但是可以对*p中存储的内容进行修改; 12.3 const修饰指针变量 为了能够在拿到变量地址后也无法修改变量的值,我们可以通过const对指针进行修饰。...我们将常量值存放在数组中时,计算机就会通过常量的地址找到对应常量的值,并将该值存放在数组中对应的元素地址下,所以此时我们是可以修改数组元素存放的值; 但是对于常量字符串来说,我们将其用字符指针指向时,是指向的常量字符串自己本身的地址
哦吼,一样的。 那现在就好玩了,我们知道了a的地址,也就是我们有了任意访问a的权限,也就是说我们可以通过地址改变a的值,来试试。...那么就更好玩了,我不仅可以访问,我还可以有选择的访问。...*pa,会导致a的值无法被改变,也即是指针变量指向的元素的值为定值,const在*后面,修饰的是pa,会导致pa存的地址无法被改变,也就是指针变量无法被修改。...,数组名就是首元素地址,首元素地址加上数组元素个数,指向了\0,令p是首元素地址,然后就是比较咯,这个我相信是很容易理解的,就不多介绍了。...反正没有给它地址,就随便存咯,跟深海鱼一样,反正没有人看到,随便长咯。 看吧,如果不初始化,指针变量的值是个随机值,且指向的位置不确定,是比较危险的。
但是如果我们不修改变量的值,直接使用是否可以?...这就像现实生活中,我这里有一个房子,你不能翻窗户进去,只能从正门进去,但是某一天呢,我有事不在家,就把房门锁上了,你无法从正门进去了,于是你把窗户砸了,从窗户爬进去了。...1.3 总结: const如果放在*的左边,修饰的是指针指向的内容,保证指针指向的内容不能通过指针来改变。 但是指针变量本身的内容可变。...const如果放在*的右边,修饰的是指针变量本身,保证了指针变量的内容不能修改,但是指针指 向的内容,可以通过指针改变。...2.赋值:可以将变量的地址赋值给指针,比如 *p = &n;表示将n的地址赋给p,从而改变指针p所指向的值。
网上存在很多错误的言论和资料,一定要明确,在C语言中,数组不存在值传递,这也是为什么不能对做函数参数的数组使用sizeof运算的原因所在,因为它会自动退化为指针。...counter函数为一个计数函数,每次调用都将传入的值加10,可是为什么在函数的外部打印t值,它的值没有发生改变呢?...什么是指针 在回答什么是指针之前,我认为应当先提问为什么需要指针?如果没有明确的应当重视的理由,大家何必花大力气学习它呢?...这样说比较绕,换个说法,如果直接将一个内存地址对应的内存中保存的值取出来,这就叫直接寻址,如果是对保存地址的变量使用,这就是间接寻址。使用间接寻址运算符的过程被称为解引用。 ?...图示 注意,指针变量的右值应当是一个地址,而不能是其他值。因此给指针变量赋值时,先使用取地址符&求得变量的地址,然后才将这个地址赋给指针变量,这个过程称为指针指向某某变量。
, *pa ); pa++ ; //注意这里,指针值被修改 } 可以看出,这段代码也是将数组各元素值输出。...数组名是指针常量,其值是不能修改的,因此不能类似这样操作:a++.前面4,5节中pa[i],*(pa+i )处,指针pa的值是使终没有改变。所以变量指针pa与数组名a可以互换。 4....即它可以重新指向另一个地址的,但是,不能通过*pi来修改i2的值。 这个规则符合我们前面所讲的逻辑吗?当然符合了! 首先const 修饰的是整个*pi(注意,我 写的是*pi而不是pi)。...pi的值为6,它就是I变量的内 存起始地址。...所以对形参变量pa值(当然值 是一个地址值)的修改并不会改变实参变量p值,因此p的值并没有改变(即p的指向并没有被改变)。 (如果还有疑问,再看一看《第五篇:函数参数的传递》了。)
在上一篇内容中我们介绍了C/C++程序中的内存分区,在C/C++程序中内存从高地址到低地址的分区依次为: 内核空间:存储内核代码,内核代码不能进行读/写操作 栈区:存储函数体内创建的对象,如变量、函数返回值...结构体在进行内存分配时,根据内存对齐的规则,每个成员都会分配到特定的位置,但是柔性数组的大小未知的,如果我们将放在了其它成员的中间,那么位于柔性数组之后的成员要被分配的位置就不可预测了,因此我们需要将大小确定的成员优先放入内存中...四、柔性数组的优势 在上例中,我创建的结构体是由整型指针与柔性数组组成的集合,之所以选择这两个作为结构体成员,是因为它们都能够通过动态函数来申请空间,如下所示: 可以看到,指针成本变量与柔性数组是可以完成同样的工作的...实际上我们从最后的空间释放就可以到,如果采用指针变量的话,在进行空间释放时,我们需要进行两次空间释放,一次是指针变量成员指向的内存空间,一个只是结构体指针变量指向的内存空间,且它们释放的顺序还不能改变。...结语 今天的内容到这里就全部结束了,如果大家喜欢博主的内容,可以点赞、收藏加评论支持一下博主,当然也可以将博主的内容转发给你身边需要的朋友。
如果是C,我们可以用%p来输出变量地址,若是C++,我们可以用static_cast(&a)来输出变量地址,大家若是使用vs,教大家一个小技巧,在调试模式中(F5)下依次单击调试,窗口,...由于我们的main函数不被其他函数调用(注意:不是不可调用,是一般情况下不调用,如果你想挨骂的话…),所以就不能像其他函数一样,在程序运行中获取参数数据,那为什么还要有这个参数呢,实际上,这个参数是程序运行时...其实相当于是调用了exe,exe里面的函数利用参数工作,而exe也同样可以利用参数工作,那么如何输入参数呢,告诉大家几张方法: 1.直接在命令行输入 start 路径 参数1 参数2 参数3 2.我们将编译好的程序...我查找了大量的有关博文,大多数有关博文都有怎么一张图,如果说以前,我可能会同意,但是现在我对图中栈区的向下增长有一些疑惑,就拿我们刚开始数组死循环的内存分配来说,内存两种分配模式,递增,递减,所以我觉得这个图还有待考证...获取函数地址,fun_2 是一个函数名, 调用的话 使用(*fun)() 和fun() 效果是一样的 char * p[]; 指针(样式的)数组 本质是数组 ,将指针进行集合
十、常量 在程序执行过程中,值不发生改变的量称为常量。 mtianyan: C语言的常量可以分为直接常量和符号常量。...由于C语言是没有检查数组长度改变或者数组越界的这个机制,可能会在编辑器中编译并通过,但是结果就不能肯定了,因此还是不要越界或者改变数组的长度 3.数组作为函数参数 数组可以由整个数组当作函数的参数,也可以由数组中的某个元素当作函数的参数...因此,如果能更好地理解内存的模型,以及 C 如何管理内存,就能对程序的工作原理洞若观火,从而使编程能力更上一层楼。 大家真的别认为这是空话,我大一整年都不敢用 C 写上千行的程序也很抗拒写 C。...上面我说,定义一个变量实际就是向计算机申请了一块内存来存放。 那如果我们要想知道变量到底放在哪了呢?可以通过运算符&来取得变量实际的地址,这个值就是变量所占内存块的起始地址。...在这里我想谈几个看起来有点无聊的话题: 为什么我们需要指针?直接用变量名不行吗? 当然可以,但是变量名是有局限的。 变量名的本质是什么?
领取专属 10元无门槛券
手把手带您无忧上云