精华内容
下载资源
问答
  • #include int inc(int a) ...int multi(int * a, int * b, int *c) { return (*c = *a * *b); } typedef int(*FUNC1)(int in); //此时FUNC1变成了指向函数的指针 typedef int(FUNC2)(int *,int *,i

    今天做到一题面试题如下, 读到第9行的时候发现和自己理解的有出入。

    个人理解函数名是函数的入口地址就是一个人指针,那为什么还要取地址再赋值给p呢?

    带着疑惑百度了一番,发现网上没人发现程序中的问题,所以就记录一下,希望以后做到这题的同学不再被误解。

    错误

    //代码为网上复制的,存在许多问题
    //运行的结果提示: 程序中有游离的‘\343’等一系列错误
    #include <stdio.h>   
    int inc(int a)   
    { return(++a); }   
    int multi(int*a,int*b,int*c)   
    {   return(*c=*a**b); }  
    typedef int(FUNC1)(int in);   
    typedef int(FUNC2) (int*,int*,int*);  
    void show(FUNC2 fun,int arg1, int*arg2)  
    {    
      FUNC1 p=&inc;   
      int temp =p(arg1);   
      fun(&temp,&arg1, arg2);   
      printf("%dn",*arg2);   
    }   
    main()   
    {   
     int a;          
     show(multi,10,&a);    
     return 0;
    }  

    于是自己手打了一遍:

    #include <stdio.h>
    
    int inc(int a)
    {
        return (++a);
    }
    
    int multi(int * a, int * b, int *c)
    {
        return (*c = *a * *b);
    }
    
    typedef int(FUNC1)(int in);
    typedef int(FUNC2)(int *,int *,int *);
    
    void show(FUNC2 fun,int arg1,int * arg2)
    {
        FUNC1 p = &inc;
        int temp = p(arg1);
        fun(&temp,&arg1,arg2);
        printf("%d\n",*arg2);
    }
    int main()
    {
        int a;
        show(multi,10,&a);
        return 0;
    }
    //编译结果错误为:
    //test.c: 在函数 ‘show’ 中:
    //test.c:26: 错误:函数 ‘p’ 像变量一样被初始化

    分析:

    FUNC1 p = &inc;
    左: 定义一个形参为int型,返回值为int型的函数p(p为函数的入口地址)。
    右: 将函数inc()的入口地址 取 地址;
    左右明显是不同的数据类型。

    修改

    //方法一:
    #include <stdio.h>
    
    int inc(int a)
    {
        return (++a);
    }
    
    int multi(int * a, int * b, int *c)
    {
        return (*c = *a * *b);
    }
    
    typedef int(*FUNC1)(int in);    //此时FUNC1变成了指向函数的指针
    typedef int(FUNC2)(int *,int *,int *);
    
    void show(FUNC2 fun,int arg1,int * arg2)
    {
        FUNC1 p = &inc;  
    //  FUNC1 p = inc;  这样写也是对的,不知道如何理解。
    //  个人理解: 像int a[10]一样 ,  a和&a 是一个地址     
        int temp = p(arg1);
        fun(&temp,&arg1,arg2);
        printf("%d\n",*arg2);
    }
    int main()
    {
        int a;
        show(multi,10,&a);
        return 0;
    }
    //方法二:
    #include <stdio.h>
    
    int inc(int a)
    {
        return (++a);
    }
    
    int multi(int * a, int * b, int *c)
    {
        return (*c = *a * *b);
    }
    
    typedef int(FUNC1)(int in);    
    typedef int(FUNC2)(int *,int *,int *);
    
    void show(FUNC2 fun,int arg1,int * arg2)
    {
        FUNC1 *p = &inc;     //定义一个指针p指向一个形参为int型,返回值为int型的函数 
        int temp = p(arg1);
        fun(&temp,&arg1,arg2);
        printf("%d\n",*arg2);
    }
    int main()
    {
        int a;
        show(multi,10,&a);
        return 0;
    }

    问题

    //为什么在typedef int(FUNC2)(int *,int *,int *);的FUNC前加*程序也是对的
    //请看到这篇文章的同学,帮我一下,谢谢。
    //如下:
    #include <stdio.h>
    
    int inc(int a)
    {
        return (++a);
    }
    
    int multi(int * a, int * b, int *c)
    {
        return (*c = *a * *b);
    }
    
    typedef int(FUNC1)(int in);    
    typedef int(*FUNC2)(int *,int *,int *);
    
    void show(FUNC2 fun,int arg1,int * arg2)
    {
        FUNC1 *p = &inc;     //定义一个指针p指向一个形参为int型,返回值为int型的函数 
        int temp = p(arg1);
        fun(&temp,&arg1,arg2);
        printf("%d\n",*arg2);
    }
    int main()
    {
        int a;
        show(multi,10,&a);
        return 0;
    }
    展开全文
  • 关于int *ptr=(int *)(&a+1)问题的探讨

    千次阅读 2013-09-21 11:10:53
    《C语言深度解剖》上看到...int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1); printf("%d,%d",*(a+1),*(ptr-1)); } 输出为:2,5 请解释以上代码的输出结果。 答案如下: *(a+1)其实很简单就是指a[1],输出为2. 问题关键就

    C语言深度解剖》上看到这样一道有意思的题目,是关于数组与指针的问题,描述如下:

    main()

    {

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

    int *ptr=(int *)(&a+1);

    printf("%d,%d",*(a+1),*(ptr-1));

    }

    输出为:2,5

    请解释以上代码的输出结果。

    答案如下:

    *(a+1)其实很简单就是指a[1],输出为2.

    问题关键就在于第二个点,*(ptr-1)输出为多少?

    解释如下,&a+1不是首地址+1,系统会认为加了一个整个a数组,偏移了整个数组a的大小(也就是5个int的大小)。所以int *ptr=(int *)(&a+1);其实ptr实际是&(a[5]),也就是a+5.

    原因为何呢?

    &a是数组指针,其类型为int(*)[5];

    指针加1要根据指针类型加上一定的值,不同类型的指针+1之后增加的大小不同,a是长度为5的int数组指针,所以要加5*sizeof(int),所以ptr实际是a[5],但是ptr与(&a+1)类型是不一样的,这点非常重要,所以ptr-1只会减去sizeof(int*),a,&a的地址是一样的,但意思就不一样了,a是数组首地址,也就是a[0]的地址,&a是对象(数组)首地址,a+1是数组下一元素的地址,即a[1],&a+1是下一个对象的地址,即a[5]


    另外还有道类似的笔试题(我才不会告诉你这是腾讯笔试的一道题目呢~(@^_^@)~):

    关于 int a[10]; 问下面哪些不可以表示 a[1] 的地址?
        A. a+sizeof(int) 
        B. &a[0]+1 
        C. (int*)&a+1 
        D. (int*)((char*)&a+sizeof(int))A. a+sizeof(int)


    解析:
    A. a+sizeof(int) 
    // 不正确, 在32位机器上相当于指针运算 a + 4
    B. &a[0]+1 
    // 正确,数组首元素地址加1,根据指针运算就是a[1]的地址
    C. (int*)&a+1 
    // 正确,数组地址被强制类型转换为int*,然后加1,这样和B表示的一个意思
    D. (int*)((char*)&a+sizeof(int))
    // 正确,数据地址先被转换为char*,然后加4,根据指针运算公式,向前移动4 * sizeof(char),之后被转换为int*,显然是a[1]的地址

    需要注意的是本题中的C答案 (int*)&a+1 与上面题目中的 (int *)(&a+1)是不一样滴哦,(int*)&a+1 取了数组的地址然后再强制转换成数组首元素地址再加1,所以(int*)&a+1 可以表示a[1]地址,而(int *)(&a+1)根据上面的分析是指向下一个数组的地址。怎么样,小伙伴们看明白了吗^_^

    展开全文
  • int a[10] 和 int *a = malloc(10 * sizeof(int)) 究竟有何区别? 这个问题的答案或许很简单,但是这里我想要细细的去探讨下。 我们都知道,C 和 C++ 对于数组和动态内存的处理方案是不同的,C 使用了数组、malloc/...

    一、引言

    曾几何时,我们初学 C/C++ 的新人总会产生这么一个疑问:

    int a[10] 和 int *a = malloc(10 * sizeof(int)) 究竟有何区别?

    这个问题的答案或许很简单,但是这里我想要细细的去探讨下。

    我们都知道,C 和 C++ 对于数组和动态内存的处理方案是不同的,C 使用了数组、malloc/free 的方案,而 C++ 为了整合 OO 的概念,提出了 std::vector 的数组替代物(STL,或者说 std::array)、new/delete 的方案。

    然而设计思想都离不开,本文标题中这个关键的概念,int a[10] 和 int *a = malloc(10 * sizeof(int)) 的区别。

    二、int a[10]

    我们都说,数组是可以随机存取的。那么为什么呢?

    数组就是一块内存,一块内存也可以被用作数组
    《C 程序设计新思维》(第 2 版)

    比如说 int a[10] 这个数组中的第 5 个元素,你可以通过数组开始的位置,计算 5 * sizeof(int) 字节的偏移,便可找到第 5 个元素。

    数组元素的初始化也是非常简单的:

    int a[10] = {0};
    

    并且,我们都知道数组的使用也是非常方便的,系统负责分配内存和释放内存(不像 malloc/free 那么复杂)。

    概念很简单,但是 int a[10] 带来了一个莫大的限制,那就是,int a[10] 定死了申请内存的范围

    这里,我们要记住一个概念,函数内部声明的 int a[10] 的内存分配于栈区。这里暂且留个悬念,后面我会合着堆区一起讲解。

    三、int *a = malloc(10 * sizeof(int))

    上面提到的 int a[10] 使用的是栈区的定死了的内存区域,那么相应的,malloc 提供的就是动态分配的内存区域。

    malloc 所动态分配的内存区域,位于堆上,需要我们程序员手动在使用完毕后进行 free(相应的 C++ 就是 new/delete)。

    对于 malloc 的内存区域来说,初始化该区域的值可以使用 calloc 函数:

    int *a = calloc(10, sizeof(int));
    

    甚至于,我们可以重新分配 malloc 的内存区域的大小:

    a = realloc(a, 20 * sizeof(int));
    

    最重要的,使用完之后千万要记得释放内存:

    free(a);
    

    那么二者究竟有什么区别呢?栈区内存和堆区内存又有什么区别呢?

    为什么 C/C++ 在设计的时候,数组就可以不用手动 free,而堆区一定要手动 free 呢?既然数组都可以自动释放内存,为何动态内存不这么设计呢?

    带着这些问题,我们接下来继续探讨。

    四、一切源于堆栈

    这一切都因为栈与堆的设计。这里我大胆引用 浅析栈区和堆区内存分配的区别 这篇博客的博主所做的比喻:

    堆和栈的区别可以用如下的比喻来看出:

    使用栈就像我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。

    使用堆就像是自己动手做喜欢的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度高。

    我很喜欢这位博主的比喻,非常的形象。

    这里也建议大家去看下该博主的这篇博客,将栈区和堆区讲解的非常好,我这里简单总结几条要点:


    连续的内存区域,向低地址扩展的数据结构。栈顶的地址和栈的最大容量是系统预先制定好的。如果想了解系统栈的大小的默认值,可以看看这篇博客:
    Windows栈大小

    一般来说,32 位 Windows 一个进程的栈的大小为 1M。如果申请的控件超过栈的剩余空间时,将提示内存溢出。

    总之,能从栈获得的空间较小,但是内存分配速度快,可由编译器自动分配释放。


    不连续的内存区域(类似链表一样由多个内存碎边控件链接而成),向高地址扩展的数据结构。系统使用链表存储空闲内存地址,自然是不连续的,遍历方向从低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存(这里根据我网上查询的结果,大概是 GB 级别的,跟栈的 MB 简直是大了三个量级!!!)。

    所以堆中分配的内存速度较慢(毕竟是不连续的内存,又是链表结构),容易产生内存碎边。

    总之,能从堆中获得的空间较大,自由度也很高,但是内存分配速度低,必须要程序员负责分配和释放。

    然而我们还有一个问题没有解决
    那么到这里你应该就懂了,实际上看似很相似的 int a[10] 和 int *a = malloc(10 * sizeof(int)) 这两种方式,实际上对应了栈区和堆区这两种内存使用方式。

    但是上述的阐述,并没有解释一个最关键的问题,为什么堆区的内存一定要程序员去释放,而栈区不需要呢?

    五、堆区的内存为什么一定要程序员释放

    这个问题我也回答不出来,因此我去网上寻找了一份自认为很好的回答,引用在这里分享给大家 堆内存为什么要程序员自己释放

    对SP寄存器的值进行操作而形成逻辑上的栈,而局部变量是在函数内部定义的,就是在栈上定义的,函数的调用和对栈的操作这是一个很基础的也是很重要的知识点,你把局部变量的释放理解成了一个单独的动作,事实上编译器没有对这个局部变量的空间做任何内存管理意义上的操作。只是一个简单的对SP寄存器的值的一个改变即形成了栈的恢复动作。栈一恢复了,那之前那段栈内存上的数据你肯定找不到了,但那个物理内存地址上的数据却还是原状,所以我建义你把 ”自动释放局部变量“ 这几个字改成“自动丢弃局部变量”,丢了的东西就是找不回了,你没法用了,但那东西不会凭空从地球上消失,只是从你的视野里消失了,可能别人捡到了,别人就能用得着了,就像在函数A里创建的局部变量 local_a 可能在进程的地址空间里是地址0X11,但函数A返回之后,可能主程序又要调用函数B,而在函数B里创建的局部变量 local_b 也可能就是在0X11这个地址,那么地址0X11上边的值从A函数结束到B函数开始这段时间一直没变,只是在这段时间里没有人管理它的值。而这个过程就叫释放,或叫丢弃,
    对堆内存的操作实际是动态内存操作,就涉及到内存管理了,其实现在的操作系统内核对用户空间的进程这块的创建与注销都加入了内存保护,你在用户空间的程序中释不释放堆内存,系统都会在这个程序结束时做内存回收动作,但这仅限于用户空间的程序,如果是内核编程的话,就一定要严格释放掉动态分配的内存,否则造成系统内存泄漏,内存泄漏的后果就是可用内存被你人为的弄成了不可用内存,到最后导至系统无动态内存可分配,就无法加载程序。
    对于你的提问,其实没有办法回答得让你理解透澈,你现在对程序的运行机制和操作系统原理基本上是一个零的认识,慢慢来吧,多看操作系统原理的书,其实用户程序都是基于操作系统编程,理解一些原理性的东西是非常重要的。

    简单来说,就是栈区的内存,编译器并非是 “释放” 掉,而是简单的 “丢弃” 掉了;而堆区的内存,如果你不去手动释放掉的话,就会造成可用的空闲内存空间越来越少,可想而知其导致的结果是什么。

    这里我也需要去认真拜读下《程序员的自我修养》这本书吧,哈哈哈 ^_^

    六、总结

    这是一篇我自己自我探索的博客,自己提出问题,从 int a[10] 与 int *a = malloc(10 * sizeof(int)) 的区别开始,探索到栈区与堆区的区别,最后探索到栈区与堆区的实际意义上。当然这个问题继续深究下去,就能到操作系统那个层面上去,毕竟探索永无止境。

    这篇博客融合了自我的思考和网上博客、回答的信息,算是给我自己一个满意的探索结果。希望这篇博客能够给你带来一些帮助吧。

    To be Stronger:)

    展开全文
  • ——分配一个有10int型元素的数组所占空间,并将该数组的第一个元素的地址赋给int 型指针p。 int p=new int(10);——分配一个int型变量所占大小的空间,在其中放入十进制数10,并将首地址赋给int 型指针p。

    int p=new int;——分配一个int型变量所占大小的空间,并将首地址赋给int 型指针p。
    int p=new int[10];——分配一个有10个int型元素的数组所占空间,并将该数组的第一个元素的地址赋给int 型指针p。
    int p=new int(10);——分配一个int型变量所占大小的空间,在其中放入十进制数10,并将首地址赋给int 型指针p。

    展开全文
  • 1.int * p =NULL;和*p =NULL的区别 1 .int * p =NULL int *p=NULL; 定义一个指针变量p,其指向的内存里面保存的是int类型的数据;...int i =10int * p =&amp;i; *p =NULL; int i ...
  • new int[] 创建一个int型数组,数组大小是在[]中指定, 例如: int * p = new int[3]; //申请一个动态整型数组,数组的长度为[]中的值 new int() ...1 int *a=new int(120); 申请一个整型变量空间...
  • int* (*a)[10]; a是一个指向包含10个int型指针元素的数组。 比如: #include int main() {  // 定义数组,包含10int*  int* b[10];  for(int i = 0; i  b[i] = new int(i+1);    int* (*a)...
  • C++中int a[10]和int* a=new int[10]]有什么区别

    万次阅读 多人点赞 2018-03-05 18:39:14
    我们常常看见,在图论中,对一个Graph类在初始化的时候,对类的成员变量**arc(邻接矩阵,是一...Graph_DG::Graph_DG(int vexnum, int edge) { //初始化顶点数和边数 this-&gt;vexnum = vexnum; this-&gt...
  • 关于int*p=&aint*p;p=&a的解惑

    万次阅读 多人点赞 2019-03-30 11:21:59
    在学习c语言解惑中遇到这个问题,其中对int *p=&a的写法百思不得其解,查了网上资料得出 这样的理解是错误的 正确理解是 一般来说*p=&a的表示方法是错的,*p=a和p=&a是正确的。2.*p=a的意思:将a的值...
  • int (*a)[10] 和 int *a[10] 的区别

    千次阅读 2018-05-17 11:17:50
    此数组有10个int型元素int (*a)[10]与int*a[10]的差别就在那个小括号int *a[10]先找到声明符a,然后向右看,有[ ]说明a是个数组,再向左看,是int *,说明数组中的每个元素是int *。所以这是一个存放i...
  • int*p[]={a,a+1,a+2,a+3};int **q=p;表达式*(p[0]+1)+**(q+2)的值是____。 正确答案: A 你的答案: 空 (错误) 5 6 7 8 4 9 添加笔记 求解答(0) 收藏 纠错 ...
  • /** * 找出所有的水仙花数:例如:153=1*1*1+5*5*5+3*3*3 */ int num=100; System.out.print("所有的水仙花数:");...int a=num%10;...int b=num/10%10;...int num1=a*a*a+b*b*b+c*c*c; if (num==num
  •  例如:a[]的值依次为:1,9,2,3,11,6;则利用指针odd返回奇数之和24;利用指针even 返回偶数之和 8。 #include #include void fun(int *a, int n, int *odd, int *even) { int i; int
  • const int、const int *、int *cosnt、const int * cosnt、const int &amp;amp;的区别
  • #include&lt;stdio.h&gt; #include&lt;math.h&... int a,b,c,d;  int s;  while(n&lt;10000)  {  a=n%10;  b=n/10%10;  c=n/100%10;  d=n/1000;  if(a*a*a*a+b*b*b*b+c*c*c...
  • /*编写函数fun(int *a,int n,int *odd,int *even),功能是:求出数组a[]中所有偶数之和,利用指针even返回偶数之和。例如:a[]的值依次为:1,9,2,3,11,6;则利用指针odd返回奇数之和24;利用指针even返回偶数之和...
  • int (*p)[10] 和 int *p[10]的区别

    千次阅读 2017-09-08 19:24:16
    第一: char (*p)[10] 主要用在函数的参数上面,主要用于约束参数数组的长度。 int add(int (*p)[2])//表示必须输入2个元素的int数组 ...int a[2]; a[0]=1; a[1]=2; printf(“%d\n”,&a); return; } 第二:
  • int a,int *a,int&a和(int)&a区别

    万次阅读 多人点赞 2014-10-22 16:07:32
    int a; /*定义a为一个整型类型*/
  • int const*与int * const

    千次阅读 2019-04-22 22:19:20
    1. int const* int const *p与const int *p意义一样。 从右往左看,进行解析,这个p是个指针,而且是个常量,类型是整型。可称为指针常量 特点:*p指向一个整型的... int a = 10; int b = 20; int c = 55; int ...
  • int **和int[][]的区别-c语言

    千次阅读 2019-04-25 15:19:27
    int **p = (int**)a; printf("p[0][0]:%d\n",p[0][0]); 这段程序会出现段错误,仔细分析了一下: p是一个二重指针变量,变量p中应该存放的是指向某个地址的的存储空间,理解比较复杂,如图所示(假设a的地址为...
  • 最近网上比较风骚的一道面试题,大概题目是这样的: 乍一看,认为张手就可以写出来,不过仔细一想,不是那么回事。好了,不说了, 直接上答案,目前有两种,一种是终止JVM... int a = 10; int b = 20; method(a, b);
  • 使用C++也有些年了,这个语言确实有诸多繁琐和变态的地方,比如这次要说明的const int*、int const*以及int *const的区别就是一例。相信不少同学都会对这其中的差异表示不解,我尝试着用一段代码来对他们进行区别。 ...
  • const int *p, int *const p的区别

    万次阅读 多人点赞 2015-10-26 20:26:51
    (1) const int i 使用const 修饰的i我们称之为符号常量,即i不能在其他地方重新赋值。const int i和int const i是等价的。 (2) const int *p 从右向左看,先结合* 再结合const,定义一个指针指向一个常量,不能...
  • void BubbleSort(int *a,int n)

    千次阅读 2012-10-26 21:49:10
    // BubbleSort.cpp : Defines the entry point for the console application. // #include "stdafx.h" ...void swap(int& a,int& b) { if(&a==&b) return; int tmp=a; a=b; b=tmp; } void BubbleSort(int *a,i
  • char *强转为int*后会怎么样?

    千次阅读 2010-05-29 13:21:00
    先把代码粘上来吧:*——* int _tmain(int argc, _TCHAR* argv[]){ char a[10]; a[0] = 0xFF; a[1] = 0x00; a[2] = 0x00; a[3] = 0x00; char *pa = a; int *pi = (int *)pa; int
  • 大概意思就是这个 ge; //百 n);}|||for(i=1;i<10;i++) for(j=1;j<10;j++) for(k=1;k<10;k++) { if(i*i*i+j*j*j+k*k*k=i*100+j*10+k) printf(数字为:+i*100+j*10+k); }很久没用C了 做repeat次下
  • 那么,换为int*,就是“元素是指向整形数据的指针的数组”)。 再看另一个: int (*p)[n]改变了自然的运算符的优先级,相当于(int)((*p)[n])。一有指针就头疼,我们把指针先替换掉,就是int a[n],是一个n维...
  • int **ptr 与 int ptr[4][4] 的区别??? *(*(ptr+1)+2);相当于ptr[1][2]; **p可以理解成*((*p+0)+0);相当于ptr[0][0];  区别在于:int **ptr定义了一个指针(具体的,二级指针),它使得编译程序使程序在...
  • c语言小的知识点int* a[5] int (*b)[5]

    千次阅读 2011-03-14 10:21:00
    <br />int main() { int* a[5]; int (*b)[5]; int i = 2, j = 3, k = 4;  b = a; a[0] = &i; printf("%d %d %d/n", *a, *a[0], i); printf("%d %d %d/n", a, a[0], ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 3,193,460
精华内容 1,277,384
关键字:

a[10]={10*1}int