c语言中定义的全局变量,在某个函数中赋值还能被其他函数使用吗?

[复制链接]
21744|21
 楼主| jiangsai 发表于 2013-4-26 16:43 | 显示全部楼层 |阅读模式
为了省下参数传递的麻烦,我把一些多个函数都要用到的变量和结构体都定义成全局的,可以吗?为什么我的程序执行时出现问题,查看修改后的全局变量值没有改变,还是初始值 呢?请各位高手指点。我在一个函数中对全局变量自加运算,再到另一个函数中全局变量值是开始的初值还是上一个函数自加后的值呢?
杨爱林林 发表于 2013-4-26 16:52 | 显示全部楼层
当然是可以用的了 而且比较方便  
如果你没带系统的话  就看使用这个全局变量的先后顺序了  全局变量,当然是最后使用该变量过后的值了 也就是自加过后的值
如果带系统的话  就得保护这个共享资源了  
你可以贴上代码
uet_cache 发表于 2013-4-26 16:56 | 显示全部楼层
全局变量,要放在程序开头位置。如果其它文件要用,要声明外部变量。
airwill 发表于 2013-4-26 18:25 | 显示全部楼层
全局变量, 当然是可以的.
不过, 我们写程序, 不建议大量使用全局变量.
"我在一个函数中对全局变量自加运算,再到另一个函数中全局变量值是开始的初值还是上一个函数自加后的值呢?"  当然是后者. 这里可能有个概念问题. 假如以变量传递给函数了. 那么修改的是个传递过来的副本, 而不是本身. 除非传递全局变量的地址.
hawksabre 发表于 2013-4-26 19:02 | 显示全部楼层
大量使用全局函数   最终程序的改动就是牵一发动全身    不建议使用过多全局函数    模块化的思想倒是不错的思想   楼主   可以借鉴一下
hawksabre 发表于 2013-4-26 19:02 | 显示全部楼层
多看看关于编程思想的书籍   我也是班门弄斧    飘过  
 楼主| jiangsai 发表于 2013-4-27 07:58 | 显示全部楼层
杨爱林林 发表于 2013-4-26 16:52
当然是可以用的了 而且比较方便  
如果你没带系统的话  就看使用这个全局变量的先后顺序了  全局变量,当然 ...

我在做小的毕业设计,没带系统。。并且只有设了一个全局变量,在main。c的开头设置的。。后面的函数要用到该变量的话要怎么应用呢。。
 楼主| jiangsai 发表于 2013-4-27 07:59 | 显示全部楼层
uet_cache 发表于 2013-4-26 16:56
全局变量,要放在程序开头位置。如果其它文件要用,要声明外部变量。

只是在该文件中使用,
 楼主| jiangsai 发表于 2013-4-27 08:04 | 显示全部楼层
airwill 发表于 2013-4-26 18:25
全局变量, 当然是可以的.
不过, 我们写程序, 不建议大量使用全局变量.
"我在一个函数中对全局变量自加运算 ...

