3、指针

  • 内存的存储是以一个字节为一个编号,也就是8位合在一起给一个编号,不是0,1就给编号。内存分为很多个单元,每个单元就会分配一个编号。

  • 地址
    内存单元的一个编号。而指针和地址一个概念的。也就是说指针就是地址

# include <stdio.h>
/*指针可以是函数返回一个以上的值:
第一个error是数据类型不符合,不能相互转换。*q代表的是整形,因为*q代表的是以q的地址为内容的变量。而p是地址(int *)类型。第二个error同样有错,因为q没有赋值。
*/
int main(void)
{
    int * p; //p是变量的名字, int * 表示p变量存放的是int类型变量的地址
    int i = 3;

    p = &i;  //OK
    //p = i; //error,因为类型不一致,p只能存放int类型变量的地址,不能存放int类型变量的值
    //p = 55; //error 原因同上

    return 0;
}
1-1 变量
  • 普通变量:只能存放一个值。
  • 指针变量:同样是一个变量,==但是指针变量存放其他变量的地址==。
# include <stdio.h>
/*
p是变量的名字, int * 表示p变量存放的是int类型变量的地址
int * p; 不表示定义了一个名字叫做*p的变量
int * p; 应该这样理解: p是变量名, p变量的数据类型是 int *类型
所谓int * 类型 实际就是存放int变量地址的类型 
*/
int main(void)
{
    int * p; 
    int i = 3;
    int j;

    p = &i;
/*
1. p保存了i的地址, 因此p指向i
2. p不是i,i也不是p,更准确的说: 修改p的值不影响i的值,修改i的值也不会影响p的值
3. 如果一个指针变量指向了某个普通变量, *指针变量  就完全等同于  普通变量
4.如果p是个指针变量,并且p存放了普通变量i的地址则p指向了普通变量i。
*p  就完全等同于i或者说:  在所有出现*p的地方都可以替换成i
在所有出现i的地方都可以替换成*p,*p 就是以p的内容为地址的变量
*/
    j = *p;  //等价于 j = i;
    printf("i = %d, j = %d\n", i, j);

    return 0;
}

注意
1、p代表的是p所指向的那个变量。在上代码中p和i是同一个东西,但是p和p不是同一个东西。
2、 int
p是一个声明,开头的int* 是他的数据类型。P是变量的名字。不能理解我定义了一个整形变量,这个整形变量的名字叫做p。所谓int 类型,实际就是存放int 变量地址的类型。
3、*p代表的是以p的内容为地址的变量。

解析:p的内容是一个地址,在代码中,p的内容就是i的地址,*p其指向的变量当然就是i变量了。


2-1 指针和指针变量:
  1. 指针就是地址,地址就是指针。
  2. ==地址就是内存单元的编号。==
  3. 指针变量:就是存放内存单元编号的变量。而指针只是一个值,这个值是内存单元的一个编号。指针变量才是一个变量,他里面才可以存放数据。指针的本质就是一个操作受限的非负整数。指针不能进行算术运算-相加 乘 除。但是能相减。
  4. 指针和指针变量是两个不同的概念,但是需要注意的是,通常我们在叙述时会把指针变量简称为指针,实际他们含义并不一样。
3-1 指针的定义
  • 地址:内存单元的编号,是一个从0开始的非负整数

==范围:cpu对内存是通过控制、数据、地址三条总线来进行控制的。==
1665530-20190624120603566-365886059.png

  • 控制:cup会先把内存中的数据读入,进行处理后,在返回给内存,然后内存在把数据写入硬盘。

  • 数据:用于数据的传输,不管是把内存中的数据发送给cpu,还是把cpu的数据写如内存条,都是由数据线来完成的,但是数据传输的方向则是由控制线来控制的。

  • 地址:地址线则是确定数据要写入内存中的那个单元。所谓的一个单元就是一个字节。

1665530-20190624120839603-45455668.png

一条地址总线能控制2的1次方,一般的机器有32个地址线,最终能够控制2的32个单元,而每个单元是八位,而最终我们的内存能够存储2的32次方*8位。

常见的错误1

