Linux C 之 指针

指针就是地址

1 变量与地址

int i = 1;//变量i是存放值1当下地址的房间名,地址则是该房间的经纬度或门牌号,房间名可变但地址不可变

2 指针与指针变量

int i = 1;
int *p = &i;//指针就是值1所在的地址,指针变量就是存放指针所在地址的房间名

3 直接访问与间接访问

int i = 1;
int *p = &i;
​
printf("i = %d\n",i);//通过变量名直接访问叫做直接访问
printf("i = %d\n",*p);//通过指针取值访问叫做间接访问

4 空指针与野指针

int *p = NULL;//空指针,把指针初始化为空指针是为了防止野指针
野指针:指的是该指针指向的地址是不确定的

5 空类型

void *p = NULL;//空类型属于百搭类型的指针,它能与诸如int、char等类进行匹配,在值传递是不知道对方类型时可以使用空类型

6 定义与初始化的书写规则

int i = 1;
int *p = &i;//一级指针
int **q = &p;//二级指针

7 指针运算

* 取值  &  取地址  关系运算   ++  --

8 指针与数组

指针与一维数组

int a[i] = {1,2,3};
值:a[i] = *(a+i) = *(p+i) = p[i]
地址:&a[i] = a+i = p+i =&p[i]

注意:
    数组a[i]中的a为常量,不能用来做算数运算,而p是变量可以用来运算,a++(×),p++(√)
    注意p++与p+1的区别,p++ -> p= p+1(改变了指针的指向),p+1没有左值并没有改变p的值
    
    
练习:
    
int main()
{
        int a[] = {2,4,6,8,10};
        int y;
        int *p = &a[1];//p的值为a[1]的地址;

        y = (*--p)++;//y = a[0]++;
        printf("y = %d\n",y); //y = a[0];            即y = 2;
        printf("a[0] = %d\n",a[0]);//a[0] = a[0]+1;    a[0] = 3;
}

指针与二维数组

定义与初始化:
int a[2][3];
int *p;

错误定义:p = a;//因为a是一个行地址量,加一或者减一是以行为单位增减的,而p是列地址的指针,强调逐个元素的增减
正确定义:p = &a[0][0]; // p = *(a+0) = *a;


指针与二维数组的输出:
#include <stdio.h>
#include <stdlib.h>

int main()
{
        int a[2][3] = {1,2,3,4,5,6};
        int i;
        int *p;

        p = &a[0][0];

        for(i = 0; i < 6 ; i++)
            printf("%d\t",p[i]);
        printf("\n");

}

指针与字符数组

字符数组:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main()
{
    char str[] = "hello";//定义一个数组并初始化
    printf("%d\t%d\n",sizeof(str),strlen(str));//打印数组所占的字节数及其有限字符数目
	//结果为 6   5  
    
    strcpy(str,"world");//用字符串world覆盖hello
    puts(str);
    exit(0);
}

字符指针:
int main()
{
    char *str = "hello";//定义一个字符指针并初始化
    printf("%d\t%d\n",sizeof(str),strlen(str));//打印字符指针所占的字节数及其有限字符数目
	//结果为 8   5
    
    str = "world";//用字符串world覆盖hello
    puts(str);

    exit(0);
}

结果是,字符数组的大小是不固定的,而字符指针是固定大小的,使用字符指针时要注意内存大小的问题,以及注意字符串覆盖的不同方式

9 const 与指针

const int a;
int const a;//定义一个int型常量
​
const int *p;//常量指针,指针的指向可以发生改变,但是指针所指向的值不能发生改变
int const *p;//这两个都为常量指针,没有啥区别
​
int *const p;//指针常量,指针的指向不能发生变化,但是指针指向的值不能发生变化
​
const int *const p;//指针的指向与指针所指向的值都不能发生改变

常量指针:

常量指针,指针的指向可以发生改变,但是指针指向的值不能改变