我想了想可以把所有的子函数都放进main中可以用设全局变量了。。但那样字话,程序就不够好看了。。所以我还是想把子函数放到外面,main中调用。。但全局变量我用不好呢。。在子函数中引用全局变量的话,要做舍呢么特别的说明吗。。代码我一会贴上去。我想实现的就是一个简单的一个按键可以先设定下圈数,按下另外的按键就可以左转或右转相应的圈数
 楼主| jiangsai 发表于 2013-4-27 08:07 | 显示全部楼层
  1. /* Includes ------------------------------------------------------------------*/
  2. #include "stm32f10x.h"
  3. #include "stm32_eval.h"
  4. #include <stdio.h>
  5. //#include "ARMJISHU_TouchScreen_ADS7843.h"
  6. #include "sys.h"               
  7.        
  8. void USART_Configuration(void);
  9. void RCC_Configuration(void);
  10. void GPIO_Configuration(void);
  11. void Delay(vu32 nCount);
  12. void Delay1(vu32 nCount);
  13. u8 M=0;
  14. /* Values magic to the Board keys */
  15. #define  NOKEY  0
  16. #define  KEY1   1
  17. #define  KEY2   2
  18. #define  KEY3   3
  19. #define  KEY4   4
  20. #define  KEY5   5            
  21. #define  KEY6   6            

  22. /*按键相关定义*/
  23. #define RCC_KEY1                                    RCC_APB2Periph_GPIOB
  24. #define GPIO_KEY1_PORT                              GPIOB   
  25. #define GPIO_KEY1                                   GPIO_Pin_0
  26. #define RCC_KEY2                                    RCC_APB2Periph_GPIOB
  27. #define GPIO_KEY2_PORT                              GPIOB
  28. #define GPIO_KEY2                                   GPIO_Pin_1
  29. #define RCC_KEY3                                    RCC_APB2Periph_GPIOB
  30. #define GPIO_KEY3_PORT                              GPIOB
  31. #define GPIO_KEY3                                   GPIO_Pin_2
  32. #define RCC_KEY4                                    RCC_APB2Periph_GPIOB
  33. #define GPIO_KEY4_PORT                              GPIOB
  34. #define GPIO_KEY4                                   GPIO_Pin_5
  35. #define RCC_KEY5                                    RCC_APB2Periph_GPIOB
  36. #define GPIO_KEY5_PORT                              GPIOB
  37. #define GPIO_KEY5                                   GPIO_Pin_6
  38. #define RCC_KEY6                                    RCC_APB2Periph_GPIOB
  39. #define GPIO_KEY6_PORT                              GPIOB
  40. #define GPIO_KEY6                                   GPIO_Pin_7

  41. /* Private function prototypes -----------------------------------------------*/
  42. #ifdef __GNUC__
  43. /* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
  44.                                              set to 'Yes') calls __io_putchar() */
  45.   #define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
  46. #else
  47.   #define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
  48. #endif /* __GNUC__ */
  49.   
  50. /*static void Delay_ARMJISHU(__IO uint32_t nCount)
  51. {
  52.   for (; nCount != 0; nCount--)
  53.   {
  54.       if(GPIO_ADS7843_INT_VALID)
  55.       {
  56.         ARMJISHU_TouchScreen_ADS7843();
  57.       }       
  58.   }
  59. }                                                   */

  60. void delay(void)
  61.   {
  62.       unsigned long ik ;
  63.       for(ik=0;ik<0x03af8;ik++) ;
  64.   }
  65. void delay1(void)
  66.   {
  67.       unsigned long ik ;
  68.       for(ik=0;ik<0x00af8;ik++) ;
  69.   }

  70. /* Private functions ---------------------------------------------------------*/

  71. /*******************************************************************************
  72. * Function Name  : GPIO_KEY_Config.
  73. * Description    : Configures the Extension Button.
  74. * Input          : None.
  75. * Output         : None.
  76. * Return         : None.
  77. *******************************************************************************/
  78. void GPIO_KEY_Config(void)
  79. {
  80.   GPIO_InitTypeDef GPIO_InitStructure;

  81.   /* Configure KEY1 Button */
  82.   RCC_APB2PeriphClockCmd(RCC_KEY1, ENABLE);

  83.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  84.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY1;
  85.   GPIO_Init(GPIO_KEY1_PORT, &GPIO_InitStructure);
  86.     /* Configure KEY2 Button */
  87.   RCC_APB2PeriphClockCmd(RCC_KEY2, ENABLE);

  88.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  89.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY2;
  90.   GPIO_Init(GPIO_KEY2_PORT, &GPIO_InitStructure);
  91.       /* Configure KEY3 Button */
  92.   RCC_APB2PeriphClockCmd(RCC_KEY3, ENABLE);

  93.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  94.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY3;
  95.   GPIO_Init(GPIO_KEY3_PORT, &GPIO_InitStructure);
  96.         /* Configure KEY4 Button */
  97.   RCC_APB2PeriphClockCmd(RCC_KEY4, ENABLE);

  98.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  99.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY4;
  100.   GPIO_Init(GPIO_KEY4_PORT, &GPIO_InitStructure);
  101.         /* Configure KEY5 Button */
  102.   RCC_APB2PeriphClockCmd(RCC_KEY5, ENABLE);

  103.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  104.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY5;
  105.   GPIO_Init(GPIO_KEY5_PORT, &GPIO_InitStructure);
  106.         /* Configure KEY6 Button */
  107.    RCC_APB2PeriphClockCmd(RCC_KEY6, ENABLE);

  108.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
  109.   GPIO_InitStructure.GPIO_Pin = GPIO_KEY6;
  110.   GPIO_Init(GPIO_KEY6_PORT, &GPIO_InitStructure);
  111. }
  112. /*******************************************************************************
  113. * Function Name  : ReadKey
  114. * Description    : Reads key from demoboard.
  115. * Input          : None
  116. * Output         : None
  117. * Return         : Return RIGHT, LEFT, SEL, UP, DOWN or NOKEY
  118. *******************************************************************************/
  119. u8 ReadKeyDown(void)
  120. {
  121.   /* 1 key is pressed */
  122.   if(!GPIO_ReadInputDataBit(GPIO_KEY1_PORT, GPIO_KEY1))
  123.   {
  124.     return KEY1;
  125.   }       
  126.     /* 2 key is pressed */
  127. else if(!GPIO_ReadInputDataBit(GPIO_KEY2_PORT, GPIO_KEY2))
  128.   {
  129.     return KEY2;
  130.   }
  131.    /* 3 key is pressed */
  132. else if(!GPIO_ReadInputDataBit(GPIO_KEY3_PORT, GPIO_KEY3))
  133.   {
  134.     return KEY3;
  135.   }

  136.    /* 4 key is pressed */
  137. else if(!GPIO_ReadInputDataBit(GPIO_KEY4_PORT, GPIO_KEY4))
  138.   {
  139.     return KEY4;
  140.   }                  
  141.     /* 5 key is pressed */
  142. else if(!GPIO_ReadInputDataBit(GPIO_KEY5_PORT, GPIO_KEY5))
  143.   {
  144.     return KEY5;
  145.   }
  146.    /* 6 key is pressed */
  147. else if(!GPIO_ReadInputDataBit(GPIO_KEY6_PORT, GPIO_KEY6))
  148.   {
  149.     return KEY6;
  150.   }  
  151.   /* No key is pressed */
  152.   else
  153.   {
  154.     return NOKEY;
  155.   }
  156. }

  157. void motor_Turn_on_1(void)                 //正转
  158. {
  159.                               GPIO_Write(GPIOA, 0x08);
  160.                                                       delay();
  161.                                                       GPIO_Write(GPIOA,0x0C);
  162.                                                       delay();
  163.                                                       GPIO_Write(GPIOA,0x04);
  164.                                                       delay();
  165.                                                       GPIO_Write(GPIOA,0x06);
  166.                                                       delay();       
  167.                                                           GPIO_Write(GPIOA, 0x02);
  168.                                                       delay();
  169.                                                           GPIO_Write(GPIOA, 0x03);
  170.                                                       delay();
  171.                                                           GPIO_Write(GPIOA, 0x01);
  172.                                                       delay();
  173.                                                            GPIO_Write(GPIOA, 0x09);
  174.                                                       delay();
  175. }
  176. void motor_Turn_on_2(void)                 //反转
  177. {
  178.                               GPIO_Write(GPIOA,0x09);
  179.                                                       delay();
  180.                                                           GPIO_Write(GPIOA,0x01);
  181.                                                       delay();
  182.                                                           GPIO_Write(GPIOA,0x03);
  183.                                                       delay();
  184.                                                       GPIO_Write(GPIOA,0x02);
  185.                                                       delay();
  186.                                                           GPIO_Write(GPIOA, 0x06);
  187.                                                       delay();       
  188.                                                            GPIO_Write(GPIOA, 0x04);
  189.                                                       delay();
  190.                                                            GPIO_Write(GPIOA, 0x0C);
  191.                                                       delay();
  192.                                                            GPIO_Write(GPIOA, 0x08);
  193.                                                       delay();       
  194. }
  195. void motor_Turn_on_3(void)                //         正转一圈

  196. {
  197.   u8 j;
  198.   u8 r;
  199.   u8 N=64;

  200.   for(r=0;r<N*M;r++)
  201.   {
  202.   for(j=0;j<8;j++)                 //电机外轴旋转一周,不是里里面面所看到的一周
  203.   {
  204.                               GPIO_Write(GPIOA, 0x08);
  205.                                                       delay();
  206.                                                       GPIO_Write(GPIOA,0x0C);
  207.                                                       delay();
  208.                                                       GPIO_Write(GPIOA,0x04);
  209.                                                       delay();
  210.                                                       GPIO_Write(GPIOA,0x06);
  211.                                                       delay();       
  212.                                                           GPIO_Write(GPIOA, 0x02);
  213.                                                       delay();
  214.                                                           GPIO_Write(GPIOA, 0x03);
  215.                                                       delay();
  216.                                                           GPIO_Write(GPIOA, 0x01);
  217.                                                       delay();
  218.                                                           GPIO_Write(GPIOA, 0x09);
  219.                                                       delay();

  220.   }
  221. }
  222. M=0;
  223. }
  224. void motor_Turn_on_4(void)                //         反转一圈
  225. {
  226.   u8 j;
  227.   u8 r;
  228.   u8 N=64;
  229.   
  230.   for(r=0;r<N*M;r++)
  231.   {
  232.    
  233.   for(j=0;j<8;j++)                 //电机外轴旋转一周,不是里里面面所看到的一周
  234.   {
  235.     GPIO_Write(GPIOA,0x09);
  236.         delay();
  237.         GPIO_Write(GPIOA,0x01);
  238.         delay();
  239.         GPIO_Write(GPIOA,0x03);
  240.         delay();
  241.         GPIO_Write(GPIOA,0x02);
  242.         delay();
  243.     GPIO_Write(GPIOA, 0x06);
  244.         delay();       
  245.         GPIO_Write(GPIOA, 0x04);
  246.         delay();
  247.         GPIO_Write(GPIOA, 0x0C);
  248.         delay();
  249.         GPIO_Write(GPIOA, 0x08);
  250.         delay();       
  251.   }
  252. }
  253. M=0;
  254. }
  255.    void num1(void)               
  256. {

  257. M=M+1;

  258. }
  259. /*void num2(void)               
  260. {
  261. if(M<=0)
  262. {
  263. M=1  ;
  264. }
  265.   M=M-1;
  266. }          */
  267. void motor_ccw00(u8 key)
  268.   {
  269.    
  270.         /* Turn Off Select LED */
  271.     switch(key)
  272.     {
  273.           case 0:
  274.                  
  275.           motor_Turn_on_1();   //反转
  276.           break;

  277.         case 1:
  278.                  
  279.           motor_Turn_on_2();         //正转
  280.           break;

  281.         case 2:                                        //反转n圈
  282.                  
  283.           motor_Turn_on_3();
  284.           break;

  285.         case 3:
  286.                
  287.          motor_Turn_on_4();                //正转n圈
  288.          break;
  289.        case 4:
  290.                  num1();
  291.                                 
  292.          break;
  293.         /*         case 5:
  294.                  num2();
  295.                   motor_Turn_on_4();               
  296.          break;                            */
  297.         default:
  298.           GPIO_ResetBits(GPIOA, GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);
  299.           break;
  300.     }

  301. }   
  302. int main(void)
  303. {                       
  304. //        int m=2, n=1;
  305.     u8 KeyNum = 0;
  306.         #ifdef DEBUG
  307.         debug();
  308.     #endif       

  309.         USART_Configuration();         //必须放在前面
  310.         RCC_Configuration();
  311.         GPIO_Configuration();
  312.     GPIO_KEY_Config();
  313. //        ADS7843_Init();       

  314.     while (1)
  315.    {
  316.                 KeyNum=ReadKeyDown();
  317.                    motor_ccw00(KeyNum-1);
  318.             
  319.     }         
  320. }

  321. void USART_Configuration(void)
  322. {
  323.      USART_InitTypeDef USART_InitStructure;

  324.      USART_InitStructure.USART_BaudRate = 115200;

  325.          USART_InitStructure.USART_WordLength = USART_WordLength_8b;

  326.          USART_InitStructure.USART_StopBits = USART_StopBits_1;

  327.          USART_InitStructure.USART_Parity = USART_Parity_No;

  328.          USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;

  329.          USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;       

  330.          STM_EVAL_COMInit(COM1, &USART_InitStructure);
  331. }          

  332. void RCC_Configuration()
  333. {
  334.          //定义错误状态变量
  335.          ErrorStatus HSEStartUpStatus;
  336.        
  337.          //将RCC寄存器重新设置为默认值
  338.          RCC_DeInit();

  339.          //打开外部高速时钟晶振
  340.          RCC_HSEConfig(RCC_HSE_ON);

  341.          //等待外部高速时钟晶振工作
  342.          HSEStartUpStatus = RCC_WaitForHSEStartUp();
  343.          if(HSEStartUpStatus == SUCCESS)
  344.          {
  345.                  //设置AHB时钟(HCLK)为系统时钟
  346.                  RCC_HCLKConfig(RCC_SYSCLK_Div1);

  347.                  //设置高速AHB时钟(APB2)为HCLK时钟
  348.                  RCC_PCLK2Config(RCC_HCLK_Div1);

  349.                  //设置低速AHB时钟(APB1)为HCLK的2分频
  350.                  RCC_PCLK1Config(RCC_HCLK_Div2);
  351.                
  352.                  //设置FLASH代码延时
  353.                  FLASH_SetLatency(FLASH_Latency_2);

  354.                  //使能预取指缓存
  355.                  FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);

  356.                  //设置PLL时钟,为HSE的9倍频 8MHz * 9 = 72MHz
  357.                  RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9);

  358.                   //使能PLL
  359.                  RCC_PLLCmd(ENABLE);

  360.                  //等待PLL准备就绪
  361.                  while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);

  362.                  //设置PLL为系统时钟源
  363.                  RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);

  364.                  //判断PLL是否是系统时钟
  365.                  while(RCC_GetSYSCLKSource() != 0x08);
  366.          }

  367.          //开启TIM3的时钟
  368.          RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
  369.          //开启GPIOB的时钟和复用功能
  370.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO,ENABLE);

  371. }

  372. void GPIO_Configuration()
  373. {
  374.          GPIO_InitTypeDef GPIO_InitStructure;

  375.          RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//打开外设A,的时钟

  376.          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;

  377.          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;//IO口的方向

  378.          GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

  379.          GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化外设0,1,2,3,6的端口
  380. }

  381. /**
  382.   * [url=home.php?mod=space&uid=247401]@brief[/url]  Retargets the C library printf function to the USART.
  383.   * @param  None
  384.   * @retval None
  385.   */
  386. PUTCHAR_PROTOTYPE
  387. {
  388.   /* Place your implementation of fputc here */
  389.   /* e.g. write a character to the USART */
  390.   USART_SendData(EVAL_COM1, (uint8_t) ch);

  391.   /* Loop until the end of transmission */
  392.   while (USART_GetFlagStatus(EVAL_COM1, USART_FLAG_TC) == RESET)
  393.   {
  394.   }

  395.   return ch;
  396. }

  397. #ifdef  USE_FULL_ASSERT

  398. /**
  399.   * @brief  Reports the name of the source file and the source line number
  400.   *         where the assert_param error has occurred.
  401.   * @param  file: pointer to the source file name
  402.   * @param  line: assert_param error line source number
  403.   * @retval None
  404.   */

  405. void assert_failed(uint8_t* file, uint32_t line)
  406. {
  407.   /* User can add his own implementation to report the file name and line number,
  408.      ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  409.   /* Infinite loop */
  410.   while (1)
  411.   {
  412.   }
  413. }
  414. #endif
  415. /**
  416.   * @}
  417.   */

  418. /**
  419.   * @}
  420.   */
  421. /******************* (C) COPYRIGHT 2010 STMicroelectronics *****END OF FILE****/
