c语言指针

【C语言】- 指向一维数组元素的指针!学习不需要带口罩,只要带脑子

 ̄綄美尐妖づ 提交于 2020-02-17 22:47:46
前面我们已经学习了指针,如果指针存储了某个变量的地址,我们就可以说指针指向这个变量。数组及其数组元素都占有存储空间,都有自己的地址,因此指针变量可以指向整个数组,也可以指向数组元素。 一、用指针指向一维数组的元素 输出结果: 说明已经通过指针间接修改了数组元素的值,跟指向一个普通int类型变量是一样的。 由于数组名代表着数组的首地址,即a == &a[0],因此第8行代码等价于: // 让指针指向数组的第0个元素 p = a; 内存分析图如下,一个指针变量占用2个字节,一个int类型的数组元素占用2个字节 二、用指针遍历数组元素 1.最普通的遍历方式是用数组下标来遍历元素 输出结果: 2.接下来我们用指针来遍历数组元素 先定义一个指针,指向数组的第一个元素 p的值是a[0]的地址,因此,现在我们利用指针p只能访问数组的第0个元素a[0],用*p就可取出a[0]的值1。要想访问其他元素,就必须拿到元素的地址,可以发现每个元素的地址差值为2,因为在16位编译器环境下,一个int类型的变量占用2个字节。现在只是知道a[0]的地址值为p,怎么根据a[0]的地址获取其他元素的地址呢?其实非常简单,p+1就是a[1]的地址。注意了,这里的p+1代表着p的值加2,并不是p的值加1,比如p的值为ffc3,p+1则为ffc5,而非ffc4。依次类推,p+2就是a[2]的地址ffc7,p+3就是a[3

我的大厂面试经历

被刻印的时光 ゝ 提交于 2020-02-17 17:31:41
2020-02-17 10:53:03 在这里提供一下自己复习的东西吧,我也就把这个东西给搞了一遍,然后面试基本没啥问题了,如果问的很深的话,那就只能只求多福了兄弟!其中可能有一些错误或者由于编译环境有差异请大家自动忽略这些错误。 1:信号的生命周期? 信号产生-》信号在进程中注册-》信号在进程中的注销-》执行信号处理函数 2:信号的产生方式? (1)当用户按某些终端键时产生信号(2)硬件异常产生信号【内存非法访问】(3)软件异常产生信号【某一个条件达到时】(4)调用kill函数产生信号【接受和发送的所有者必须相同,或者发送的进程所有者必须为超级用户】(5)运行kill命令产生信号 3:信号处理方式? (1)执行默认处理方式(2)忽略处理(3)执行用户自定义的函数 4:如何消除隐式转换? 使用explicit关键字进行修饰 5:重载,重写和隐藏的区别? 重载:即函数重载 重写【覆盖】:即用于虚函数 隐藏:只要派生类的函数名与基类相同就会隐藏 6:volatile表示什么?有什么作用? 易变的,不会被编译器进行优化,让程序取数据直接去内存中的。 7:Static_cast<>,dynamic_cast<>,const_cast<>,reinterpret_cast<>的各自作用和使用环境? Static_cast:能完成大部分转换功能,但是并不确保安全 Const_cast

函数调用约定

ε祈祈猫儿з 提交于 2020-02-16 22:17:48
在C语言中,假设我们有这样的一个函数: int function(int a,int b) 调用时只要用result = function(1,2)这样的方式就可以使用这个函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一个问题就凸现出来:在CPU中,计算机没有办法知道一个函数调用需要多少个、什么样的参数,也没有硬件可以保存这些参数。也就是说,计算机不知道怎么给这个函数传递参数,传递参数的工作必须由函数调用者和函数本身来协调。为此,计算机提供了一种被称为栈的数据结构来支持参数传递。 栈是一种先进后出的数据结构,栈有一个存储区、一个栈顶指针。栈顶指针指向堆栈中第一个可用的数据项(被称为栈顶)。用户可以在栈顶上方向栈中加入数据,这个操作被称为压栈(Push),压栈以后,栈顶自动变成新加入数据项的位置,栈顶指针也随之修改。用户也可以从堆栈中取走栈顶,称为弹出栈(pop),弹出栈后,栈顶下的一个元素变成栈顶,栈顶指针随之修改。 函数调用时,调用者依次把参数压栈,然后调用函数,函数被调用以后,在堆栈中取得数据,并进行计算。函数计算结束以后,或者调用者、或者函数本身修改堆栈,使堆栈恢复原装。 在参数传递中,有两个很重要的问题必须得到明确说明: 当参数个数多于一个时,按照什么顺序把参数压入堆栈 函数调用后,由谁来把堆栈恢复原装 在高级语言中,通过函数调用约定来说明这两个问题

查找链表中间节点 -- C语言

