C 指针要点

指针知识点总结

'&':取地址运算符,求变量的地址

指针    :地址(内存最小地址单位为字节  所有变量用首地址标识)  地址值unsigned long数值
指针变量:存放地址数值的变量,在C语言种用'*'表示指针类型  指针变量通过间接引用(解引用)访问所指向的空间  '*'解引用运算符

int   a,value=555;
int   *ptr; 或者 int *ptr=&value
;

 

1.在声明或定义时'*'表示指针类型

2.除了声明或定义之外'*'表示解引用运算符
*ptr=4455;//相当于改变value为4455
a=*ptr;

3.void   *v;//无类型指针(万能型指针:可以存放任意类型变量的地址,但不可直接访问所指空间)

4.指针变量本身的空间大小与所指向的空间类型无关 与平台位数相关

 

指针变量可以执行以下算术运算:
1.同类型的指针可以比较== != > < >= <= (比较地址值的关系)

2.指针可以加减某个整数,加减整数实现偏移  注意:仅在连续空间有意义
type *a;
a+n   向高地址偏移
a-n   向低地址偏移
偏移量:n*sizeof(type) 偏移N个所指向的空间大小

3.同类型的指针可以减去同类型的指针
     指针减指针得到 该空间内可以容得多少个所指向的类型数据

 

数组与指针
1.数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素



指针数组 
int *ar[5];
char  *names[10];
int **temp[5];
void (*funcs[10])(int,char);

数组指针
int (*x)[6];

函数指针:函数名单独作为右值或函数参数即为函数指针(通过函数指针可以直接调用函数)
void (*func)(char);


指针函数:返回值为指针的函数(函数的简称以返回类型为名)

 

指针的好处

  1. 指针节省数据空间,当存放数据过大时,使用指针,存放地址(避免爆栈)
  2. 在函数调用时,要求函数中实参改变,必须传其地址(数组除外),使用指针在函数中改变实参

指针的大小

 指针的地址大小与数据类型无关,只与平台有关,(8B)64bit-------(4B)32bit

指针变量本身的空间大小与所指的空间类型无关

 实参如果是数组名ar),形参接到的为数组的  首地址   ,在其函数中 sizeof(ar)= 8(64bit);

指针的几种特殊用法

数组指针                int   (*ar)[2]                    是指针,指向该数组

指针数组                int     *ar[2]                    是数组,数组元素是指针

函数指针                int    (*fun)(int  a)           是指针,指向该函数

指针函数                int     *fun(int  a)            是函数,函数的返回值是指针地址    

指针注意事项

万能型指针            void   *v;                       万能型指针  可以存放任意地址 但不可直接访问

int *ptr;                                             野指针 ptr值随机 指向随机的空间
           *ptr=5566;                                         //error!!!


            int  *ptr=NULL;                                指向NULL 0地址(0地址为安全空间 访问则出错 避免修改随机空间)

取地址,交换实参的值

#include <stdio.h>
//*x-->a   *y--->b
void swap(int *x,int *y)
{
    int temp;
    temp=*x;
    *x=*y;
    *y=temp;
}

int main(void)
{
    int a=2,b=3;

    printf("a:%d b:%d\n",a,b);
    swap(&a,&b);
    printf("a:%d b:%d\n",a,b);
    
    return 0;
}

普通指针数组指针的用法 、并求指针大小


#include <stdio.h>

int main(void)
{
    int a=10,b=20;
    int *ptr=&a;

    printf("ptr:%p &a:%p *ptr:%d a:%d\n",ptr,&a,*ptr,a);

    printf("size ptr:%d &ptr:%p\n",sizeof(ptr),&ptr);

    int **qtr;
    qtr=&ptr;

    printf("qtr:%p  &ptr:%p\n",qtr,&ptr);
    printf("*qtr:%p  ptr:%p\n",*qtr,ptr);
    printf("**qtr:%p  *ptr:%d  a:%d\n",**qtr,*ptr,a);

/*
    type   tt;
    type *yy
    yy=&tt
*/

    int ar[5]={1,2,3,4,5};
    int (*xx)[5];//指向5个整型元素的数组的指针
    xx=&ar;

    int i;
    for(i=0;i<5;i++)
    {
       //printf("%d ",ar[i]);
       printf("%d ",(*xx)[i]);
    }
    putchar('\n');
    return 0;
}

指针加减

指针可以加减某个整数,加减整数实现偏移
 * type *ptr;
 * ptr+n
 * 偏移量:n*sizeof(type) 偏移N个所指向的空间大小

同类型的指针可以相减:指针减指针得到 该空间内可以容得多少个所指向的类型数据

/*
 * 2.指针可以加减某个整数,加减整数实现偏移
 * type *ptr;
 * ptr+n
 * 偏移量:n*sizeof(type) 偏移N个所指向的空间大小
*/
#include <stdio.h>