楼主小白一只,只为潜心做毕业设计,,可能会有很多问题,虚心听取大家的指正,多谢各位了。。
 楼主| jiangsai 发表于 2013-4-27 08:27 | 显示全部楼层
好像那个M在加一后,在下一个函数中引用时M还是保持着初始值0,
mmuuss586 发表于 2013-4-27 08:35 | 显示全部楼层
1、可以;
2、是不是定义了一个常量;
 楼主| jiangsai 发表于 2013-4-27 08:37 | 显示全部楼层
外出一下,下午回来回你们
 楼主| jiangsai 发表于 2013-4-27 08:38 | 显示全部楼层
mmuuss586 发表于 2013-4-27 08:35
1、可以;
2、是不是定义了一个常量;

是全局变量,你看看那个M为什么在下面的函数应用中还是初值0
杨爱林林 发表于 2013-4-27 08:38 | 显示全部楼层
jiangsai 发表于 2013-4-27 07:58
我在做小的毕业设计,没带系统。。并且只有设了一个全局变量,在main。c的开头设置的。。后面的函数要用 ...

你在main.c里面定义全局变量  U8 m=0;
在其他文件中想用的话  只要  extern u8 m;
就好了
还有 你确定 执行过m=m+1;那句了吗
 楼主| jiangsai 发表于 2013-4-27 19:47 | 显示全部楼层
