返回目录:https://blog.csdn.net/chen1083376511/article/details/82723709
问题:
问:什么是指针?
答:指针是用来存储内存地址的变量,它指向单个对象的地址,除了void指针类型之外,指针的数据类型与所指向地址的变量数据类型须保持一致。不论指针指向的数据类型是哪一种,他本身永远是整型,保存的是地址。
分析:
int *ip;
const intt *ip2;
ip和ip2都是指针变量名,int表示该指针变量的类型是整型。*表示指针变量。
-------------------------------------------------------
问题:
问:如何初始化指针并对其赋值?
答:指针的初始化就是给指针赋初值,&符号可以用来获取对象的内存地址,并且赋值给指针变量。指针变量的初始化和赋值都可以通过运算符”=“来实现。
分析:
指针可以初始化为0(NULL),,没有初始化的指针指向是随机的,它可能导致随机修改了程序的值。
变量的数据类型和指针变量的数据类型要保持一致。所以以下代码是错误的:
int a=123;
long *p;
p=&a;
------------------------------------------------------------
问题:
问:是否可以确定指针指向一个对象?
答:指针用于指向对象,一个指针只指向一个对象的内存地址。
---------------------------------------------------------------
问题:
问:指针和迭代器主要的区别?
答:指针和迭代器都是提供其所指对象的间接访问。区别是:指针用于指向单个对象,而迭代器只用于访问容器内的元素。
------------------------------------------------------------
问题:
问:运用好指针有哪些优点?
答:
1.提高程序的编译效率和执行速度。
2.通过指针可使用主调函数和被调函数之间共享变量或数据结构,便于实现双向数据通讯。
3.可以实现动态的存储分配。
4.便于表示各种数据结构,编写高质量的程序。
5.使表达式变得紧凑和简洁。
---------------------------------------------------------------------------
问题:
问:使用指针不恰当的会出现哪些问题?举些例子。
答:
1.访问数组和其他数据结构时越界。
2.自动变量消失后被引用。
3.堆上分配的内存释放后被引用。
4.内存分配之前解引用。
-------------------------------------------------------------
问题:
问:指针是一种特殊的变量,只能用来保存地址。这句话对么?
答:对的。
-----------------------------------------------------------------
+问题(慧通面试):
问:一个32位的机器,该机器的指针是多少位?
答:4位。指针变量的位数根据机器地址总线位数而定,对于32位地址总线的机器指针的位数就是4个字节。
分析:
系统为指针变量分配一定的内存空间,无论指针变量指向何种类型的数据,指针变量的长度一般是一个机器的字长。所以,在32位的机器就是4,但是其他位数的机器就不一定是这个结果了。(注意:分配的内存与编译器有重大的相关,比如在win32环境下编译,在操作系统64位环境下,仍然是4字节。)
---------------------------------------------------------------------
+问题(慧通面试):
问:字符指针、浮点数指针、函数指针这三种类型的变量哪个占用的内存最大?为什么?
答:三者占用的内存一样大,因为所有指针变量所占的内存单元数量都是相同的。在32位平台下,三个不同类型的指针占用的内存都是4个字节。
---------------------------------------------------------------------
问题:
问:用变量a给出下面的声明和定义
a.一个整型数。 答:int a;
b.一个指向整型数的指针。 答:int *a;
c.一个指向指针的指针,它指向的指针是指向一个整型数。 答:int **a;
d.一个有10个整型数的数组。 答:int a[10];
e.一个有10个指针的数组,该指针是指向一个整型数的。 答:int *a[10];
f.一个指向有10个整型数数组的指针。 答:int (*a)[10];
g.一个指向函数的指针,该函数有一个整型参数并返回一个整型数。 答:int (*a)(int);
h.一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数。 答: int (*a[10])(int);
分析:
分析同下一道面试题。
---------------------------------------------------------------------
问题:
问:各种复杂指针的声明,下面的数据声明都代表什么意思?
a.float(**fa)[10]
答:fa是一个二级指针,它指向的是一个一维数组的指针,数组的元素都是float类型。
b.double *(*sp)[10]
答:sp是一个指针,它指向一个一维数组,该数组元素都是double*。
c.double (*arr[10])()
答:arr是一个数组,arr有10个元素,元素都是函数的指针,指向的函数类型是没有参数且返回double的函数
d.int *((*a)[10])
答:与“int *(a)[10]”一样的,a是一维数组的指针。
e.long (*fun)(int)
答:函数指针。
f. int (*(*f)(int,int))(int)
答:f是一个函数的指针,指向的函数的类型是有两个int 参并且返回一个函数指针的函数,返回的函数指针指向一个int参数且返回int类型的函数。
分析:
笔者对于指针声明总结了一下技巧,有重要的两点:
第一点,用优先级来分析指针声明语句,优先级从高到低为:()>[]>*。第二点,从里到外分析,比如(*a),a先与*结合,再到().
接下来让笔者为大家分析一下怎么看懂多种指针的声明,比如最难的最后面那个指针声明:int (*(*f)(int,int))(int)
1.找到变量f,由于*在()里面,f先与*号结合,然后是(),说明f是一个指针变量。即:(*f)
2.f再与右边的(int,int)结合,并且(int,int)中有两个参数,说明f指向一个有两个int参数的函数,即f是一个函数指针,(*f)(int ,int)。
3.如果觉得太长,难理解,笔者在这里把(*f)(int ,int)当作一个变量名N,N先与*号结合,然后是外面的(),即(*N)是一个指针(确切地说函数指针N返回类型不是指针类型,通过(*N)之后,这个函数指针的返回类型是指针。 )。
4.(*N)与右边(int)结合,并且(int)有一个参数,说明(*N)指向有一个int参数的函数,即函数指针的返回类型指针指向一个有一个int参数的函数。
5.由于最左边是int,则函数指针返回类型指针指向的是返回值为int型且有一个int参数的函数。
其实笔者认为在f点当中也可以这么说:含有返回两个int参数的函数指针返回类型指针指向一个int参数且返回int类型的函数。
只是这样说,易于理解。但是标准的说法是,把整个声明语句都拆分来讲的,比如函数指针也要拆开来说明,新手因为复杂理解比较困难而已。但是没关系,这并不重要,在程序设计时一般是不会使用这么复杂的定义的,因为这使程序的可读性变差,在这里只是为了学会分析即可。
--------------------------------------------------------------------------
问题:
问:指针指向的变量,那么请说说指针与数值运算的问题。
答:指针可能会指向意想不到的内存地址。
using namespace std;
int main()
{
int a = 100;
int b = 200;
int *p = &a;
p = p - 1;//由于整型变量占4个字节,指针应该移动1*4
cout << &a << endl;
cout << &b << endl;
cout << p << endl;//此时指针指向了变量b,也有可能不是
printf("%d\n",&a);
printf("%d\n", &b);
printf("%d\n", p);
//注意,指针与数值进行运算适合运用在在数组,因为数组的元素是连续排列的。
//而在这里,由于编译器处理内存不一样,可能要指向的地址就不会准确(在内存管理机制中,变量之间可能会有空隙空间,所以会留出空隙地址)。
return 0;
}
------------------------------------------------------------------------
问题:
问:指针与变量的类型不一致时,请问怎么解决这个问题?
答:由于指针与变量的类型不一致,指针会指向不正确的内存地址,需要强制转换成和指向的对象的数据类型保持一致。
分析:
#include<iostream>
using namespace std;
int main()
{
//当p的类型和a不一样时
char a[15]= "mygirlislovely";
int *p = (int *)&a;
p++;//由于指针p是整型类型的,它移动4个字节,指向下一个地址会,指向了字符数组中的“r”元素
cout << (char)*p << endl;//需要强制转换char类型可以输出字符
return 0;
}
----------------------------------------------------------------------------------
问题:
问:分析一下,下面中定义的指针,说出指针类型、指针所指向的类型、指针的值和指针本身所占据的内存区?
答:
int a= 4;
int *p= &a;
指针类型:int* 指针所指向的类型:int 指针的值:4
----------
char *p;
指针类型:char* 指针所指向的类型:char
-----------
int **p;
指针类型:int** 指针所指向的类型:int
------------
int (*p)[3];
指针类型:int (*)[3] 指针所指向的类型:int ()[3]
------------
指针本身所占据的内存区:以上指针本身所占的内存大小,在32位程序中,为4个字节。
分析:
指针类型:把指针声明语句的指针名字去掉,就是指针类型,例如int *p;指针类型为int*。
指针所指向的类型:把指针声明语句的指针名字和名字左边的*号都去掉。例如:int *p;指针所指向的类型是int。
指针的值:指针所指向的变量的值。
------------------------------------------------------------------
+问题:
问:什么是野指针?
答:“野指针”是在定义指针后没有对其进行初始化,或者指针指向的内存被释放,而指针没有被设置为NULL。野指针随机地指向一个地址,使用这个指针进行操作时,就会更改该内存的数据,造成程序数据的破坏,严重威胁着程序的安全。
-------------------------------------------------------------------
问题:
问:什么是悬浮指针?
答:当所指向的对象被释放或者收回,但是对该指针没有做任何的修改,以至于该指针仍旧指向已经回收的内存地址,是悬浮指针,也称作是迷途指针,是造成野指针的一部分,属于野指针。
分析:
假如在进程A中,释放了指针所指向的内存M,然后操作系统把原来一部分已经释放掉的内存M重新分配给进程B。如果通过进程A中的迷途指针修改内存M的数据,由于内存M后来已经分配给进程B的,这将会产生无法预料的后果。这种错误是不易被发现的。
----------------------------------------------------------------------
+问题:
问:下面代码会编译通过吗?
char *tabHeader = "Sound";
*tabHeader = 'L';
printf("%s\n", tabHeader);
答:
//字符串字面值作为常量,在vs编译器的环境下不能修改,出错。
//在gcc环境下可以修改,即改变的是新的一块内存地址(拷贝一份),原来的常量的值并没有被改变。但是char前面加上const,编译也不会通过,
char *tabHeader = "Sound";
*tabHeader = 'L';//tabHeader指向的是常量的地址,不能修改
printf("%s\n", tabHeader);
---------------------------------------------------------------------------
问题:
问+答:请根据以下代码讲述一下“*p,*p(++),(*p)++,*++p”之间的区别以及含义?
void main()
{
int b[5] = {9, 2, 3, 4, 5 };
int *p = b;
for (int j = 0; j <4; j++)
{
cout <<b[j+1]<< "指针指向的内容:" << *++p << endl;//先p++,后*p
}
p = b;//指针指向恢复原来数组的首地址,因为上一次循环会改变p的地址值
cout <<endl;
for (int i=0;i<5;i++)
{
//*p(++)语法错误
cout << b[i]<<"指针指向的内容:" << *p++ << endl;//先*p,后p++
}
p = b;
cout << endl;
//分开执行是因为下面循环的*p的内容改变
for (int m = 0; m < 5; m++)
{
cout << "值:" << (*p)++ << endl;//指针所指向的内容加1
}
}
------------------------------------------------------------------------------
问题:
问:观察下面代码,说说“pp++”编译之后,为何没有输出结果?
char a[6] = "hello";
char *p = a;
char **pp = &p;
printf("%c\n", **pp);
pp++;
printf("%c\n", **pp);
答:因为pp++之后,pp指向的变量不再是p,指向的是p变量前面的一块未知内存,非法。