A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 王元18611727076 中级黑马   /  2015-10-26 23:20  /  932 人查看  /  1 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

//-------------------------------指针

内存单元的指针和内存单元的内容是两个不同的概念。

内存单元的编号也叫做地址。既然根据内存单元的编号或地址就可以找到所需的内存单元,所以通常也把这个地址称为指针。


总结:对于一个内存单元来说,单元的地址即为指针,其中存放的数据才是该单元的内容。

使用指针好处

a.为函数提供修改调用变量的灵活手段;
b.让函数有多个返回值
c.可以改善某些子程序的效率
>>在数据传递时,如果数据块较大(比如说数据缓冲区或比较大的结构),这时就可以使用指针 传递地址而不是实际数据,即提高传输速度,又节省大量内存。


3、变量的存取方式 存取方式分为两种:直接存取和间接存取

int a = 3; 直接存取:变量的赋值和取值(通过变量名进行存取值)

int b = a;
printf("%d",b);

间接存取:通过指针(地址)间接操作完成。

int *b = &a;
printf("%d",*b);

//------------------------------指针变量

1、指针变量 在C语言中,允许用一个变量来存放指针,这种变量称为指针变量。
因此,一个指针变量的值就是某个内存单元的地址或称为某内存单元的指针。

注意: 严格意义上说,指针是一个地址,是一个常量指针变量是存放一个地址,是一个变量。

定义一个指针变量

对指针变量的定义包括三个内容:
1)指针类型说明,即定义变量为一个指针变量;
2)指针变量名;
3)变量值(指针)

其一般形式为: 类型说明符 *变量名;

注意:

1)在定义指针时,“*”号表示定义的变量是指针变量,
变量的值只能存放地址。
2)一个类型的指针只能指向同类型的变量,不能指向其他类型的变量。


//-------------------------------初始化和引用

指针变量初始化的方法有两种:
定义的同时进行初始化和先定义后初始化

1)定义的同时进行初始化

int a = 5; int *p = &a;

2)先定义后初始化

int a; int *p; p=&a;



3)把指针初始化为NULL int *p=NULL;

int *p = NULL;   //   还是不能用这个指针变量    暂时把p有所指向



int *q=0; 不合法的初始化:




注意点
1、多个指针变量可以指向同一个地址 int a = 5;
2、指针的指向是可以改变的
3、指针没有初始化里面是一个垃圾值,这时候我们这是一个野指针, 如果操作一个野指针
1)可能会导致程序崩溃
2)访问你不该访问数据 所以指针必须初始化才可以访问其所指向存储区域


两个有关的运算符:
& :取地址运算符;
* :指针运算符(或称“间接访问” 运算符)。

&变量名;

*指针变量名 //获取指针变量指向的存储空间的内容 如&a表示变量a的地址,&b表示变量b的地址。变量本身必须预先说明。


关于*的使用注意:
1)在定义变量的时候 * 是一个类型说明符,说明定义的这个变量是一个指针变量

int a = 5;

int *p = &a;

int *p1 = p;

2)在不是定义变量的时候 *是一个操作符,访问指针所指向存储空间

int x = *p;


//------------------------野指针

int *p;   //  没有任何指向的指针为野指针

*p = 10;

//------------------------确定类型

*修饰什么,就代表是什么的指针,原则:先确定变量的类型(根据符号优先级)

int *p;

int *p[3];    //指针数组  -->   首先这是一个数组,数组里面存的是指针(地址)

int (*p)[3];  //数组指针  -->   指向数组(数组第一个元素的地址)的指针

//数组指针  简单理解:指向数组的指针 (指向数组第一个元素的地址的指针)

xxx指针     指向xxx的指针

//--------------------函数实现两变量交换
分析:
常规做法不能实现变量值的交换。
指针地址交换也不能实现
指针指向的值交换可以实现。

void swapNum2(int *a,int *b){
   
    int temp;
   
    temp = *a;
   
    *a = *b;
   
    *b = temp;
   
}

主调函数一定要传同一数据类型的地址


//----------------------指针常见的应用场景
1)在被调函数中可以修改主调函数中变量的值
void change(int*num)
{
    *num = 10;
}

2)函数返回多个值
void sumAndMinusAndJiAndShang(int num1,int num2,int *sum,int *minus,int *ji,float *shang)
{
    *sum = num1 + num2;
    *minus = num1 - num2;
    *ji = num1 * num2;
    *shang = (float)num1 / num2;
}



//------------------------二级指针
如果一个指针变量存放的又是另一个指针变量的地址,则称这个指针变量为指向指针(地址)的指针变量。也称为“二级指针”

int a = 5;

int * p = &a;

int ** p1 = &p;


p---指向a的地址

*p---a的地址对应的值----也就是5

p1--指针变量p的地址

*p1 --->  p的地址所对应的内容  ---   a的地址

* *p1  ---->   * a的地址  -->  *p  --> 5



//-------------------------指针为什么要区分类型
一个指针变量所占用的内存空间是固定的。

虽然所有的指针都只占8个字节,但不同类型的变量却占不同的字节数。

结论:定义什么类型的指针就应该指向什么类型的变量。

#include <stdio.h>

/*   验证过程

arr[0][0]=0x7fff560d8be0  arr[0][1]=0x7fff560d8be4  arr[0][2]=0x7fff560d8be8
arr[1][0]=0x7fff560d8bec  arr[1][1]=0x7fff560d8bf0  arr[1][2]=0x7fff560d8bf4


arr = 0x7fff5ab9fbe0             -->   arr是数组名  代表  数组第一个元素的地址
arr+1 = 0x7fff5ab9fbec           -->   数组第一个元素(因为是一个二维数组,第一个元素的地址又是这个一维数组的)的地址   以第一个元素的长度+1

&arr[0][0] = 0x7fff5ab9fbe0      -->  第一个元素的地址
&arr[0][0]+1 = 0x7fff5ab9fbe4


arr[0] = 0x7fff5e393be0          -->  行地址   二维数组内第一个元素(这个元素是个一维数组)的地址   以第一行元素的长度+1
arr[1] = 0x7fff5e393bec          -->  第二行地址

&arr = 0x7fff560d8e0            -->  二维数组的地址
&arr+1 = 0x7fff560d8e0          -->  越界了的地址

*/

int main(){
   
    int arr[2][3] = {1,2,3,4,5,6};
   
    for (int i = 0; i < 2; i++) {
        
        for (int j = 0; j < 3; j++) {
            
            printf("&arr[%d][%d]=%p  ",i,j,&arr[i][j]);
            
        }
        
        printf("\n");
    }
   
    printf("\narr = %p\n",arr);      // &arr[0][0]=0x7fff560d8be0
   
    printf("\narr+1 = %p\n",arr+1);  // &arr[1][0]=0x7fff560d8bec
   
    printf("\narr[0] = %p\n",arr[0]);
   
    printf("\narr[1] = %p\n",arr[1]);
   
   
    return 0;
}

1 个回复

倒序浏览
赞一个,很给力
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马