喜夏-厌秋 提交于 2020-02-16 19:06:50
算法思路 1. 求链表总长度,取得一半数,遍历链表一半的数量,取得中间节点 2. 用两个指针,一个每次都移动一回,一个每两次移动一回,当第一个指针遍历完链表,后一个指针就正好指向中间 代码实现1 st_dataNode * getListMidNode(st_dataNode * head){ if(NULL == head){ printf("%s: param error\n",__func__); return NULL; } int len = 0; int m = 0; st_dataNode * mid = NULL; len = getListLen(head); m = (len / 2 - 1); // 注意应该建议,因为下标是从0开始的 if(m == 0){ return head; } mid = head; while(m > 0){ mid = mid->next; m--; } return mid; } 代码实现2 /* 通过一次遍历来完成寻找中间节点 */ st_dataNode * getListMidNode2(st_dataNode * head){ if(NULL == head){ printf("%s: param error\n",__func__); return NULL; } int step1 = 0, step2 = 0;

Linux Device Driver 3rd 下

做~自己de王妃 提交于 2020-02-16 09:34:54
第十一章 内核的数据类型 坚持使用严格的数据类型,并且使用-Wall -Wstrict-prototypes选项编译可以防止大多数的代码缺陷 内核使用的数据类型主要分为三大类: ① 标准C语言类型,类似int ② 类似u32这样有确定大小的类型 ③ 类似pid_t这样用于特定内核对象的类型 使用标准C语言类型 在不同的体系架构上,普通C语言的数据类型所占空间的大小并不相同。 Linux系统中,指针和long整型的大小总是相同的。 为数据项分配确定的空间大小 有时内核代码需要特定大小的数据项,多半是用来匹配预定义的二进制结构或者和用户口空间进行通讯或者通过在结构体中插入"填白 padding"字段 来对齐数据。 当需要知道自己的数据大小时,内核提供了下列数据类型,定义在<asm/types.h>中 ① u8; 无符号字节8位 ② u16; 无符号字 16位 ③ u32; 无符号32位 ④ u64; 无符号64位 相应的有符号类型也存在,只需将名字中的u用s替换就可以了。 接口特定的类型 内核中最常用的数据类型由typedef声明,这样可以防止出现任何移植性问题。 当需要打印一些接口特定的数据类型时,最行之有效的方法就是将其强制转换成可能的最大类型(通常是long或者unsigned long),然后用相应格式。 因为格式和类型相匹配,而且也不会丢失数据位

c语言指针

[亡魂溺海] 提交于 2020-02-15 07:50:02
1.计算机会为变量在存储器中分配空间。 2.局部变量位于栈中。 3.全局变量位于全局变量段。 4.指针只是一个保存“存储器”地址的变量。 5.&运算符可以找到变量的地址。 6.*运算符可以读取存储器地址中的内容 7.*运算符还可以设置存储器地址中的内容 如: int x = 3; int *address = &x; *address中保存的就是x变量的存储地址 通过&提取x的地址,保存在了*address中 #include <stdio.h> int main() { int x = 3; int *address = &x; // 打印结果:一样相等 printf("%p----%p", *address, x); return 0; } 讲解: &运算符用于接收一个数据并获取地址 而 *运算符则是用于接收一个地址并保存数据 c语言中的指针在其他语言中叫法为引用类型,*就算对于地址的解析,生成具体的值 相当于其他语言中的,引用地址的具体值 C语言中声明一个指针变量: 指针变量是什么呢? 答:用来保存内存地址的变量,相当于其他语言的引入地址传给函数假参 声明指针变量: int *名称(或标识符) = &变量; 如: int x = 3; int *address = &x; &提取了变量x的地址并赋值给了address变量,*就是接收地址来表示这是一个指针变量 这时如果你去改变

C@指针&数组

拟墨画扇 提交于 2020-02-15 00:54:03
一、指针数组和数组指针 1、字面意思理解指针数组和数组指针 指针数组的实质就是一个数组,这个数组中存储的内容全部是指针变量 数组指针的实质是一个指针,这个指针指向的是一个数组。 2、分析指针数组和数组指针的表达式 (1)int*p[5]; int(*p)[5]; int *(p[5]); (2)一般规律 :int *p;(p是一个指针) int p[5] ;(p是一个数组) 总结:我们定义一个符号时,关键在于首先找到定义的符号是谁(第一步找核心) 其次再来看谁跟核心最近,谁跟核心结合(第二部:找结合) 以后继续向外扩展(第三步:继续向外结合直到符号完) (3)核心结合 - 如何核心和 “ * ”结合,表示核心是指针, - 如果核心和“[ ]”结合表示核心是数组, - 如果核心和小括号“()”结合,表示核心是函数 (4)一般规律来分析3个符号 例子1: int *p[5]; (“[ ]”的优先级比“ * ”优先级高) p是一个数组,数组有5个元素,数组中的元素都是指针,指针指向的元素类型是int类型,整个符号是一个指针数组。 例子2: int (*p)[5]; 核心是p,p是一个指针,因为p被用括号和星好强制结合起来了。指针指向一个数组,数组有5个元素,数组中存在的元素是int类型; 例子3: int *(p[5]); 这里 加小括号没有意义,没起到左右,没有小括号,也是p与[

java与C++的区别

不问归期 提交于 2020-02-14 17:46:42
“作为一名C++程序员,我们早已掌握了面向对象程序设计的基本概念,而且Java的语法无疑是非常熟悉的。事实上,Java本来就是从C++衍生出来的。”   然而,C++和Java之间仍存在一些显著的差异。可以这样说,这些差异代表着技术的极大进步。一旦我们弄清楚了这些差异,就会理解为什么说Java是一种优秀的程序设计语言。本附录将引导大家认识用于区分Java和C++的一些重要特征。   (1) 最大的障碍在于速度:解释过的Java要比C的执行速度慢上约20倍。无论什么都不能阻止Java语言进行编译。写作本书的时候,刚刚出现了一些准实时编译器,它们能显著加快速度。当然,我们完全有理由认为会出现适用于更多流行平台的纯固有编译器,但假若没有那些编译器,由于速度的限制,必须有些问题是Java不能解决的。   (2) 和C++一样,Java也提供了两种类型的注释。   (3) 所有东西都必须置入一个类。不存在全局函数或者全局数据。如果想获得与全局函数等价的功能,可考虑将static方法和static数据置入一个类里。注意没有象结构、枚举或者联合这一类的东西,一切只有“类”(Class)!   (4) 所有方法都是在类的主体定义的。所以用C++的眼光看,似乎所有函数都已嵌入,但实情并非如何(嵌入的问题在后面讲述)。   (5) 在Java中,类定义采取几乎和C++一样的形式。但没有标志结束的分号

2019春第七周学习&编辑总结

你说的曾经没有我的故事 提交于 2020-02-13 14:36:26
这个作业属于哪个课程 C语言程序设计二 这个作业要求在哪里 2019春季学期第七周作业 我的课程目标 掌握数组名作为函数参数的用法,理解指针、数组和地址之间的关系,理解指针和数组可以实现相同的操作。。 这个作业在哪个具体方面帮助我实现目标 题目让我学会如何操作运用指针 参考文献 c语言程序设计第3版 基础题 6-2 每个单词的最后一个字母改成大写 (10 分) 函数fun的功能是:将p所指字符串中每个单词的最后一个字母改成大写。(这里的“单词”是指由空格隔开的字符串)。 函数接口定义: void fun( char *p ); 其中 p 是用户传入的参数。函数将 p所指字符串中每个单词的最后一个字母改成大写。 裁判测试程序样例: #include <stdio.h> void fun( char *p ); int main() { char chrstr[64]; int d ; gets(chrstr); d=strlen(chrstr) ; chrstr[d] = ' ' ; chrstr[d+1] = 0 ; fun(chrstr); printf("\nAfter changing: %s\n", chrstr); return 0; } /* 请在这里填写答案 */ 输入样例: my friend is happy 输出样例: After changing: mY

数据结构之链表定义及基本操作实现

对着背影说爱祢 提交于 2020-02-13 14:06:30
  在我上一篇的博客中说过,数据结构的线性结构中有连续存储结构和离散存储结构,这次就写一写学习离散存储结构——链表的小总结。   首先说一下链表的定义:链表是物理存储单元上非连续、非顺序的存储结构,链表的结点间通过指针相连,每个结点只对应有一个前驱结点和一个后继结点,其中,首结点没有前驱结点,尾节点没有后继结点。上述表述共同构成了对链表的定义。   接下来说一下链表的结构:链表由头结点+有效节点构成,其中有效节点由分为首结点、普通节点、尾节点。 头结点:链表中有效结点前面的结点,头结点并不存放实际数据,仅仅是为了方便对链表的操作。 头指针:头结点并没有什么实际的含义,仅仅是为了方便对链表的操作,而头指针,顾名思义,就是指向头结点的指针。我们通过头指针指向的头结点的指针域对链表进行操作。 首结点:链表的第一个有效的结点。 尾结点:链表中最后一个有效的结点,尾结点的指针域为空。   链表已经学习完毕,那么接下来就是要说一下链表的构成——结点。因为链表是一张离散存储的结构,所以就需要通过地址去访问,那么久需要在结点中保存下一个结点的地址。还是用到c语言中的结构体。 1 //定义链表的节点 2 typedef struct Node{ 3 //数据域 4 int data; 5 //指针域 6 struct Node * pNext; 7 }NODE,*PNODE;   结点定义完毕后