C/C++语言基础知识 之 引用和指针

  1. 关于引用
    引入是C++引入的新语言特性。
1   int &rn = a;
-----------------------------------------------
2   int* p = &a;
3   int* &pa = p;
4   (*pa)++;
5   pa = &b;
6   (*pa)++;

L1:声明rn为变量a的一个引用,不需要为rn另外开辟内存单元。rn和a占内存中的同一个存储单元,他们具有同一个地址。

L3:声明p的一个指针引用pa。
L4: 将pa指向的内容加1,实际上是p指向的内容加1,也就是a+1。
L5: 将pa指向变量b的地址。由于pa是p的引用,所以此时p也指向了b。
L6: 将pa指向的内容加1,实际上是p指向的内容加1,也就是b+1。

  1. 指针和引用有什么区别?

区别如下:
(1)初始化要求不同。引用在创建的时候必须初始化,即引用到一个有效的对象;而指针在定义的时候不必初始化,可以在定义后面的任何地方赋值。
(2)可修改性不同。引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,给引用赋值并不是改变它和原始对象的绑定关系;指针在任何时候都可以改变为指向另一个对象。
(3)不存在NULL引用,必须指向某个确定的对象。
(4)由于引用不会指向NULL值,所以使用之前不需要测试它的合法性。因此,使用引用的代码效率比使用指针的要高。
(5)如果应用场景为“一旦指向一个对象后就不会改变指向”,那么应该使用引用;如果应用场景为“有可能指向NULL或不同时刻指向不同对象”,那么使用指针。

  1. 为什么传指针比传引用安全?

由于不存在NULL引用,并且引用一旦被初始化为指向一个对象,它就不能被改变为另一个对象的引用,因此引用很安全。

对于指针来说,它可以随时指向别的对象,并且可以不被初始化,或为NULL,所以不安全。
const指针仍然存在空指针,并且有可能产生野指针。

  1. 复杂指针的声明
    一个有十个指针的数组,指针是指向整型数的:int *a[10];
    一个指向有十个整型数数组的指针:int (*a)[10];
    一个指向函数的指针,该函数有一个整型参数并返回一个整型数:int (*a)(int);
    一个有10个指针的数组,指针指向函数,函数有一个整型参数并返回一个整型数:int (*a[10])(int);
  2. 根据代码输出结果—用指针赋值
#include <stdio.h>

int main(void)
{
	char a[] = "hello, world";
	char *ptr = a;
	printf("%c\n", *(ptr+4));//输出o
	printf("%c\n", ptr[4]);//输出o
	printf("%c\n", a[4]);//输出o
	printf("%c\n", *(a+4));//输出o

	*(ptr+4) += 1;
	printf("%s\n",a);//hellp, world
	return 0;
}
  1. 指针加减操作
#include <stdio.h>

int main(void)
{
	char a[5] = {1,2,3,4,5}char *ptr = (int *)(&a+1);
	
	printf("%d\n", *(a+1));//输出2
	printf("%d\n",*(ptr-1));//输出5
	return 0;
}

我觉得这是个非常容易出错的地方。

ptr是一个int的指针&a+1,即取a的地址,该地址的值加sizeof(a)的值,即&a+5sizeof(int),也就是a[5]的地址,已越界。
a与&a的地址是一样的,但是意思不一样。a是数组首地址,也就是a[0]的地址;&a是对象(数组)的首地址,a+1是数组下一元素的地址,即a[1];而&a+1是下一个对象的地址,即a[5]。
ptr指向a[5],并且ptr是char
类型,所以ptr-1指向a[4]。

  1. 指针的比较
#include <iostream>
using namespace std;

