C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例

一个奇怪的C语言问题,涉及到指针、数组、堆栈、以及printf。下面实现:

整数向字符串的转换,返回字符串指针,并在main函数中调用printf显示。

  1. #include<stdio.h>
  2. #include<stdlib.h>
  3. #include<string.h>
  4. char* swich(int n)
  5. {
  6. char A[20],B[20];
  7. char*p;//=(char*)malloc(4*sizeof(char));
  8. int i=0,a;
  9. int minus=0;
  10. if(n<0)
  11. {
  12. minus=1;
  13. n=-n;
  14. }
  15. while(n/10!=0)
  16. {
  17. a=n%10;
  18. n=n/10;
  19. A[i++]=‘0‘+a;
  20. }
  21. a=n%10;
  22. A[i++]=‘0‘+a;
  23. if(minus==1)
  24. A[i++]=‘-‘;
  25. A[i]=0;
  26. int len=i;
  27. int j=len-1;
  28. i=0;
  29. while(i<len)
  30. {
  31. B[i]=A[len-1-i];
  32. i++;
  33. }
  34. B[i]=0;
  35. p=B;
  36. printf("%s,",p);
  37. return p;
  38. }
  39. void main()
  40. {
  41. int a=-234;
  42. char* p=swich(a);
  43. char b[10];
  44. strcpy(b,p);
  45. int i=0;
  46. printf("%s,",b);
  47. }

上面程序执行结果如下:

在swich函数中,234能正常输出。

而在main中输出的却是乱码,如果在main中用

  1. for(int i=0;i<3;i++)
  2. {
  3. printf("%c",p[i]);
  4. }

则只有‘2‘能正确输出,p[1],p[2]乱码。

这是什么原因呢?

调用函数printf前先要将形参压栈,这时候要计算*p。所以,第一条printf语句已经把参数算出来并放到栈顶保存了。然后调用printf函数(函数调用需要用到栈建立访问连和控制链,而原来的函数f执行完了,原本f是在栈顶的,所以,函数f的栈空间释放。数组空间也被释放),printf占用了栈,所以,把原来函数f的栈空间内容修改了。所以,第一条printf语句是可以得到结果的。后面因为arr空间的内容已经被修改,所以,之后的printf语句都得不到结果。

顺便再解释一下printf("%s\n",p);得到的为什么是乱码。

正如上面所说,先计算参数p的值保存栈顶。保存的值为arr的地址。然后调用printf函数,把栈顶空间内容修改了。虽然保存了地址,但是原来的内容已经修改了,所以得不到结果。

来源: <http://zhidao.baidu.com/question/326625441.html>

时间: 2024-10-02 20:12:45

C语言:一个涉及指针函数返回值与printf乱码、内存堆栈的经典案例的相关文章

函数指针与指针函数返回值的区别

指针函数是指带指针的函数,即本质是一个函数.函数返回类型是某一类型的指针定义: 类型标识符 *函数名(参数表)eg: int *f(x,y);函数指针是指向函数的指针变量,即本质是一个指针变量.int (*f) (int x); /* 声明一个函数指针 */ f=func; /* 将func函数的首地址赋给指针f */ 函数指针与指针函数返回值的区别,码迷,mamicode.com

C语言中函数返回值的问题

c语言中有关于在函数返回值的问题,在函数中的局部变量主要是在栈上开辟的,出了函数变量就被回收了,针对函数返回值得问题,给出下面几个比较具体的例子来说明: 函数返回值是在函数中定义的局部变量 这类型的返回值在主函数中是可以使用的,因为返回局部变量值得时候,返回的是值得一个副本,而在主函数中我们需要的也只是这个值而已,因此是可以的,例如 int fun(char *arr) { int num = 0; while (*arr != '\\0') { num = num * 10 + *arr -

C语言的函数返回值

一:背景 谈到C语言的函数返回值,可能会感觉很亲切,不就是一个函数返回值嘛,当初学C语言的时候早就学过了很easy嘛,我曾经也是这么想的.后来要上研究生了,研究生阶段搞得就是C,所以又重新开始学习C,学习C的过程中遇到了很多问题,在此博客中一一记录.实际过程中遇到的第一个问题自然就是函数返回值了.如果有人问你在一个函数中声明一个字符串数组,最后再return这个数组.这可以实现嘛?如果是问我我可能会毫不犹豫的说OK.那事实呢?由此本文诞生了...... 二:问题 先看几个实际的例子: #incl

C++ Primer 学习笔记_17_从C到C++(3)--引用、const引用、引用传递、引用作为函数返回值、引用与指针区别

欢迎大家阅读参考,如有错误或疑问请留言纠正,谢谢 一.引用 1.引用是给一个变量起别名 变量: 名称 空间 引用: 引用不是变量 引用仅仅是变量的别名 引用没有自己独立的空间 引用要与它所引用的变量共享空间 对引用所做的改变实际上是对它所引用的变量的改变 引用在定义的时候必须要进行初始化 引用一经初始化,不能重新指向其他变量 2.定义引用的一般格式: (1)类型  &引用名 = 变量名: (2)例如: int a=1; int &b=a; // b是a的别名,因此a和b是同一个单元 (3)

C++基础知识(八)---函数返回值(返回值,返回指针,返回对象,返回引用)---引用---复制构造函数(拷贝构造函数)

一.函数返回值 1.返回值: int test () { int a=1; return a; } 返回值时最简单的方式,它的操作主要在栈上,变量a在函数结束后会删除,为了返回a的值,系统会在内部建立一个临时变量保存a的值,以返回给调用该函数的表达式,调用结束后变量便不再存在.如果a是简单地数据类型也无所谓,不是很占用内存,如果a是大的自定义类型的数据,那么对a的复制将会占用比较大的内存.函数返回值是右值,不能进行运算符操作. 2.返回指针: int *test2() { int *b=new

【03】指针、返回值、成员函数的const

1 // 2 // 2015-03-05 03/55 3 // 指针.返回值.成员函数 之 const 4 // 5 6 #include <iostream> 7 #include <string> 8 9 using namespace std; 10 11 // ------------------------------ 12 // 1. 指针的const 13 // ------------------------------ 14 const char *p1 = &q

函数指针,函数指针数组,函数返回值为函数指针

函数的名字就是函数的首地址:定义函数指针; int (*p)(int ) p为函数指针变量名字,int 为函数的返回值类型为int型:(int)为函数的形参类型为int型, 注:因为优先级所以要用(*p),否则就会p先和后面的()结合为int*p(int),意思就变为p(int)函数的返回值为int* 注:main2()函数中   int (*p[])(int ,int )  为一维数组,下面写错了, #include<stdio.h> #include<stdlib.h> int

C基础--指针与函数返回值

#include <stdio.h> #define A 0 int funcA(int a, int b) { return a + b; } /*把指针作为函数的返回值*/ int * funcB(int a, int b) { static int c = A; c = a + b; return &c; } /*通过函数进行内存的申请*/ /* * 参数:要申请的内存大小 * 返回值:申请好的内存的首地址 * 这是一种不好的方式 */ int * funcC(int size)

【C语言及程序设计】指针与返回值

指针与返回值(赋值)是两种自定义函数对主函数内变量的操作手段 例: #include "stdafx.h" void exchange(int *, int *, int *); void myswap(int *, int *); int main() { int a, b, c; scanf_s("%d %d %d", &a, &b, &c); exchange(&a, &b, &c); //另一种调用方法 pri