指针
一讲到指针,不少同学就会觉得云里雾里。首先要明白,指针和地址是一个概念;然后明白指针和指针变量的区别。
先理解地址和数据,想象内存里面是一个个的小盒子,每个盒子对应一个编号,这个编号就是地址,盒子里存放的就是数据。
&
是取地址运算符,如有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、如果p
是int *
指针变量,那么*&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的成员函数。