指针

一讲到指针,不少同学就会觉得云里雾里。首先要明白,指针和地址是一个概念;然后明白指针和指针变量的区别。

先理解地址和数据,想象内存里面是一个个的小盒子,每个盒子对应一个编号,这个编号就是地址,盒子里存放的就是数据。

&是取地址运算符,如有int a;即有一个小盒子里面存放的数据起名叫a&a就是取a的地址,即该盒子的编号。

*(地址)是取值运算符,这里*是解引用操作符,可以理解成打开对应地址编号的盒子,取出里面的数据。*(&a) 就是打开a对应的小盒子,取出里面的数据,即*(&a)a等价。

我们定义一个指针变量int *p; p是指针变量,专门用来存放地址。

int *p=&a;相当于int *p; p=&a;

p存放的是a的地址,*p也等价于 a。指针变量p既然是变量,也同变量a一样对应一个小盒子,也有一个地址编号,&p就是取指针p的地址。这样就好理解二级指针了。

*p**p的区别

int *p :一级指针,表示p所指向的地址里面存放的是一个int类型的值

int **p :二级指针,表示p所指向的地址里面存放的是一个指向int类型的指针(即p指向的地址里面存放的是一个指向int的一级指针)

例:

int a=5;     //定义整形变量
int *p=&a;   //定义一个指针指向这个变量
int **p1=&p; //定义一个二级指针指向p指针
/*   那么取出5的方式都有哪些呢? */
printf("a=%d",a);
printf("a=%d",*p);
printf("a=%d",**p1);

以上3行输出的值都是5 。

回过来看标题问题:*&p&*p

根据运算优先级,*&p 等价于*(&p)&*p 等价于&(*p)

1、如果pint *指针变量,那么*&p = p&*p = p,都是p,但还没定义p指向哪,存的是谁的地址。

2、如果p是一个int变量,那么*&p = p;&*p是非法的,因为*p非法。

比如int p =10;那么*&p = *(&p) = p = 10(即从p的地址取值),而&*p = &(*p) 则非法,因为p=10*10是取内存地址为10的值,这在c语言中是不合法的。


(1)const int *p;

int const *p; //含义是指向常量的指针,指针的常量值不可以修改

两者相同,p是一个指向整形常亮的指针,可以修改指针的值,但不能修改指针所指向的值。int b = 5;

int c = 3;

const int *p=&b;

*p=6; //错误,不能通过指针修改所指向的值;

p=&c; //正确,可以修改指针的值

(2)int * const p; //含义是常量指针,p的值不可以修改

p是一个指针,指针p是常量,它的值无法修改,但是可以修改p所指向的整型的值。int b = 5;

int c = 3;

int *const p = &b;

*p = 6; //正确,可以修改指针所值向的值

p =&c; //错误,不可以修改指针的值

(3)const int * const p;

无论是指针本身还是它所指向的值都是常量。

简单的判断的方法:

如果const在 * 的左侧,则const用来修饰指针所指向的变量,即指针指向位常量;

如果const位于 * 的右侧,则const就是修饰指针本身,即指针本身就是常量。

3.const用于函数的形参void foo(const int * p)

const用于形参时说明了形参在函数内部不会被改变。这种形式通常用于数组形式的参数中模拟传值调用。这也是const最有用之处,限定函数的形参,这样该函数将不会修改实参指针所指向的数据。这里需要注意得的是,是函数不应该去修改而不是不能修改。

4.声明常量的其他方法

C语言中可以用enum类型和#define宏来定义常量#define MAX_SIZE 10;

int const max_size =10;

此处使用#define比使用const变量更好。

只要允许使用字面值常量的地方都可以使用前者,比如声明数组的长度。

const变量只能用于允许使用变量的地方。

关于c语言中const的使用方法就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

文章知识点与官方知识档案匹配,可进一步学习相关知识

const的用法总结

const在C/C++中有很多的用法,现将const的用法做如下总结。
1、const修饰变量
const修饰变量,可以使变量具有常属性,也就是该变量在以后的使用中其值都不能进行改变。

在这里要注意的一点就是const修饰的变量要进行初始化。
2、const和指针
用const修饰指针有以下几种情况

3、保护函数参数不被改变
用const修身函数的参数,可以保证该参数的值在函数内部不被改变。
但是一般const修饰的参数都有哪些呢?
一般用引用或者传地址的方式给函数传递一个参数,如果在函数体内对该参数进行修改,那么就会连实参的值一并进行修改。
4、const修饰函数返回值
const修饰函数的返回值,防止函数的返回值被修改

但是这里要注意的是,必须也用const修饰的变量来接收这个函数的返回值。
5、const修饰类成员函数
const可以修饰类成员函数,防止类成员函数中除了static成员之外的其他成员被修改。


6、const修饰类的成员变量
类的成员变量可以分为静态的和非静态的,如果const修饰的是静态的成员变量,可以在构造函数中对该变量进行初始化;如果const修饰的是静态的成员变量,则需要在类外对该变量进行初始化。

7、const和#define的区别

define A 10

const int A=10;
上面两条语句的作用是一样的,但是后面一条语句可以节省内存空间,这是为什么呢?
原因在于在程序中多次使用const类型的变量,只会在第一次分配内存,但是如果使用#define定义的宏,则每次都会分配内存,这样看来使用const会节省很多空间。
8、const和extern
file1.cpp中, const int a;
file2.cpp中, extern int a; //错误,无法调用,
说明const修饰大的变量只能在该程序的本文件中使用,不能在该程序的其他文件中使用。
要想const定义的对象变量能被其他文件调用,定义时必须使用extern修饰为
extern const int val;

void function() const{}

// test1107.cpp : 定义控制台应用程序的入口点。
//
 
#include "stdafx.h"
#include <iostream>
using namespace std;
 
class aa{
    int num;
public:
    aa(){
        int b =10;
        num = b;
    };
    void out1(){
        cout<<num<<endl;
    }
    void out2() const{
        cout<<num<<endl;
    }
    void out3() const{
        num+=10; //出错,const函数不能修改其数据成员
        cout<<num<<endl;
    }
 
};
int _tmain(int argc, _TCHAR* argv[])
{
    aa a1;
    a1.out1();
    a1.out2();
    a1.out3();
    const aa a2;
    a2.out1(); // 错误,const的成员 不能访问非const的函数
    a2.out2();
    a2.out3();
    return 0;
}

在类成员函数的声明和定义中,

const的函数不能对其数据成员进行修改操作。

const的对象,不能引用非const的成员函数。

Last modification:May 5, 2022
如果觉得我的文章对你有用,请帮忙点一下上面的广告