温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

C/C++指针是什么及怎么使用

发布时间:2022-08-27 11:21:58 来源:亿速云 阅读:115 作者:iii 栏目:开发技术

这篇文章主要介绍“C/C++指针是什么及怎么使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“C/C++指针是什么及怎么使用”文章能帮助大家解决问题。

    什么是指针

    C/C++语言拥有在程序运行时获得变量的地址和操作地址的能力,这种用来操作地址的特殊类型变量被称作指针。

    翻译翻译什么tmd叫tmd指针!

    变量或常量的指针存储的数据是 :对应的变量或常量在内存中的地址。

    图解:

    C/C++指针是什么及怎么使用

    此时 我们定义三个指针 p1, p2, p3 分别指向a, b, c ,那么p1中存储的数据是变量a所占用内存的首地址:0x00;

    b和c中存储的数据是什么呢? 没错,就是0x02和0x04。

    显然。若要知道变量a的值,首先读取指针p1中的数据0x00,然后读取内存0x00和0x01中的数据就可以了。这个时候,会出现一个问题:怎么才能确定究竟要读取几个单位内存中的数据呢?毕竟p1中只存储了0x00呀。这个时候 ,指针的类型就发挥了作用。举个例子:如果定义的指针是int类型的,那么读取的时候自动从指针中存储的初值向后读取4个字节;float类型的指针就是读取8个字节。这样就可以既完整又不多余的取出所需要的数据了。

    总结一下一个指针的两个要素:指针类型和指针所指变量的初地址。

    定义指针变量

    指针在定义的时候最好直接初始化,否则可能出现意想不到的结果。

    @定义一个指向变量的指针。

    /*定义一个指向int类型变量a的指针p*/
    int a = 3;
    int * p;	
    p = &a;	//把a的地址赋值给p;
    /*下面的语句最好不要用!!!!*/
    p = &28;	//这也是可以的,p指向的地址中存储的数据是28.
    /*可以用下面的语句代替上面的语句*/
    *p = 28;

    间接引用指针

    间接引用操作符也是 *

    *p 取出p指向的内存空间中的值。

    所以区分定义或是引用指针可能有些麻烦。

    只有同类型的指针和变量才能通过 * 和 & 互相建立关系。

    int a = 0;
    int temp;
    int * p = &a;
    /*指针的间接引用*/
    cout<< *p;	//输出结果是0
    /*以下两种表达等价*/
    *p = 3;	//把3赋值给a
    a = 3;
    /*以下两种表达效果相同。都是把变量a赋值给temp*/
    temp = a;
    temp = *p;	//temp被赋值为0
    /* 以下表达是错误的*/
    float f = 3.1;
    int * p = &f;	//error,指针类型与变量类型不匹配

    常or常常

    这个部分本来应该在定义指针变量里,但是因为需要指针的间接引用作为铺垫,所以把它单独拿出来了

    我们先区分一组概念:常量、指向常量的指针、常指针以及指向常量的常指针。

    1.常量:顾名思义不发生改变的量,想必大家是熟悉的。

    2.指向常量的指针:只限制间接访问操作,不限制指针指向的值本身的操作规范。

    3.常指针:指针中存储的地址一经初始化就不能改变了,也就是说常指针只能指向一个固定的地址,但是地址中存储的数据是可以改变的哦~

    4.指向常量的常指针:根据上面三个概念大家应该可以理解了,就是指针中存储的地址和该地址中的数据皆不可更改。

    例如:

    int b = 4;
    const int a = 5;	//定义一个常量a。
    /*注意观察以下三个定义中const的位置*/
    const int *p = &a;	//定义一个指向常量的指针p,指向常量a。
    p = &b;	//这个也是没问题的哦
    *p = 6;	//error,这个间接访问操作是不可以。 
    int * const p2 = &b;//定义一个常指针p2
    *p2 = 6;	//这个是可以的,注意区分和上面的区别
    const int * const p3 = &a;	//指向常量的常指针p3
    /* emm我也不知道该注释点什么,自行体会吧~*/
    *p = 11;	//error,因为p指向的是常量,常量的值不可更改
    *p2 = 2;	//true,p2是常指针,指向的地址不变,但地址中的值可以更改
    *p3 = 4;	//error
    p3 = &b;	//error

    指向指针的指针

    指针本质上也是一个变量或常量,那么指针也是有地址的,而指向这些地址的指针被称为指向指针的指针。

    int a = 25;
    int * p  = &a;
    int pp = &p;	//true,pp指向的地址中存储的是指针p的地址。

    指针与数组

    一个数组的数组名就是一个常指针。

    int arr[] = {5,4,6,9,8,3};

    arr就是一个指针,而且指向数组的第一个元素arr[0]。

    指针数组:

    char * arr[] ={"this is", "a", "C++ !"};

    在此提及一下字符串常量:

    char * a 
    /*
    双引号的作用:
    	在字符串结尾加一个\0,并分配内存空间,返回首地址。
    */
    a = "dshfw";	

    指针的运算

    指针只能支持 + 和 - 的运算,但这已经足够满足大多数指针操作的需求了。

    /*接下来以数组为例,只介绍加法 ,减法同理*/
    int arr[] = {5,4,6,9,8,3};
    cout<< *p;	//输出结果为5
    cout<< *(p+1);	//输出结果为4
    /*打印整个数组*/
    for(int *p = arr; p < arr+5; ++p)
    {
    	cout<< *p<<' ';
    }
    cout<<endl;

    堆内存分配

    C语言

    /*函数原型*/
    void * malloc(size_t size);
    /*使用:开辟5个int类型变量的存储空间,返回首地址*/
    /**/
    int *arr;
    if(arr = (int *) malloc(5 *sizeof(int)) == NULL)
    {
    	exit(1);
    }
    /*释放堆内存*/
    free(arr);

    C++语言

    注意释放数组内存空间时,delete后有[] !!!

    /*申请一个5个元素的数组空间*/
    int * arr = new int[5];
    delete[] arr;
    /*申请一个变量的空间*/
    int * arr = new int;
    delete arr;

    指针与函数

    函数名和数组名一样都是一个指针,有时我们需要把函数名作为参数传入其他函数中。

    数组名作为函数的入口参数

    arr[] = {4,6,9,8,5,3,2,7,5};
    /*两种不同的写法均可以*/
    void Sort_Shell(int arr[], int n)
    {
    /*code*/
    }
    void Sort_Shell(int * arr, int n)
    {
    /*code*/
    }
    /*下面这种是不可以的!!!*/
    void Sort_Shell(int * arr[], int n)
    {
    /*code*/
    }

    举个小小的例子

    /*来个小小的希尔排序算法*/
    void Sort_Shell(int arr[], int n)
    {
    	int gap = n / 2;
    	for(; gap > 0; gap /= 2)
    	{
    		for(int i = gap; i <n; ++i)
    		{
    			int temp = a[i];
    			int j = i;
    			while(j >= gap&& temp < arr[j -  gap])
    			{
    				a[j] = a[j - gap];
    				j -=gap;
    			}
    			a[j] = temp;
    		}
    	}
    }

    开了个小差,接下来回归正题,我们的指针。

    函数名作为参数传入其他函数

    static bool cmp(int a, int b)
    {
    	return a < b;
    }
    void show(bool * b)
    {
    	if( &b)
    	{
    		cout<< true;
    	}
    	else
    	{
    		cout<<false;
    	}
    }

    使用指针修改函数参数

    首先来看个例子:

    void swip(int a, int b)
    {
    	int c = a;
    	a = b;
    	b = c;	
    }
    int main()
    {
    	int a = 5, b = 6;
    	swip(a, b);
    	cout<<a<<' '<<b;
    }

    输出结果:5 6

    并未达到交换的效果,因为函数内部对形参的修改并不能反映到上层的main函数中。

    此时我们可以通过指针作为函数的入口参数来实现预期的功能。

    void swip(int * a, int* b)
    {
    	int c = *a;
    	*a = *b;
    	*b = c;	
    }
    int main()
    {
    	int a = 5, b = 6;
    	swip(&a, &b);
    	cout<<a<<' '<<b;
    }

    输出结果:6 5

    传递函数的指针虽然能达到预期效果,但是确实以破坏函数的黑盒为代价,可读性差,调试困难。

    有没有什么更好的办法呢?接下来 引用登场了。

    变量的引用作为函数的参数

    void swip(int &a, int &b)
    {
    	int c = a;
    	a = b;
    	b = c;	
    }
    int main()
    {
    	int a = 5, b = 6;
    	swip(a, b);
    	cout<<a<<' '<<b;
    }

    输出结果:6 5

    两个常用的字符串函数

    • strcmp() :用于比较字符串的大小。

    • strcpy() :复制字符串。

    //函数原型
    int strcmp(const char * arr1, const char * arr2);
    //使用举例:
    char arr1[] = "dfetf";
    char arr2[] = "cfefef";
    int b = strcmp(arr1, arr2);

    输出b的值是大于0 的。

    关于“C/C++指针是什么及怎么使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注亿速云行业资讯频道,小编每天都会为大家更新不同的知识点。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    AI