int main(void)
{
	char str1[]       = "abc";
	char str2[]       = "abc";
	const char str3[] = "abc";
	const char str4[] = "abc";
	const char* str5  = "abc";
	const char* str6  = "abc";
	char* str7        = "abc";
	char* str8        = "abc";

	cout << (str1 == str2) <<endl;//输出0
	cout << (str3 == str4) <<endl;//输出0
	cout << (str5 == str6) <<endl;//输出1
	cout << (str6 == str7) <<endl;//输出1
	cout << (str7 == str8) <<endl;//输出1

	return 0;
	
}

数组str1 str2 str3和str4都是在栈中分配的,内存中的内容都是"abc\0",但是它们的位置是不同的。
指针str5 str6 str7和str8也是在栈中分配的,它们都指向"abc"字符串,注意"abc"存放在数据区,所以str5 str6 str7和str8其实指向同一块数据区的内存。

  1. 指针常量和常量指针的区别?

常量指针 就是指向常量的指针,它所指向的地址的内容是不可修改的。
指针常量,就是指针的常量。它是不可改变地址的指针,但是可以对它所指向的内容进行修改。

  1. const关键字在指针声明时的作用?
1   char* const p1;
2   char const *p2;
3   const char *p3;
4   const char *const p4;

如果const位于 * 号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量; 如果const位于 *
号的右侧,const就是用来修饰指针本身,即指针本身是常量。

p1是指针常量,它本身不能被修改,指向的内容可以被修改。 p2和p3是常量指针,它本身可以被修改,但是指向的内容不能被修改。
p4本身是常量,并且它指向的内容也不可以被修改。

  1. 指针数组与数组指针的区别?

指针数组表示它是一个数组,并且数组中的每一个元素都是指针。
数组指针表示它是一个指针,并且指向了一个数组。

  1. 函数指针与指针函数的区别?

指针函数:是返回指针类型的函数。 函数指针:指向函数地址的指针。
事实上,每一个函数,即使它不带有返回某种类型的指针,它本身都有一个入口地址,该地址相当于一个指针。比如函数返回一个整型值,实际上也相当于返回一个指针变量的值,不过这时的变量是函数本身而已,而整个函数相当于一个变量。
函数指针是指向函数的指针变量,有了指向函数的指针变量后,可用该指针变量调用函数,就如同用指针变量可引用其它类型的的变量一样。

  1. 什么是“野指针”?

野指针不是NULL指针,而是指向垃圾内存的指针。 其成因主要有两种: 指针变量没有被初始化,可以置为NULL或者指向合法的内存;
指针被free或delete后,没有置为NULL。

  1. 内存的分配方式?

(1)从静态存储区域分配。内存在程序编译的时候就已经分配好,这块内存在程序的整个运行期间都存在,例如全局变量。
(2)在栈上创建。在函数执行时,函数内的局部变量都可以在栈上创建,函数执行结束时,这些存储单元自动释放。处理器的指令集中有关于栈内存的分配运算,因此效率很高,但是分配的内存容量有限。
(3)从堆上分配,亦称动态内存分配。程序在运行的时候用malloc或new申请任意多少的内存,程序员自己负责在何时去free或delete释放内存。动态内存的生存期由我们自己决定,使用非常灵活,但是问题也最多。

  1. 指针和句柄有什么区别?
    windows给每个使用GlobalAlloc等函数声明的内存区域指定一个句柄,句柄是一种指向指针的指针。

(1)句柄所指的可以是一个很复杂的结构,并且很有可能是与系统有关的。比如说线程的句柄,它指向的就是一个类或者结构,它和系统有很密切的关系。当一个线程由于不可预料的原因而终止时,系统就可以返回它所占用的资料,如CPU、内存等。反过来想可以知道,这个句柄中的某一些项,是与系统进行交互的。由于Windows系统是一个多任务的系统,它随时都可能要分配、回收和重组内存。
(2)指针也可以指向一个复杂的结构,但是通常是由用户定义的,所以必须的工作都要用户完成,特别是在删除的时候。

备注:
上述内容是本人学习《C和C++程序员面试秘笈》的读书笔记

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值