c语言指针

c指针

内存和地址

  • 内存中的位置由每个独一无二的地址标识。
  • 内存中的每一个位置标识一个值。

什么是指针

利用地址,它的值直接指向(points to)存在电脑存储器中另一个地方的值。

把某个变量的地址,称为“指向该变量的指针”

变量的三要素:
  • 变量地址,
  • 变量名字,
  • 变量值。
我们可以用取地址运算符

“&” 来拿到一个变量的地址,例如 &c。

定义变量:
int *pointer;
指针变量的定义:
int c = 76;
int *pointer;
pointer = &c; //将变量c的地址赋值给指针变量pointer。
//赋值后,我们称指针变量Pointer指向了变量c.

指针变量也是有地址的。

关于*的优先级

由高到低排列

  1. 后置++ –
  2. 前置++ – ,逻辑非(!) ,*, &
  3. 算数运算符
  4. 关系运算符
  5. && 与 ||
  6. 赋值运算符

举个例子:

&*pointer = &(*pointer)
*&a = *(&a)
但是:
(*pointer)++ 不等于 *pointer++ 

关于p++的含义:

有这么一段程序:

#include <stdio.h>
int main(){
    int n = 0;
    int *p = &n;
    printf("%#x\n", p);
    p++;
    printf("%#x\n", p);
    system("pause");
}

我们查看一下结果。
这里写图片描述

结果显示地址移动了4个字节。
由此我们得出如下结论:
假设iptr当前所存地址是 0x00000100

  • 若iptr指向一个整型元素(占四个字节的),
    则iptr++等于 iptr+ 1*4 =0x00000104;
  • 若iptr指向一个实型元素(占四个字节的),
    则iptr++等于 iptr+ 1*4 =0x00000104;
  • 若iptr指向一个字符元素(占1个字节的),
    则iptr++等于 iptr+ 1*4 =0x00000101;

指针是一种数据类型

  1. 指针也是一种变量,占有内存空间,用来保存内存地址
    测试指针变量占有内存空间大小

  2. *p操作内存
    在指针声明时,*号表示所声明的变量为指针
    在指针使用时,*号表示 操作 指针所指向的内存空间中的值
    *p相当于通过地址(p变量的值)找到一块内存;然后操作内存
    *p放在等号的左边赋值(给内存赋值)
    *p放在等号的右边取值(从内存获取值)

  3. 指针变量和它指向的内存块是两个不同的概念
    //含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
    //含义2 给*p赋值*p=’a’; 不会改变指针变量的值,只会改变所指的内存块的值
    //含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
    //含义4 =左边char *p
    //含义5 保证所指的内存块能修改

  4. 当我们不断的给指针变量赋值,就是不断的改变指针变量(和所指向
    内存空间没有任何关系)。

#include    <stdlib.h>
#include    <string.h>
#include    <stdio.h>
//不断给指针赋值就是不断改变指针的指向
int main(void)  
{   
    char                buf[128];   
    int                 i;  
    char                *p2 =   NULL;   
    char                *p1 =   NULL;   
    p1  =   &buf[0];    //不断的修改p1的值 相当于 不断改变指针的指向
    p1  =   &buf[1];    
    p1  =   &buf[2];    
    for (i=0;   i<10;   i++)    
    {   
        //不断改变p1指向的内存块
        *p1 =   buf[i]; 
    }   
    for (i=0;   i<10;   i++)    
    {   
        //不断改变p1本⾝变量
        p1  =   &buf[i];    
    }   
    p2  =   (char   *)malloc(100);  
    strcpy(p2,  "abcdefg1212333333333311"); 
    for (i=0;   i<10;   i++)    
    {   
        //不断的改变p1本⾝变量,跟p1指向的内存块⽆关
        p1  =   p2+i;   
        printf("%c  ",  *p1);   
    }   
    return 0;   
}   

指针与数组

1.数组名字代表元素的首地址。

对于数组 a[10] = {1,2,3,4,5,6,7,8,9,0};
&a[0] = a
a 相当于指向第一个元素 a[0]的指针。

例如:

#include <stdio.h>
int main(){
    int a[5] = { 1, 2, 3, 4, 5 };
    int *p = NULL;
    printf("%#x\n",a); //1
    printf("%#x\n", &a[0]); //2
    p = a;
    printf("%#x\n", p);//3
    printf("%d\n", *p++);//4
    printf("%d\n", *p++);//5
    system("pause");
}

结果为:
这里写图片描述

  • 注释1处打印的是a,其实也就是a[0]的地址。所以注释2处和注释1处相等。
  • p= a;
    也就是p的地址也和 a一样,也就是a[0]一样。所以注释3处和注释1,2相等。
  • *p则表示 a[0]了。
    我们注意一下*p++的优先级。 ++先执行,也就是先运算后++。所以 *p++这个还是表示 a[0]的值,注释4也就是1。
    注释5也就是2.

2[array]和 array[2]是相等的。

我们运行下面一段程序:

#include <stdio.h>
int main(){
    int array[5] = { 1, 2, 3, 4, 5 };
    int *ap = array + 2;
    printf("%d\n", 2[array]);
    printf("%d\n", array[2]);
    system("pause");
}

结果两个输出的是一样的。
我们推到一下:

2[array] -> *(2+(array)) -> *(2+array) -> *(array + 2)

注意

int *p = &a[0];
a++是没有意义的,但是p++会引起变化。
p可以指向数组最后一个元素以后的指针。
指针做加减运算时一定要注意有效的范围。

指针与const

常量指针和指针常量。

常量指针是指针指向的内容是常量,可以有一下两种定义方式。

const int * n;
int const * n;

需要注意的是一下两点:
1、常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。

int a=5;
const int* n=&a;
a=6;

2、常量指针指向的值不能改变,但是这并不是意味着指针本身不能改变,常量指针可以指向其他的地址。

int a=5;
int b=6;
const int* n=&a;
n=&b;

指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:

int *const n;

需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。

int a=5;
int *p=&a;
int* const n=&a;
*p=8;

区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。如果我们将星号读作‘指针’,将const读作‘常量’的话,内容正好符合。int const * n;是常量指针,int *const n;是指针常量。

指向常量的常指针

是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。

const int* const p;
  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值