C语言初识指针

指针

指针和指针类型:int*,short*,char*,double*   大小都为4/8字节

指针类型的意义

1.在解引用时

例:char* p;*p=0;

//只改动一个字节

int* p;*p=0;

//改动四个字节

指针类型决定了指针进行解引用操作时能够访问的空间大小

2.指针+/-整数时,跳过的空间大小

int  main()

{

    int  a=0x11223344;

    int*  pa=&a;

    char*  pc=&a;

    printf("%p\n",pa);

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

    printf("%p\n",pc);

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

    return 0;   

}

结果打印出://此结果仅为示例,每个电脑打印的地址不一样

0095FB58

0095FB5C//由0095FB58+4得

0095FB58

0095FB59//由0095FB58+1得

指针类型决定了指针+1向后跳的字节数

指针类型决定了:指针一步走多远(指针的步长)

int*  p;//p+1—4,   char* p;//p+1—1,   double* p;//p+1—8

野指针:指指针指向的位置是不可知的(随机的,不合语法的,没有明确限制的)

原因:

1.指针未初始化

2.指针越界访问  

例:int a[10];

int* p=arr;

for(i=0;i<12;i++)

    *(p++)=i;

3.指针指向内容空间释放

int* test( )

{

    int a=10;

    return &a;

}

int  main()

{

    int *p=test( );

    *p=20;

    return 0;

}

此时p虽然指向a中的空间,a中有10了,但使用时a的空间已经释放了

相当于电脑世界中,程序各有各的领地,当a不属于这个程序时(函数结束,a销毁),再去使用相当于非法入侵

除非设为static变量

如何规避:

1.指针初始化

2.小心指针越界

3.指针不指向某具体空间即设置NULL

4.指针使用之前检查有效性

当不知道把什么赋给指针时可以赋空指针,例int* p=NULL;  NULL本质:(void* )0

NULL为无效空间,不能访问

指针运算:加法前文已提,减法同理

指针可以比大小

例:

float  values[5];

float  *vp;

for(vp=&value[0];vp<&value[5];)

    *vp++=0;

指针减指针

例:

int main()

{

    int  arr[10]={1,2,3,4,5,6,7,8,9,10};

    printf("%d\n",&arr[0]-&arr[9]);

    return  0;

}

大地址减小地址为正,小地址减大地址为负

打印结果:-9

指针要指向一组连续的空间,像数组这样

C语言标准规定:允许指向数组的指针与指向数组最后一个元素后面的那个内存位置的指针地址相比较,但不允许与指向第一个元素之前的那个内存位置进行比较

例:推荐

float  values[5];

float*  vp;

for(vp=&values[5];vp>&values[0];)

    *--vp=0;

不推荐

for(vp=&values[4];vp>=&values[0];vp--)

    *p=0;

仅有两种情况数组名不表示首地址

1.&+数组名,指向整个数组空间,取出整个数组的地址(从数值上看还是首地址的值,但+1将跨越整个数组)

2.sizeof(数组名),求得整个数组的大小,此时数组名表示整个数组

int  arr[10]={0};

printf("%p\n",arr);

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

printf("%p\n",&arr[0]);

printf("%p\n",&arr[0]+1);

printf("%p\n",&arr);

printf("%p\n",&arr+1);

运行结果:(仅为示例)

00EFF8E0

00EFF8E4//由00EFF8E0+4得

00EFF8E0

00EFF8E4//由00EFF8E0+4得

00EFF8E0

00EFF908//由00EFF8E0+40得

二级指针

int  a=0;

int*  pa=&a;

//pa是一级指针

一级指针的语法int*  pa(int表示指向的对象为整形,*表示pa是指针)

当pa的地址也要储存时

int**  ppa=&pa;

//ppa就是二级指针

二级指针的语法 int**  ppa(int*表示ppa指向的对象是整型指针,第二个*表示ppa是指针)

以此类推

int***  pppa=&ppa;

//pppa为三级指针

指针数组—数组——存放指针的数组

int  arr[10];

//整型数组

int**  arr2[3];

//指针数组

例:

int  a=10;

int  b=20;

int  c=30;

int*  arr2[3]={&a,&b,&c};

//数组中的每一个都是指针

int  i=0;

