再议C语言第二节(数组与指针)讲座整理

2024-05-25 15:18

本文主要是介绍再议C语言第二节(数组与指针)讲座整理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

首先先区分一下两个容易混淆的定义:
数组指针是指向数组首元素的地址的指针,其本质为指针(这个指针存放的是数组首地址的地址,相当于2级指针,这个指针不可移动); 指针数组是数组元素为指针的数组,其本质为数组。例如:*p[2]是指针数组,实质是一个数组,里面的两个元素都是指针 []的优先级比*的优先级高,p先与[]结合,形成数组p[2],有两个元素的数组,再与*结合,表示此数组是指针类型的,每个数组元素相当于一个指针变量。
指针数组中的每一个元素均为指针,即有诸形如“*ptr_array[i]”的指针。指针数组中的元素亦可以表示为“*(*(ptr_array+i))”。又因为“()”的优先级较“*”高,且“*”是右结合的,因此可以写作**(ptr_array+i)。由于数组元素均为指针,因此ptr_array[i]是指第i+1个元素的指针。
                                              ————以上摘自百度百科
数组和指针的区别
首先对于编译器而言, 一个数组是一个地址,一个指针是一个地址的地址。 
数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。数组名对应着(而 不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。一般变量在内存单元中存放的是数据,指针变量在内存单元中存放的是地址。无论何种类型的指针都占4个字节的内存空间。 其中void和带有const的指针变量容易出错,void修饰指针代表的是一种不确定类型的指针,任何类型的指针都可以直接赋给它,无需类型转换,但是不能对void指针进行算术操作。当使用带有const的指针时其实有两种意思。一种指的是不能修改指针本身的内容,另一种指的是你不能修改指针指向的内容。先说指向const的指针,它的意思是指针指向的内容是不能被修改的。它有两种写法。
      const int* p; (推荐)
      int const* p;
      第一种可以理解为,p是一个指针,它指向的内容是const int 类型。p本身不用初始化它可以指向任何标示符,但它指向的内容是不能被改变的。
      第二种很容易被理解成是p是一个指向int的const指针(指针本身不能被修改),但这样理解是错误的,它也是表示的是指向const的指针(指针指向的内容是不能被修改的),它跟第一种表达的是一个意思。为了避免混淆推荐大家用第一种。
     再说const指针,它的意思是指针本身的值是不能被修改的。它只有一种写法
      int* const p=一个地址; (因为指针本身的值是不能被修改的所以它必须被初始化)
     这种形式可以被理解为,p是一个指针,这个指针是指向int 的const指针。它指向的值是可以被改变的如*p=3;
     还有一种情况是这个指针本身和它指向的内容都是不能被改变的,请往下看。
      const int* const p=一个地址;
      int const* const p=一个地址;
指向const的指针(指针指向的内容不能被修改)const关健字总是出现在*的左边而const指针(指针本身不能被修改)const关健字总是出现在*的右边,那不用说两个const中间加个*肯定是指针本身和它指向的内容都是不能被改变的。
  这次讲座欢神学长还讲了 左值与右值的概念:
在常见的C风格的语言中,有一些细微的地方是容易被忽视的,如表达式:a=b 这样的表达式在大多数编程语言中都是合法的,它是一个简单的赋值表达式,站在编译器的角度它又是怎么样对待与处理的呢?
      我们先温习一下,“地址”和“地址的内容”两个概念。在编译器看来,赋值运算符两边的a和b并不是两个地位平等的代号。这里的等号“=”并不代表a和b的地位平等,这里符号a的含义是a所代表的地址,习惯上我们称之为左值。而符号b的含义是b所代表的地址的内容,习惯上我们称之为右值,确切的说右值就是除了左值以外的值,他们可能是立即数和变量的某些组合。左值在编译时可知,表示存储结果的地方。通常只有允许修改的左值可以合法用作赋值运算符左边的操作数。所以尽管数组的名字表示“地址”,它是“左值”,但是它不是一个可以修改的左值,所以它也就不能用作赋值运算符的左操作数了,同理,用关键字const修饰的变量也是如此。编译器为每个变量分配一个地址(左值),虽然具体什么时候分配这个地址各个语言的编译器可能有所不同,但是变量在运行时会一直保存于这个地址。
      相对应的,存储于变量中的值(它的右值)只有在运行时才可知。如果需要用到变量中存储的值,编译器就发出指令从指定的地址读入变量值并将它存于寄存器中。也就是说,右值是运行时才会需要去用的实际值。于是"a=b;"的背后发生的事情大致就是,编译器会先检查操作数的合法性,如果操作数合法,就生成如下的指令:取b的右值(可能是一个立即数),将其保存至a的左值(一个地址)。在这里,a作为左值出现,但是实际其作用的是存储a的地址,这条语句的作用就是将这个地址存储的值赋值为b所代表的常量。b作为右值出现的时候就代表的是存储b的地址所存储的值,用语句表达就是*(&b)。先取到地址,再对该地址反引用取得这个地址存储的值。

这篇关于再议C语言第二节(数组与指针)讲座整理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1001870

相关文章

C语言中联合体union的使用

本文编辑整理自: http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=179471 一、前言 “联合体”(union)与“结构体”(struct)有一些相似之处。但两者有本质上的不同。在结构体中,各成员有各自的内存空间, 一个结构变量的总长度是各成员长度之和。而在“联合”中,各成员共享一段内存空间, 一个联合变量

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

大语言模型(LLMs)能够进行推理和规划吗?

大语言模型(LLMs),基本上是经过强化训练的 n-gram 模型,它们在网络规模的语言语料库(实际上,可以说是我们文明的知识库)上进行了训练,展现出了一种超乎预期的语言行为,引发了我们的广泛关注。从训练和操作的角度来看,LLMs 可以被认为是一种巨大的、非真实的记忆库,相当于为我们所有人提供了一个外部的系统 1(见图 1)。然而,它们表面上的多功能性让许多研究者好奇,这些模型是否也能在通常需要系

人工和AI大语言模型成本对比 ai语音模型

这里既有AI,又有生活大道理,无数渺小的思考填满了一生。 上一专题搭建了一套GMM-HMM系统,来识别连续0123456789的英文语音。 但若不是仅针对数字,而是所有普通词汇,可能达到十几万个词,解码过程将非常复杂,识别结果组合太多,识别结果不会理想。因此只有声学模型是完全不够的,需要引入语言模型来约束识别结果。让“今天天气很好”的概率高于“今天天汽很好”的概率,得到声学模型概率高,又符合表达

C语言 将“China”译成密码

将“China”译成密码,密码规律是:用原来的字母后面的第4个字母代替原来的字母。例如,字母“A”后面的第4个字母是“E”,用“E”代替“A”。因此,“China”应译为“Glmre”。编译程序用付赋初值的方法使c1,c2,c3,c4,c5这五个变量的值分别为“C”,“h”,“i”,“n”,“a”,经过运算,使c1,c2,c3,c4,c5分别变成“G”,“l”,“m”,“r”,“e”。分别用put

C语言入门系列:探秘二级指针与多级指针的奇妙世界

文章目录 一,指针的回忆杀1,指针的概念2,指针的声明和赋值3,指针的使用3.1 直接给指针变量赋值3.2 通过*运算符读写指针指向的内存3.2.1 读3.2.2 写 二,二级指针详解1,定义2,示例说明3,二级指针与一级指针、普通变量的关系3.1,与一级指针的关系3.2,与普通变量的关系,示例说明 4,二级指针的常见用途5,二级指针扩展到多级指针 小结 C语言的学习之旅中,二级

剑指offer(C++)--数组中只出现一次的数字

题目 一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。 class Solution {public:void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {int len = data.size();if(len<2)return;int one = 0;for(int i

利用结构体作为函数参数时结构体指针的定义

在利用结构体作为函数的参数进行传递时,容易犯的一个错误是将一个野指针传给函数导致错误。 #include <stdio.h>#include <math.h>#include <malloc.h>#define MAXSIZE 10typedef struct {int r[MAXSIZE]; //用于存储要排序的数组,r[0]作为哨兵或者临时变量int length;

【LinuxC语言】select轮询

文章目录 前言select函数详解selectfd_set类型一个小问题select函数使用步骤改进服务器代码select服务器示例代码 总结 前言 在Linux C语言编程中,我们经常需要处理多个I/O操作。然而,如果我们为每个I/O操作创建一个线程,那么当I/O操作数量增加时,线程管理将变得复杂且效率低下。这就是我们需要select轮询的地方。select是一种高效的I/

拓扑排序——C语言

拓扑排序(Topological Sorting)是一种用于有向无环图(DAG)的排序算法,其输出是图中所有顶点的线性排序,使得对于每条有向边 (u, v),顶点 u 在 v 之前出现。拓扑排序确定了项目网络图中的起始事件和终止事件,也就是顶点的执行顺序。         因为是有向无环图,所以拓扑排序的作用其实就是把先发生的排序在前面,后发生的排序到后面。 例如现在我们有一个