杨爱林林 发表于 2013-4-27 08:38
你在main.c里面定义全局变量  U8 m=0;
在其他文件中想用的话  只要  extern u8 m;
就好了

反正按键按了,但m的值好像始终都是初值
 楼主| jiangsai 发表于 2013-4-27 19:48 | 显示全部楼层
杨爱林林 发表于 2013-4-27 08:38
你在main.c里面定义全局变量  U8 m=0;
在其他文件中想用的话  只要  extern u8 m;
就好了

其实我觉得就是这个地方粗了问题
 楼主| jiangsai 发表于 2013-4-27 19:52 | 显示全部楼层
杨爱林林 发表于 2013-4-27 08:38
你在main.c里面定义全局变量  U8 m=0;
在其他文件中想用的话  只要  extern u8 m;
就好了

我是不想多次使用调用,所以定义了个全局变量。。希望在下次用到M值时用到的是这次M变化之后的值,但实际没有达到那样子的效果。。请问下是什么原因呢
杨爱林林 发表于 2013-4-27 21:07 | 显示全部楼层
你在m=m+1;设个断点吧
个人感觉 你程序没执行那步
 楼主| jiangsai 发表于 2013-4-28 09:27 | 显示全部楼层
杨爱林林 发表于 2013-4-27 21:07
你在m=m+1;设个断点吧
个人感觉 你程序没执行那步

如何设置断点呢,我先百度下。。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

49

帖子

0

粉丝
快速回复 在线客服 返回列表 返回顶部