4、C语言面试笔试--内存操作-指针
文章目录
- 1、指针变量
- 1.1 基本概念
- 1.2 指针运算
- 1.3 面试题
- 2、 常量和常量指针
- 2.1 字面常量和符号常量
- 2.2 const指针常量
- 2.2.1 常量指针
- 2.2.2 常量指针变量
- 2.2.3 指针常量
- 3、总结
- 1、多级指针
- 2、void * 的含义与void **
- 面试 1
- 面试2
- 面试3
1、指针变量
1.1 基本概念
与普通变量不同,指针定义时的数据类型并不是指针变量本身的数据类型,而是其所指目标数据的数据类型,称之为基类型。指针初始化的一般形式如下:
数据类型 * 指针名=初始地址值;
其中指针变量名前的仅仅是一个说明符,表示其后的名称是一个指针变量名。这里的并没有访问指针目标的含义。
有关指针的注意事项如下:
在定义指针变量后系统为该指针变量分配一个地址大小的存储单元,指针变量中存放的是地址值。特别注意,无论指针变量的基类型是何种数据类型,占用的内存大小都是相同的,例如“char *p1;double *p2”,在32位系统中有sizeof(p1)=sizeof(p2)=4,即p1和p2两个指针变量均占用4个字节。
尽管任何指针变量中存放的都是地址值,但一个指针变量只能存放相同基类型的数据地址。
一个指针变量本身占用的空间很小,但可以指向一整块很大的连续控件,这个一整块的连续控件通常是采用动态分配函数malloc分配,存放在堆空间中。
指针和地址有什么区别?指针意味着已经有一个指针变量存在,其值是一个地址,指针变量本身也有地址,而地址本身并不代表任何变量存在,地址仅表示内存空间的一个位置。
1.2 指针运算
指针与整数的加减:p±n 以该地址量为基点的其阿芳或后方的第n个数据的地址。例如,对于基类型为type的指针p,p±n的结果是地址值p±n*sizeof(type),其中sizeof(type)称之为步长,显然步长是与指针变量的基类型有关。
指针++和–:++代表运算后指向下一个数据的位置,指针–代表运算后指向上一个数据的位置,运算后指针地址值的变化量取决于滋镇的基类型。
两个指针相减:并非他们的两个地址值直接做减法运算,而是两指针所指地址之间的数据个数。
NULL(与0等效):一旦某个指针赋值为NULL,就将该指针值设置为0,表示真真变量没有意义,就不能再存储数据,如int *p=NULL, *p=10,是错误的。
也就是说我们一定要记住,指针运算指的是针对指针的基类型进行的运算,而不是地址的加加减减
野指针:一个指针变量的值(地址值)为垃圾值的指针变量称之为野指针;
产生野指针的原因及其解决办法如下:
指针变量定义时没有被初始化,解决办法是在定义指针时初始化,可以是具体的地址值,也可以是NULL。
指针p被free或者delete之后没有置为NULL,后面又去使用。解决办法就是释放指针指向的内存空间,然后将指针指向NULL。
指针操作超越了所指变量的作用域,解决办法是在所指变量的作用域结束之前释放掉变量的纸质空间,并让指针指向NULL。
1.3 面试题
以下程序的输出是()
int *pint=0;
pint+=6;
printf("%d\n",pint);
答案:24
首先题中在定义指针的时候p=0,也就是相当于p=NULL.
其次,+6,其实也就是相当于+6*sizeof(pint);所以输出的地址值是24
以下程序的输出结果是什么?
#include <stdio.h>
void main()
{int*p1,*p2;int value;p1=(int *)0x500;p2=(int *)0x508;value=p2-p1;printf("%d\n",value);
}
输出结果是2
解析:8/4=2
以下程序执行会输出什么?
#include<stdio.h>
int main()
{char *p="Linux";printf("[%c]",*p++);printf("[%c]",*p);return 0;}
请问执行Test函数会有什么样的结果?
#include<stdio.h>
#include <malloc.h>
#include <string.h>void test (void)
{char *str=(char*)malloc(100);strcpy(str,"hello");free(str);if(str!=NULL){strcpy(str,"world");printf(str);}
}void main()
{test();}
因为执行free(str)语句后,str会成为野指针,其中地址值是不为NULL的垃圾地址,将world字符串存放在垃圾地址空间中,后果难以预料,非常危险。
2、 常量和常量指针
2.1 字面常量和符号常量
常量分为字面常量和符号常量。字面常量只能引用不能修改,字面常量通常保存在静态数据区,由p指针指向它,不能通过p指针修改该常量。
char *p="abc";
像上面这种写法,在C语言中是在太多了,只能由p指针指向它,不能通过p指针修改该常量。
其中“abc”为常量,程序员最好采用const char *p="abc"定义。这样在后面执行 *p='x’就会发生错误,也能一眼找到原因。
另外,如果p指向的常量字符串不是通过malloc函数分配的,执行free§,会导致程序崩溃。
使用const定义,const的意思是“一个不能被改变的变量”
注意对于define只是替换语句,不是指令,所以没有;分号,但是,const是指令,所以有;分号。
const常量有数据类型,而宏常量没有数据类型。
可以把const常量的地址赋给指针变量,例如:const int i=10;int *p=&i ;
C中默认这种隐式转换,但是在C++中,“cannot convert from ‘const int *’ to ‘int *’”编译错误,需要采用强制转换,即 int *p=(int *)&i ;
2.2 const指针常量
3类:常量指针、常量指针变量、指针变量
2.2.1 常量指针
在定义指针时用const关键字进行修饰,称为const指针常量。
const char *p
用const修饰 * 时称为常量指针,这样就不能通过该指针变量修改指向的内容。
2.2.2 常量指针变量
在C++中还可以用const修饰指针变量名,称之为常量指针变量。
char *const p;
表示指针p是一个常量指针变量,p的值不能再法神改变,所以必须初始化,一旦初始化,p不能指向其他数据,但可以通过指针p修改所指的内容。
#include<stdio.h>
#include <malloc.h>
#include <string.h>
int main()
{int a=10;
int *p=&a;
int * const q=p;
*q=56;printf("shuchu %d",*p);
printf("chuchu %d",*q);
}
解释:也就是常量指针变量是在指针的前面加上const,这样,这个指针变量其实也就是初始值代表的指针变量,所以更改这个指针变量的内容,也会导致赋予的指针变量的内容改变。
2.2.3 指针常量
指针变量即为常量指针,又是常量指针变量,例如:
const char * const p;
指针常量,前一个const修饰指针变量的定义,后一个const修饰变量名,指针p必须初始化,并且p的值和指向的内容都不能修改。
#include<stdio.h>
#include <malloc.h>
#include <string.h>
int main()
{int a=10;
int *p=&a;
const int * const q=p;
*q=56;printf("shuchu %d",*p);
printf("chuchu %d",*q);
}
如上图,编译错误
3、总结
注意,
const int *p=&a;
int const *p=&a;
以上这两个表达式是相同的,都是常量指针,两个const 都是针对*p。
所以值不能改变,而指向地址可以改变。
而
int * const p ;
const是去修饰 p指针的,所以指针地址不能改变,但是指向的内容值是可以改变的,故称之为常量指针变量。
最后一种
const int * const p
是同时针对地址和值,所以都不能改变。
1、多级指针
在C中指针还可以指向另外的指针,这种指向指针的指针就称之为多级指针。(这一点,只要理解了,指针变量存储了指向的地址,另外指针变量自身也有自己的地址)
int x=10;
int *p=&x;
int **pp=&p;
int ***ppp=&pp; //三级指针
理解:也就是说,**p取p的地址,(注意不是,p指向的地址,如果写成p,那就成了p的指向地址了,所以需要写成 **pp=&p)
2、void * 的含义与void **
void *p;
int *p;
p1=p2;
"无类型”可以包含“有类型”,void *可以指向任何类型的数据。
void ** 可以看做 (void * *)
也就是类型void * 的类型转换。
(void *) 相当于一个转换成一个无类型的地址。
int n=10;
int *p=& n;
printf("%d\n",*(void ** )p);
(void **)p 相当于(int *) (void *p)
也就是说,( void ** )p
相当于转换成空指针类型,再强制类型转成p的基类型。
面试 1
int main()
{char * p="hello ,world";return 0;
}
上面程序中p和“hello,world”分别存储在内存中的哪个区域?
p指针变量是在栈控件分配的,
它指向的常量字符串“hello,world”是在静态数据区分配的。
面试2
以下程序有什么问题?
#include<stdio.h>
#include <malloc.h>
#include <string.h>
void main()
{int i,*p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++){*(p+i)=i+1;printf("%d\n",*(p+i));}
p++;free(p);
}
由于释放程序的时候,free释放的不是分配时候的起始地址,所以会导致程序崩溃。
把p++注释掉即可
面试3
以下程序有什么问题
#include <stdio.h>
#include <malloc.h>
void main()
{int i,*p,**pp=&p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++)*(p+i)=i+1;printf("%d\n",**(++pp));free(p);}
对于表达式**(++pp),先执行++pp,是增加pp的地址值,此时pp的地址值加1,会指向一个垃圾地址,应该是让p的地址加1,所以应该是 **++pp
#include <stdio.h>
#include <malloc.h>t
void main()
{int i,*p,**pp=&p;p=(int *)malloc(3*sizeof(int));for(i=0;i<3;i++)*(p+i)=i+1;printf("%d\n",++**pp);free(p);}
4、C语言面试笔试--内存操作-指针相关推荐
- c语言关于内存笔试,4、C语言面试笔试--内存操作-指针
文章目录1.指针变量1.1 基本概念1.2 指针运算1.3 面试题2. 常量和常量指针2.1 字面常量和符号常量2.2 const指针常量2.2.1 常量指针2.2.2 常量指针变量2.2.3 指针常 ...
- 1、C语言面试笔试---变量定义和声明
文章目录 1.背景 2.变量定义和声明 1.局部变量和全局变量 2.变量的存储类别 3.例题 4.内存泄漏 1.背景 2019秋招马上开始了,今天已经是7月30号了,赶紧刷刷C语言,争取在8月中旬刷完 ...
- 2、C语言面试笔试---运算符和表达式
文章目录 背景 1.运算符和表达式 1.1自增自减运算符++与-- 1.2 C语言符号的优先级 1.3 类型转换 1.4 顺序点的概念 1.5 贪心法 2.面试笔试例题 背景 1.运算符和表达式 1. ...
- 5、C语言面试笔试--数据组织--数组
文章目录 1.一维数组 2.一维数组和指针的区别 3.sizeof的使用 4.二维数组 5.用一级指针访问二维数组元素 6.字符数组和字符串数组 7.strlen函数与sizeof运算符号的差别 8. ...
- 3、C语言面试笔试--控制结构
文章目录 背景 1.选择控制结构 2.面试例题 3.循环控制语句 4.面试题 背景 现在进入C语言的控制结构,这篇完成后,C语言的基础操作也就算完结了.控制语句主要分为选择控制语句和循环控制语句. 1 ...
- 返回指针_C语言面试中的问题指针和引用的使用场景?
先解决两个疑问: ◆ 指针和引用的不同之处是什么? ◆ 何时用用指针?何时用引用? 01 指针和引用的不同之处 看如下代码: 指针是用来表示内存地址的,而指针这个整数正是被指向的变量地址. 而引用就 ...
- 单片机c语言面试笔试,c语言面试题集(单片机)..doc
c语言面试题集(单片机). c语言面试题集(单片机) 1.预处理器(Preprocessor)1. 用预处理指令#define 声明一个常数,用以表明1年中有多少秒(忽略闰年问题) #define S ...
- 【C 语言】结构体 ( 指针运算与指针内存操作 | 结构体成员偏移量计算 )
文章目录 一.指针运算 与 指针内存操作 二.结构体偏移量计算 一.指针运算 与 指针内存操作 指针变量算术运算 ( 指针可以是任意值 ) : 指针 是一个变量 , 如果对指针进行 算术 / 逻辑 等 ...
- STM32学习第三课:STM32 c语言学习基础3(内存操作、指针、结构指针)
1.内存操作 在对内存操作头疼的时候我发现了这篇神奇的文章,拜读之后豁然开朗心生崇拜 数据指针 在嵌入式系统的编程中,常常要求在特定的内存单元读写内容,汇编有对应的MOV指令,而除C/C++以外的其它 ...
最新文章
- Matlab概率统计编程指南
- x shell 配置 和相关注意点(vm相关注意点)
- 根据工作年限预测工资python代码实现
- html5中加入音频,使用HTML5在网页中嵌入音频和视频播放的基本方法
- arcengine 加载地图不显示_用LSV下载城市地图、全省地图教程
- 移植JRTPLib到Montavista
- Android面试题总结加强再加强版(三)
- 大整数减法(信息学奥赛一本通-T1169)
- 数据结构及算法总结(概述)
- 赚钱这件事并不难,难的是你没有搞懂这个思维?
- Node.js路径操作
- Fixjs——显示基类DisplayObject
- TCP协议的滑动窗口协议以及流量控制
- (转)区块链:CITA
- Unomi 成为 Apache 软件基金会顶级项目
- 谭浩强《C语言程序设计第五版》第二章学习笔记
- DH参数(Denavit-Hartenberg parameters)
- PS使用:利用PS去除图片中的多余文字
- Unreal4+Qt+Plugins(unrealcv)安装教程
- 报道 | 香港科技大学三十周年校庆红鸟之夜庆祝晚宴圆满落幕