for(i=0;i<3;i++)

    printf("%d  ",*(arr2[i]));

#include<stdio.h>

int  main()

{

    int  arr[]={1,2,3,4,5};

    short  *p=(short*)arr;

//p是指针,*p只改变2字节长度的二级制代码

//short*不是为了强制类型转换,而是将int*变为short*

    int i=0;

    for(i=0;i<4;i++)

    {

        *(p+i)=0;

    }

    for(i=0;i<5;i++)

    {

        printf("%d  ",arr[i]);

    }

    return  0;

}

打印结果:0  0  3  4  5

int  main()

{

    int  a=0x11223344;

    char *pc=(char*)&a;

//若未加(char*)则int*与char*不兼容

//a的储存形式为44  33  22  11

//进行第一次赋0得:00  33  22  11

//打印:11  22  33  00

    *pc=0;

    printf("%x\n",a);

    return  0;

}

若&(char*)a则取一个指针的地址需char**  pc储存

全局变量不被初始化,默认为0,局部变量不初始化为随机数

int  i;

int  main()

{

    i--;

//i--得-1

    if(i>sizeof(i))

//sizeof()计算变量/类型所占内存的大小,大小恒大于等于0,sizeof返回值为无符号数,i为一个有符号数,相互比较时,会转换为无符号数,-1的最高位为1(符号位)化为有效位,i为一个特大数字(i化为补码再转换为无符号数)

        printf(">\n");

    else

        printf("<\n");

}

结果:打印出>

例题:计算二进制中1的个数

int  count_one_bit(int  n)

{

    int  count=0;

    while(n)

    {

        if(n%2==1)

            count++;

        n=n/2;

    }

}

int  main()

{

    int  a=0;

    scanf("%d",&a);

    int  count=count_bit_one(a);

    printf("count=%d\n",count);

    return  0;

}

缺点:只能计算正数

改进:(int   n),改为(unsigned  int  n)

法二:

int  count_bit_one(int  n)

{

    int  count=0;

    int  i=0;

    for(i=0;i<32;i++)

    {

        if(((n>>i)&1)==1)

            count++;

    }

    return count;

}

法三:更优解(负数适用)

int  count=0;

while(n)

{

    n=n&(n-1);

    count++;

}

return  count;

//n&(n-1)    13:

00000000  00000000  00000000  00001101——n

00000000  00000000  00000000  00001100——n-1

00000000  00000000  00000000  00001100——n'——n&(n-1)

00000000  00000000  00000000  00001011——n'-1

00000000  00000000  00000000  00001000——n"——n'&(n'-1)

00000000  00000000  00000000  00000111——n"-1

00000000  00000000  00000000  00000000——n'''——n''&(n''-1)

可见进行一次n&(n-1)去一个1

例题:计算二进制有几个不同

int  get_diff_bit(int m,int n)

{

    int  tmp=m^n;

//m,n相异为1

    int  count=0;

    while(tmp)

    {

        tmp=tmp&(tmp-1);

//计算1的个数

        count++;

    }

    return  0;

}

int  main()

{

    int  m=0;

    int  n=0;

    scanf("%d%d",&m,&n);

    int  count=get_diff_bit(m,n);

    printf("count=%d\n",count);

    return  0;

}

例题:将字符串改为其逆序(不是逆序打印)

int  my_strlen(char*  str)

{

    int  count=0;

    while(*str!='\0')

    {

        count++;

        str++;

    }

    return  count;

}

void  reverse_string(char  arr[])

{

    int  left=0;

    int  right=my_strlen(arr)-1;

    while(left<right)

    {

        int  tmp=arr[left];

        arr[left]=arr[right];

        arr[right]=tmp;

        left++;

        right--;

    }

}

int  main()

{

    char  arr[]="abcdef";

    reverse_string(arr);

    printf("%s\n",arr);

    return  0;

}

递归型:

void  reverse_string(char  arr[])

{

    char  tmp=arr[0];

    int  len=my_strlen(arr);

    arr[0]=arr[len-1];

    arr[len-1]='\0';

//\0是为了计算交换后,未交换部分的长度

    if(my_strlen(arr+1)>=2)

        reserve_string(arr+1);

    arr[len-1]=tmp;

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值