int main(void)
{
    int    *i;
    char   *c;
    short  *s;
    double *d;
    void   *v;
    int    **ii;

    printf("i:%p i+1:%p\n",i,i+1);
    printf("c:%p c+1:%p  c-1:%p\n",c,c+1,c-1);
    printf("s:%p s+1:%p\n",s,s+1);
    printf("d:%p d+1:%p\n",d,d+1);
    printf("v:%p v+1:%p\n",v,v+1);

    printf("ii:%p ii+1:%p\n",ii,ii+1);

    //注意:仅在连续空间有意义
    int idx,ar[5]={11,22,33,44,55};

    i=&ar[0];
    c=&ar[0];
    for(idx=0;idx<5;idx++)
    {
       //printf("%d ",ar[idx]);
       //printf("%d ",*(ar+idx));
       printf("%d ",*(i+idx));
       //printf("%d ",i[idx]);
       printf("%d",*(c+idx));
    }
    putchar('\n');

    printf("------------------------------\n");
    //指针比较
    for(i=&ar[0];i<=&ar[4];i++)
    {
       printf("%d ",*i);
    }
    putchar('\n');

    //同类型的指针可以相减:指针减指针得到 该空间内可以容得多少个所指向的类型数据
    int count;
    count=&ar[5]-&ar[0];
    printf("count:%d\n",count);


    count=(char *)200-(char *)100;
    printf("count:%d\n",count);


    count=(int *)200-(int *)100;
    printf("count:%d\n",count);


    count=(double *)200-(double *)100;
    printf("count:%d\n",count);

    return 0;
}

数组指针

数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素
    //br=ar;//错误:将‘int *’赋值给‘int[5]’时类型不兼容


#include <stdio.h>

int main(void)
{
    

    //数组名单独作为右值或函数参数,它以首地址的形式存在,它是指向第一个元素
    //br=ar;//错误:将‘int *’赋值给‘int[5]’时类型不兼容
    //
	int ar[5]={11,22,33,44,55},br[5];

    int *ptr;
    ptr=ar;

    int (*qtr)[5];
    qtr=&ar;


    char  chs[5];
    char *pp;
    pp=chs;


    int yy[3][2]={1,2,3,4,5,6};
    int (*xx)[2];
    xx=yy;

    int (*zz)[3][2];
    zz=&yy;
    return 0;
}

整型指针数组 的典型例题和用法

int a=10,b=20,c=30,d=40,e=50;要求用一个函数内一个循环循环5次实现对a b c d e 分别累加1

// 1.int a=10,b=20,c=30,d=40,e=50;要求用一个函数内一个循环循环5次实现对a b c d e 分别累加1
#include <stdio.h>

int main(void)
{
     int i,a=10,b=20,c=30,d=40,e=50;
     //整型指针数组
     int *ar[5]={&a,&b,&c,&d,&e};//int *

     printf("a:%d b:%d c:%d d:%d e:%d\n",a,b,c,d,e);
     for(i=0;i<5;i++)
     {
        *ar[i]=*ar[i]+1;
     }
     printf("a:%d b:%d c:%d d:%d e:%d\n",a,b,c,d,e);

     return 0;
}
#include <stdio.h>

int main(void)
{
    int a[2]={1,2},b[2]={3,4},c[2]={5,6};

    int (*ar[3])[2]={&a,&b,&c};

    int i;
    //access array b
    for(i=0;i<2;i++)
    {
       printf("%d ",(*ar[1])[i]);
    }
    putchar('\n');

    return 0;
}

函数指针

  • 函数名作为参数 或作为右值 也为其首地址 指向该函数
  • 通过函数指针可以直接调用函数
//反汇编  objdump -S a.out  > tt.s
#include <stdio.h>

//typedef将一种已经存在的类型 取个别名

typedef unsigned int  u32;
typedef int  array_t[3][2];
typedef void func_t(char *);


void sayHello(char *name);

//void func(void (*f)(char *),int num)
void func(func_t *f,int num)
{
    f("func");
}

int main(void)
{
    int a[3][2];//array_t a;
    printf("size of a:%d\n",sizeof(a));

    array_t *x; //int (*x)[3][2];
    x=&a;

    sayHello("king");

    //函数名作为参数 或作为右值 也为其首地址 指向该函数
    //通过函数指针可以直接调用函数
    printf("main:%p  sayHello:%p\n",main,sayHello);
    func_t *ptr;//void (*ptr)(char *);
    ptr=sayHello;

    //(*ptr)("tom");

    ptr("marray");//直接调用

    int value=111222;

    //函数作为另一个函数的参数
    func(sayHello,value);

    return 0;
}
void sayHello(char *name)
{
    printf("hello %s\n",name);
}

函数指针的高级用法

  • 用一个循环分别求ab之间的 + - * / %运算
//用一个循环分别求ab之间的 + - * / %运算
#include <stdio.h>

typedef  int func_t(int,int);

#if 0
int add(int a,int b);
int sub(int a,int b);
int sum(int a,int b);
int mydiv(int a,int b);
int mod(int a,int b);
#else
func_t add,sub,sum,mydiv,mod;
#endif //

int main(void)
{
    int i,a=10,b=5,value;
    //int (*ar[5])(int,int)={add,sub,sum,mydiv,mod};
    //ar为返回值为int 且有两个int参数的函数指针数组
    func_t *ar[5]={add,sub,sum,mydiv,mod};
    char   ops[5]={'+','-','*','/','%'};

    for(i=0;i<5;i++)
    {
        value=ar[i](a,b);
        printf("%d%c%d=%d\n",a,ops[i],b,value);
    }
    return 0;
}
int add(int a,int b){return a+b;}
int sub(int a,int b){return a-b;}
int sum(int a,int b){return a*b;}
int mydiv(int a,int b){return a/b;}
int mod(int a,int b){return a%b;}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值