tag 标签: c语言函数

相关博文
  • 热度 29
    2010-8-26 14:11
    7136 次阅读|
    4 个评论
    发现对C语言函数形参进行说明的文章点击率远高于其它文章,看来大家对C语言的热情可不是一般,难怪谭浩强教授那本C语言的书发行量能过千万册,显然是有坚实的群众基础。既然大家都偏好C语言的相关知识,今天我们来剖析一道C语言的面试题,这道题除了考察对C语言函数形参的理解外,还有对++这类操作先加还是后加掌握程度的考察。 题目见下,可以直接用VC进行编译运行,另外这道题也不是我出的,只是借来一用,不代表我完全认同其代码规范格式。 #include typedef struct{int b,p;}S; void f(S s) { int a="1",b=2,c=3,d=4,m=2,n=2; (m=ab)(n=cd); printf("m=%d,n=%d\n",n,m); s.b+=1; s.p+=2; } void fun(char *a,char *b) { a="b"; (*a)++; } void main(void) { int i; unsigned int array ,*p; char c1='A',c2='a',*p1,*p2; S s={1,2}; f(s); printf("%d,%d\n",s.b,s.p); p1=c1; p2=c2; fun(p1,p2); printf("%c%c\n",c1,c2); i="7"3+12; p="array"; *(p++)=++i; printf("%d\n",array ); *(p)=i++; *(p++)+=++i; printf("%d\n",array ); } 运行结果分析: void main(void) { int i; unsigned int array ,*p; char c1='A',c2='a',*p1,*p2; S s={1,2}; 完成main()函数中的变量初始化 没有特别需要注意的地方 假定结构s分配到的地址为s_main f(s); 进入函数fun(),main()函数中结构s的起始地址 s_main会传给函数fun() 进入函数fun()会先另外分配一段空间s_f,并把s_main的值传给s_f void f(S s) int a="1",b=2,c=3,d=4,m=2,n=2; 完成fun()函数中变量的初始化 (m=ab)(n=cd); 这里考察对运算符以及运算优先级别的理解 1.考察队=和运算符优先级的掌握程度,运算符优先级比=高 所以(m=ab)实际上为(m=(ab)),先执行ab操作,此时a=1,b=2,执行结果不为真,也就是m=0,m的值从2变为0 (n=cd)同理,如果执行完(n=cd)应该是n的值从2变为0 2.考察对运算符的理解,因为是条件与,如果前一个条件不为真,就不会进行后面的处理 因为(m=ab)得结果是m=0,所以不用再进行其右边的运算,(n=cd)没有执行,n的值保持不变 printf("m=%d,n=%d\n",n,m); 到这里m的值为0,n为2,正常输出即可 留意这里会额外考察面试者看题的细致程度,输出格式交换了m和n,最终输出应为“m=2,n=0” s.b+=1; s.p+=2; 这里的s实际上是s_f.b加1和s_f.p加2,s_main.b和s_main.p的值均保持不变 这就是之前我分析的形参的处理方法,可以将其当成函数的局部函数,调用时从别处取到初始值 printf("%d,%d\n",s.b,s.p); 这里考察的是对函数形参的理解 到这里函数f()已经执行完返回到main()函数中,函数f()中使用的s_f已经释放掉 所以输出实际还是没有改变的s_main.b和s_main.p,最终输出为“1,2” p1=c1; p2=c2; fun(p1,p2); 这里也是考察队函数形参的理解,不过这里的参数是指针,所以结果会和前面的f()有所不同 void fun(char *a,char *b) 进入函数时候fun()也会分配两个指针a_fun和b_fun 调用函数fun()会先将p1_main和p2_main的值传递给a_fun和b_fun a="b"; 这一句执行结果是a_fun从p1_main变为b_fun,也就是p2_main (*a)++; 指针操作,此时a_fun等于p2_main,指向main()中c2所在的地址,实际结果为将c2所在的地址的内容加1 printf("%c%c\n",c1,c2); 因为前面将c2所在的地址的内容加了1,实际上就是c2内容已经被加了1,最终输出应为“A,b” 对比函数f(),作为形参的p1和p2内容同样没有改变,但是函数fun()中改变了指针所指向地址的内容,从而改变了main()函数中的相应内容 i="7"3+12; 考察的是对运算符的掌握程度,实际等效为i=7(3+12)=7 p="array"; 取数组的首地址给指针p *(p++)=++i; 考察对i++和++i这类操作的理解,p先用再加,i先加再用,实际等效为下面 i="i"+1;这里i变为8 (*p)=i;这里p指向array 的地址,所以array 变为8 p="p"++;这里p改指向array 的地址 printf("%d\n",array ); 最终输出应为“8” *(p)=i++; i先用再加,实际等效为下面 (*p)=i;此时i依然为8,p指向array ,所以array 变为8 i="i"+1;i的内容变为9 *(p++)+=++i; p先用再加,i先加再用,实际等效为下面 i="i"+1;i的内容变为10 (*p)=(*p)+i;此时p指向array ,i为10,array 为8,执行结果是array 变为18 p="p"+1; printf("%d\n",array ); 最终输出应为“18” } (全文完)
  • 热度 33
    2010-8-9 22:00
    7873 次阅读|
    17 个评论
    这也是面试时常碰到的题,通常是把一个指针作为函数的输入参数,在函数内部会改变输入参数对应的指针,问面试者在函数调用过程中指针的具体内容。 这里我也设计一个这样的函数,功能是对输入参数指定的地址连续写入指定个数的指定内容。问在位置(1)(2)(3)指针p的值,在位置(4)(5)指针 buf的值。 答案是 位置(1)指针p还没赋值为空指针0 位置(2)(3)指针p的值均为data_buf 位置(4)针buf值为data_buf 位置(5)指针buf值为data_buf void fill_buffer(unsigned char* buf,unsigned char data,unsigned char size) {                                           //位置(4)     unsigned char i;     for(i=0;isize;i++)     {         *buf=data;         buf++;     } }                                            //位置(5) void main(void) {     unsigned char data_buf ;     unsigned char *p;     p=(char*)data_buf;                   //位置(1)     fill_buffer(p,0,100);                   //位置(2)     while(1);                                  //位置(3) } 可能有的人会疑惑,明明指针p作为函数的参数,在函数中有进行递增操作,为什么函数返回后在位置三还是保持内容为data_buf 不变? 有这种想法的人理解的逻辑流程如下,看上去也好像有道理。 void main(void) {     unsigned char data_buf ;     unsigned char *p;     p=(char*)data_buf;     fill_buffer(p,0,100); p在这里是输入参数     //unsigned char i;     //for(i=0;isize;i++)     //{     // *p=data;     // p++; 执行到这里不就是改变了p吗?     //}     while(1); 函数返回p应该也改变了 } 这种理解自然不对,对于函数的参数,不能简单的在函数中进行替代理解,以这里的fill_buffer(p,0,100)为例子,函数中并不会对p进行任何处理,而是先将p的值用一个临时变量保存起来(也可以为寄存器),在函数中使用的是这个临时变量。 如果用汇编来表示 fill_buffer(p,0,100)的调用过程,参考流程如下: ;lda x 为把x装到A中 ;sta x 为把A的内容存到装x中 ;得到第一个参数 lda p sta buf_para ;得到第二个参数 lda #0 sta data_para ;得到第三个参数 lda #100 sta size_para ;跳转到具体函数代码位置 jsr fill_buffer 从这个流程可以看出指针p实际上没有被改写,虽然p所指的位置会被函数写入指定的内容,函数只是从p得到一个起始地址,在函数内部是通过另外一个指针来改写这个地址开始位置的内容,在调试中观察到的写指针是另外那个指针,并不是p。这也是C函数指针可以做输入输出参数,而变量只能做输入参数的原因。 如func(char *p,char data),函数可以读p所指的地址内容,也可以向p所指的地址写入指定内容,但data只能供函数使用,不能将函数中的值反存到data中。