# include <stdio.h>
/*
Int *p:p只能存放int类型的地址。
P = & i:把i的地址赋给p。然后p就指向了i,*p就等于i。其实就是
1:该语句保存了i的地址。
2:p保存了i的地址,所以p指向i。
3:p既然指向i,*p就是i。
*p:表示以p的内容为地址的变量。
*p:p是有指向的,p里面是个垃圾值,*p则是说以p的内容为地址的变量。
因为不知道p的值是多少,所以不知道*p到底代表的是那个变量。而*p = i,i=5,
最终的结果就是把5赋给了一个所不知道的单元。
*/
int main(void)
{
    int * p;           //*p 表示以p的内容为地址的变量。
    int i = 5;

    *p = i;
    printf("%d\n", *p);

    return 0;
}
# include <stdio.h>
/*
q的空间是属于本程序的,所以本程序可以读写q的内容, 
但是如果q内部是垃圾值,则本程序不能读写*q的内容
因为此时*q所代表的内存单元的控制权限并没有分配给本程序
所以本程序运行到13行时就会立即出错
*/
int main(void)
{
    int i = 5;
    int * p;
    int * q;

    p = &i;
    //*q = p; //error 语法编译会出错
    //*q = *p;  //error
    p = q;  //q是垃圾值,q赋给p, p也变成垃圾值
    printf("%d\n", *q);   //13行
        
    return 0;
}

经典指针程序—互换两个数字

# include <stdio.h>

void exchange1(int , int);
void exchange2(int *, int *);
void exchange(int *, int *);

int main(void)
{
    int a = 3;
    int b = 5;
    
    exchange3(&a, &b); //huhuan_2(*p, *q); 是错误的,exchange2(a, b);也是错误的
    printf("a = %d, b = %d\n", a, b);

    return 0;
}

//不能完成互换功能
void exchange1(int a, int b)
{
    int t;

    t = a;
    a = b;
    b = t;

    return;
}

//不能完成互换功能
void exchange2(int * p, int * q)
{
    int * t;//如果要互换p和q的值,则t必须是int *,不能是int,否则会出错

    t = p;
    p = q;
    q = t;
}

//可以完成互换功能
void exchange3(int * p, int * q)
{
    int t; //如果要互换*p和*q的值, 则t必须定义成int,不能定义成int *, 否则语法出错

    t = *p;  //p是int *,  *p是int
    *p = *q;
    *q = t;
}
4-1 * 号的含义
  • 定义指针变量。Int * p,定义了一个名字叫p的变量,int *表示p只能存放int变量的地址。

  • 指针运算符。该运算符是放在已经定义好的指针变量的前面。如果p是一个已经定义好的指针变量,则*P表示以p的内容为地址的变量。注意理解形参,实参,和局部变量的关系。

#### 基本类型指针
# include <stdio.h>

int main(void)
{
    int * p;//等价于 int *p; 也等价于 int* p;
    int i = 5;
    char ch = 'A';

    p = &i;  // *p 以p的内容为地址的变量
    *p = 99;
    printf("i = %d, *p = %d\n", i, *p);
    
    //p = &ch;
    //p = ch; //error
    //p = 5;  //error

    return 0;
}

显例代码

# include <stdio.h>

void swap_3(int * p, int * q) //形参名字是p和q,接收实参数据的是p和q,而不是*p和*q
{
    int t;
    t = *p; *p = *q; *q = t;
}


int main(void)
{
    int a = 3;
    int b = 5;

    swap_3(&a, &b);
    printf("a = %d, b = %d\n", a, b);

    return 0;
}

void swap_1(int i, int j)
{
    int t;

    t = i; i = j; j = t;
}

void swap_2(int * p, int * q) //形参名字是p和q,接收实参数据的是p和q,而不是*p和*q
{
    int * t;
    t = p; p = q; q = t;
}
5-1 如何通过被调函数修改主调函数普通变量的值

1665530-20190624121116357-524994516.png

指针使函数返回一个一上的值

# include <stdio.h>

int f(int i, int j)
{
    return 100;
//  return 88;
}

void g(int * p, int * q)
{
    *p = 1;
    *q = 2;
}

int main(void)
{
    int a = 3, b = 5;
    g(&a, &b);
    printf("%d %d\n", a, b);
    return 0;
}

转载于:https://www.cnblogs.com/Guard9/p/11076334.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值