zoukankan      html  css  js  c++  java
  • 指针步长要注意

    eg1:

    #include <stdio.h>
    
    int main(void)
    {
      int  *s = (int *)"believe yourself!";
       s++;
       printf("%c",*(char *)s);
        return 0;
    }

    输出:

    int四字节,char一字节。注意步长。

    有了上面的铺垫,我们来看下一个,这是一个面试题:

    找出下面代码的bug:

    #include <stdio.h>
    
    void test_func(int * p)
    {
        /*do somethings*/
        printf("%d
    ",*p);
    }
    int main(void)
    {
        char a=1;
        test_func(&a);
        return 0;
    }

    当然,很明显的是char * 和 int *的类型不兼容,虽然C语言中的char就是int的子集,但是在指针操作的时候,类型所占用字节是极其重要的。

    不过,这并不代表这个题目就结束了,你要找出问题的根源,我们试试下面这样强制类型转换:

    #include <stdio.h>
    
    void test_func(int * p)
    {
        /*do somethings*/
        printf("%d
    ",*p);
    }
    int main(void)
    {
        char a=1;
        test_func((int *)&a);
        return 0;
    }

    这样编译倒是没有警告了,但是运行呢?

    明显不对,我们再试试多运行几次呢?

    居然每次运行的结果都不一样,这是什么导致的呢?

    有了第一个例子的启发,我们应该能够明白一点什么,char和int数据是不一样的字节大小,而指针操作和对象所占字节有着关系,本来是一个char类型数据的地址,你把它给一个int *的指针,那么这个int类型的指针,会按照四个字节去解读这个char类型的指针,这样的出来数据,发生错误是意料之中的。所以,我们使用指针操作的时候,一定要谨慎、细致、缜密、灵活。

     那怎么修改呢?

    我们可以这样:

    #include <stdio.h>
    
    void test_func(int * p)
    {
        /*do somethings*/
        printf("%d
    ",(char)*p);
    }
    int main(void)
    {
        char a=12;
        //printf("%p %p 
    ",&a,(int *)&a);
        test_func((int *)&a);
        return 0;
    }

    可以看到无论怎么运行结果都是正确的。你可能会想,哪有这样的操作,这样的强制类型转换在链表之中我相信应该经常看到吧,还有一个解决办法就是实参和形参完全匹配,这也是最规范的方法。不过往往很多时候,我们都需要强制类型转换,尤其涉及void *的类型,在上面的例子中,推荐使用实参和形参指针类型完全匹配,而在void *的应用中,强制类型转换是一大利器。

  • 相关阅读:
    java并发编程 线程间协作
    博客园添加目录,导航,回到顶部
    汉诺塔递归实现
    java并发编程 线程基础
    Flink中算子进行Chain的规则分析(最新代码,源码版本大于1.11.2)
    Flink流处理程序在Local模式下的运行流程源码分析
    Flink-DataStream流处理应用(Local模式下)运行流程-源码分析
    Flink Streaming基于滚动窗口的事件时间分析
    Spark-2.3.2 Java SparkSQL的自定义HBase数据源
    Spark-2.3.2 HBase BulkLoad
  • 原文地址:https://www.cnblogs.com/yangguang-it/p/7341605.html
Copyright © 2011-2022 走看看