记忆方法:先看到const再看到*号,就读常量指针,const限制 *p 所指向的值,即值不能变但是指针的指向可以改变

int const *p;
const int *p;

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i=1;//定义一个变量

    const int *p = &i;//将i的地址赋给一个int类型的常量指针
    
//(F)  *p = 2;  //因为*p是常量指针,所以不能通过指针来改变i的值
    
    i = 2;//可以通过变量名赋值来改变i的值

    printf("%d",i);
}

 

指针常量:

指针常量,指针的指向不可以发生改变,但是指针指向的值可以改变

记忆方法:先看到 * 再看到const,就读指针常量,const限制 p 所指向的地址,即指向不能变但是指针指向的值可以改变

const用法之一:定义一个常量
#define PI 3.14  //定义一个常量,3.14为PI,缺点define是在预处理与编译阶段就会被处理,所以不会检查语法是否错误
					如define PI abcdef 因为错误输入,并不想如此定义但因为该语句不检查语法就会发现不了错误

const float pi = 3.14;//定义一个float类型的常量,可以检查语法,防止错
const注意问题之二:小心被const限制的值被修改
    
#include <stdio.h>
#include <stdlib.h>

int main()
{

    const float pi = 3.14;//定义一个float型常量

     float *p = &pi;//定义一个指向pi的float型指针

    *p = 3.14159;//修改指针p所指向的值,将3.14改为3.14159

    printf("pi = %f\n",*p);//打印

    exit(0);

}
结果就是将一个被const限制的值给修改了
    
解决方法:
  将定义的float类型的指针被const限制,即const常量对应常量指针
  const float pi = 3.14;
  const float *p = &pi;

10 指针数组与数组指针

数组指针:【存储类型】 数据类型 ( * 指针名)【下标】 = 值 如:int (*p)[3]; ->type name -> (int[3]) *p

数组指针与二维数组的关系:
    
#include <stdio.h>
#include <stdlib.h>

int main()
{
    int a[2][3] = {1,2,3,4,5,6};//定义一个二维数组
    int (*q)[3] = a;//定义一个数组指针*q指向数组a,a为行地址的起始地址,因为*q是一个行指针
    int i,j;

     printf("%p\t%p\n",a,a+1);//打印a与a+1的地址
     printf("%p\t%p\n\n",q,q+1);//打印数组指针q与q+1的地址
    //数组指针q的地址是以行为单位变化的,q+1递增了三个int型数据,与a+1递增三个int型数据一样

    for(i = 0; i < 2 ; i++)
    {
        for(j = 0; j < 3; j++)
        {
            printf("%p->%d\n",*(q+i)+j,*(*(q+i)+j));//打印数组指针的值与地址
        }
        printf("\n");
    }

    exit(0);
}

总结:数组指针是针对二维数组的,减少了内存的浪费

指针数组: 【存储类型】 数据类型 * 数组名 【长度】

如:int *arr[3]; - >TYPE NAME ; ->int *[3] arr;

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    char *str[5] = {"Fellow me","Basic","Great","Fortran","Computer"};

    for(i = 0 ; i < 5 ; i++)
    {
        puts(str[i]);
    }

    exit(0);

}

总结:指针数组主要是处理多个字符串,将字符串定义为指针类型的字符串,方便处理以及节省内存

11 多级指针

多理解一级与二级指针即可

指针大小:

#include <stdio.h>

#define STRSIZE 128

int main()
{
    int i = 1;
    int *p;
    float *f;
    double *d;
    char *c;

    //打印指针所占地址的大小
    printf("%d\n",sizeof(p));
    printf("%d\n",sizeof(f));
    printf("%d\n",sizeof(d));
    printf("%d\n",sizeof(c));

}

从下图结果中可以看出,指针所占的地址空间是一样的,在不同的计算机系统中会有不同的大小,但要注意的是相应类型的指针要与相应类型的值对应,例如,char i = 1  要与 char *c 对应,因为指针在运算时隔多少个字节读出来的数不一样,不然会出错

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值