#ifdef #else #endif #fi #ifndef 的用法(高手勿进)

lijinyan3000 2008-03-21 04:51:12
  预处理就是在进行编译的第一遍词法扫描和语法分析之前所作的工作。说白了,就是对源文件进行编译前,先对预处理部分进行处理,然后对处理后的代码进行编译。这样做的好处是,经过处理后的代码,将会变的很精短。
   关于预处理命令中的文件包含(#include),宏定义(#define),书上已经有了详细的说明,在这里就不详述了。这里主要是对条件编译(#ifdef,#else,#endif,#if等)进行说明。以下分3种情况:
  1:情况1:
  #ifdef _XXXX
  ...程序段1...
  #else
  ...程序段2...
  #endif
   这表明如果标识符_XXXX已被#define命令定义过则对程序段1进行编译;否则对程序段2进行编译。
  例:
  #define NUM
  .............
  .............
  .............
  #ifdef NUM
   printf("之前NUM有过定义啦!:) \n");
  #else
   printf("之前NUM没有过定义!:( \n");
  #endif
  }
   如果程序开头有#define NUM这行,即NUM有定义,碰到下面#ifdef NUM的时候,当然执行第一个printf。否则第二个printf将被执行。
   我认为,用这种,可以很方便的开启/关闭整个程序的某项特定功能。
  2:情况2:
  #ifndef _XXXX
  ...程序段1...
  #else
  ...程序段2...
  #endif
   这里使用了#ifndef,表示的是if not def。当然是和#ifdef相反的状况(如果没有定义了标识符_XXXX,那么执行程序段1,否则执行程序段2)。例子就不举了。
  3:情况3:
  #if 常量
  ...程序段1...
  #else
  ...程序段2...
  #endif
   这里表示,如果常量为真(非0,随便什么数字,只要不是0),就执行程序段1,否则执行程序段2。
   我认为,这种方法可以将测试代码加进来。当需要开启测试的时候,只要将常量变1就好了。而不要测试的时候,只要将常量变0。
...全文
113192 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
chin_yong 2010-07-15
  • 打赏
  • 举报
回复
学习一下
zysdehao 2009-09-30
  • 打赏
  • 举报
回复
thank you!
Supper_Jerry 2008-03-21
  • 打赏
  • 举报
回复
写的不错,学习
lijinyan3000 2008-03-21
  • 打赏
  • 举报
回复
  我们主要使用以下几种方法,假设我们已在程序首部定义#ifdef DEBUG与#ifdef TEST:

  1.利用#ifdef/#endif将某程序功能模块包括进去,以向某用户提供该功能。

  在程序首部定义#ifdef HNLD:

  #ifdef HNLD

  #include"n166_hn.c"

  #endif

  如果不许向别的用户提供该功能,则在编译之前将首部的HNLD加一下划线即可。

  2.在每一个子程序前加上标记,以便追踪程序的运行。

  #ifdef DEBUG

  printf(" Now is in hunan !");

  #endif

  3.避开硬件的限制。有时一些具体应用环境的硬件不一样,但限于条件,本地缺乏这种设备,于是绕过硬件,直接写出预期结果。具体做法是:

  #ifndef TEST

  i=dial();

  //程序调试运行时绕过此语句

  #else

  i=0;

  #endif

  调试通过后,再屏蔽TEST的定义并重新编译,即可发给用户使用了。

8192CU LINUX驱动/****************************************************************************** * * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA * * ******************************************************************************/ /* * Public General Config */ #define AUTOCONF_INCLUDED #define RTL871X_MODULE_NAME "92CU" #define DRV_NAME "rtl8192cu" #define CONFIG_USB_HCI 1 #define CONFIG_RTL8192C 1 #define PLATFORM_LINUX 1 //#define CONFIG_IOCTL_CFG80211 1 #ifdef CONFIG_IOCTL_CFG80211 #define CONFIG_CFG80211_FORCE_COMPATIBLE_2_6_37_UNDER //#define CONFIG_DEBUG_CFG80211 1 #endif /* * Internal General Config */ //#define CONFIG_PWRCTRL //#define CONFIG_H2CLBK #define CONFIG_EMBEDDED_FWIMG 1 //#define CONFIG_FILE_FWIMG #ifdef CONFIG_WAKE_ON_WLAN #define CONFIG_WOWLAN 1 #endif //CONFIG_WAKE_ON_WLAN #define CONFIG_R871X_TEST 1 #define CONFIG_80211N_HT 1 #define CONFIG_RECV_REORDERING_CTRL 1 //#define CONFIG_TCP_CSUM_OFFLOAD_RX 1 //#define CONFIG_DRVEXT_MODULE 1 #ifndef CONFIG_MP_INCLUDED #define CONFIG_IPS 1 #ifdef CONFIG_IPS //#define CONFIG_IPS_LEVEL_2 1 //enable this to set default IPS mode to IPS_LEVEL_2 #endif #define SUPPORT_HW_RFOFF_DETECTED 1 #define CONFIG_LPS 1 #define CONFIG_BT_COEXIST 1 //befor link #define CONFIG_ANTENNA_DIVERSITY //after link #ifdef CONFIG_ANTENNA_DIVERSITY #define CONFIG_SW_ANTENNA_DIVERSITY //#define CONFIG_HW_ANTENNA_DIVERSITY #endif #define CONFIG_IOL #else //#ifndef CONFIG_MP_INCLUDED #define CONFIG_MP_IWPRIV_SUPPORT 1 #endif //#ifndef CONFIG_MP_INCLUDED #define CONFIG_AP_MODE 1 #define CONFIG_NATIVEAP_MLME 1 // Added by Albert 20110314 #define CONFIG_P2P 1 #ifdef CONFIG_P2P // Added by Albert 20110812 // The CONFIG_WFD is for supporting the Wi-Fi display //#define CONFIG_WFD 1 // Unmarked if there is low p2p scanned ratio; Kurt //#define CONFIG_P2P_AGAINST_NOISE 1 #define CONFIG_P2P_REMOVE_GROUP_INFO //#define CONFIG_DBG_P2P #endif // Added by Kurt 20110511 //#define CONFIG_TDLS 1 #ifdef CONFIG_TDLS #define CONFIG_TDLS_AUTOSETUP 1 #define CONFIG_TDLS_AUTOCHECKALIVE 1 #endif #ifdef CONFIG_AP_MODE #ifndef CONFIG_NATIVEAP_MLME #define CONFIG_HOSTAPD_MLME 1 #endif #define CONFIG_FIND_BEST_CHANNEL 1 #endif #define CONFIG_SKB_COPY 1//for amsdu #define CONFIG_LED #ifdef CONFIG_LED #define CONFIG_SW_LED #ifdef CONFIG_SW_LED //#define CONFIG_LED_HANDLED_BY_CMD_THREAD #endif #endif // CONFIG_LED #define USB_INTERFERENCE_ISSUE // this should be checked in all usb interface #define CONFIG_GLOBAL_UI_PID #define CONFIG_LAYER2_ROAMING #define CONFIG_LAYER2_ROAMING_RESUME //#define CONFIG_ADAPTOR_INFO_CACHING_FILE // now just applied on 8192cu only, should make it general... //#define CONFIG_RESUME_IN_WORKQUEUE //#define CONFIG_SET_SCAN_DENY_TIMER #define CONFIG_LONG_DELAY_ISSUE #define CONFIG_NEW_SIGNAL_STAT_PROCESS //#define CONFIG_SIGNAL_DISPLAY_DBM //display RX signal with dbm #ifdef CONFIG_IOL #define CONFIG_IOL_LLT #define CONFIG_IOL_MAC #define CONFIG_IOL_BB_PHY_REG #define CONFIG_IOL_BB_AGC_TAB #define CONFIG_IOL_RF_RF90_PATH_A #define CONFIG_IOL_RF_RF90_PATH_B #endif #define CONFIG_BR_EXT 1 // Enable NAT2.5 support for STA mode interface with a L2 Bridge #ifdef CONFIG_BR_EXT #define CONFIG_BR_EXT_BRNAME "br0" #endif // CONFIG_BR_EXT #define CONFIG_TX_MCAST2UNI 1 // Support IP multicast->unicast //#define CONFIG_CHECK_AC_LIFETIME 1 // Check packet lifetime of 4 ACs. /* * Interface Related Config */ //#define CONFIG_USB_INTERRUPT_IN_PIPE 1 #ifndef CONFIG_MINIMAL_MEMORY_USAGE #define CONFIG_USB_TX_AGGREGATION 1 #define CONFIG_USB_RX_AGGREGATION 1 #endif #define CONFIG_PREALLOC_RECV_SKB 1 //#define CONFIG_REDUCE_USB_TX_INT 1 // Trade-off: Improve performance, but may cause TX URBs blocked by USB Host/Bus driver on few platforms. //#define CONFIG_EASY_REPLACEMENT 1 /* * CONFIG_USE_USB_BUFFER_ALLOC_XX uses Linux USB Buffer alloc API and is for Linux platform only now! */ #define CONFIG_USE_USB_BUFFER_ALLOC_TX 1 // Trade-off: For TX path, improve stability on some platforms, but may cause performance degrade on other platforms. //#define CONFIG_USE_USB_BUFFER_ALLOC_RX 1 // For RX path /* * USB VENDOR REQ BUFFER ALLOCATION METHOD * if not set we'll use function local variable (stack memory) */ //#define CONFIG_USB_VENDOR_REQ_BUFFER_DYNAMIC_ALLOCATE #define CONFIG_USB_VENDOR_REQ_BUFFER_PREALLOC #define CONFIG_USB_VENDOR_REQ_MUTEX #define CONFIG_VENDOR_REQ_RETRY //#define CONFIG_USB_SUPPORT_ASYNC_VDN_REQ 1 /* * HAL Related Config */ #define RTL8192C_RX_PACKET_NO_INCLUDE_CRC 1 #define SUPPORTED_BLOCK_IO #define RTL8192CU_FW_DOWNLOAD_ENABLE 1 #define CONFIG_ONLY_ONE_OUT_EP_TO_LOW 0 #define CONFIG_OUT_EP_WIFI_MODE 0 #define ENABLE_USB_DROP_INCORRECT_OUT 0 #define RTL8192CU_ASIC_VERIFICATION 0 // For ASIC verification. #define RTL8192CU_ADHOC_WORKAROUND_SETTING 1 #define DISABLE_BB_RF 0 #define RTL8191C_FPGA_NETWORKTYPE_ADHOC 0 #ifdef CONFIG_MP_INCLUDED #define MP_DRIVER 1 #undef CONFIG_USB_TX_AGGREGATION #undef CONFIG_USB_RX_AGGREGATION #else #define MP_DRIVER 0 #endif /* * Platform Related Config */ #ifdef CONFIG_PLATFORM_MN10300 #define CONFIG_SPECIAL_SETTING_FOR_FUNAI_TV #if defined (CONFIG_SW_ANTENNA_DIVERSITY) #undef CONFIG_SW_ANTENNA_DIVERSITY #define CONFIG_HW_ANTENNA_DIVERSITY #endif #endif #ifdef CONFIG_WISTRON_PLATFORM #endif #ifdef CONFIG_PLATFORM_TI_DM365 #define CONFIG_USE_USB_BUFFER_ALLOC_RX 1 #endif /* * Debug Related Config */ //#define CONFIG_DEBUG_RTL871X #define DBG 0 #define CONFIG_DEBUG_RTL819X #define CONFIG_PROC_DEBUG 1 //#define DBG_IO //#define DBG_DELAY_OS //#define DBG_MEM_ALLOC //#define DBG_IOCTL //#define DBG_TX //#define DBG_XMIT_BUF //#define DBG_TX_DROP_FRAME //#define DBG_RX_DROP_FRAME //#define DBG_RX_SEQ //#define DBG_RX_SIGNAL_DISPLAY_PROCESSING //#define DBG_RX_SIGNAL_DISPLAY_SSID_MONITORED "jeff-ap" //#define DBG_EXPIRATION_CHK //#define DBG_SHOW_MCUFWDL_BEFORE_51_ENABLE //#define DBG_ROAMING_TEST //#define DBG_HAL_INIT_PROFILING #define DBG_MEMORY_LEAK 1 #define DBG_CONFIG_ERROR_DETECT //#define DBG_CONFIG_ERROR_RESET
如果用PHP不能再满足你的需求,最好的办法就是开发PHP扩展。这有一些好处: 1、增加自己的特殊功能。 2、保护自己的专利代码。 这是几年前的一篇英文文章,现在已被翻译成中文版的。 作者应该是hshq_cn。 链接是:http://bbs3.chinaunix.net/thread-1028798-1-1.html。 现我将此转变为PDF文件,仅有兴趣者参阅。同时非常感谢 原作者及hshq_cn,给我们带来的这么好的资料。里面还有一个幻灯片的,也是很有帮助的文档。另外,再提供一篇相关的文章(http://www.programbbs.com/doc/4083.htm): 编写php的extension实例的方法 所属类别:JSP 推荐指数:★★☆ 文档人气:161 本周人气:1 发布日期:2008-7-3 一、说明 前端时间因为客户的原因折腾了一下asp的扩展,在ATL的帮助下写一个asp的模块还是很容易的。不巧的时刚刚折腾完asp的COM就碰到另一个客户的问题。客户想给系统集成ICBC的接口,但是用ICBC的接口需要用他们的提供的库函数去 1. sign对发送的数据进行签名 2. getcertid获取用户证书的版本 3. verifySign对签名后的数据进行验证 问题是ICBC只给了现成的COM组件,意味在只能在Win的主机上使用。俺们公司只有linux的主机,在*nix上就要自己想办法调用ICBC给的静态库了。对此我们有两个想法 1.用ICBC的静态库做一个独立的执行文件,用PHP的系统调用函数来执行这个独立的执行文件 2.将ICBC的静态库做出一个PHP的扩展 方法一应该比较简单,但是远不如方法二的灵活。搞成PHP的扩展,只要服务器编译一次,服务器上的所有客户都可以用的。 有ASP的前科,俺觉得搞个PHP的也不是什么难事。操起google搜了一通,结果发现Zend已经写了一个如何编写php extension的教程: http://devzone.zend.com/article/1021-Extension-Writing-Part-I-Introduction-to-PHP-and-Zend 浏览完牛人的大作,更是信心十足,php的扩展其实很简单,分七步走: 1. 制作编译配置文件:config.m4 2. 执行phpize生成扩展的框架 3. 在生成的php_xxx.h中声明自己写的函数 4. 在xxx.c中实现自己的函数 5. 编译自己的扩展 6. 将生成的xxx.so拷贝到php.ini中指定的extensions_dir 7. 在php.ini中打开xxx.so的调用 此问题问题唯一搞的地方就是在config.m4中折腾出正确的Makefile,因为Zend的教程中没有提到,俺自己也折腾了好久,才搞出来。 二、实际操作 1.建立工作环境 将php源码包解开,我的版本的php-4.4.4,转到源码包中的ext目录建立一个新的目录叫icbc,然后在icbc目录下touch三个文件config.m4、php_icbc.h、icbc.c 2.建立config.m4 内容如下: PHP_ARG_ENABLE(icbc, whether to enable ICBC support, [ --enable-icbc Enable ICBC support]) if test \"$PHP_ICBC\" = \"yes\"; then AC_DEFINE(HAVE_ICBC, 1, [Whether you have ICBC]) if test -f ./libicbcapi.a; then PHP_ADD_LIBRARY_WITH_PATH(icbcapi, ./, ICBCAPI_SHARED_LIBADD) PHP_SUBST(ICBCAPI_SHARED_LIBADD) AC_MSG_RESULT(checking for libicbcapi.a is OK) else AC_MSG_RESULT(libicbcapi.a not found) AC_MSG_ERROR(Please make sure the libicbcapi.a is in current directory) [Page] fi PHP_NEW_EXTENSION(icbc, icbc.c, $ext_shared) fi 第三行判断是否要启用icbc扩展, 第五行判断ICBC的静态库是否在当前目录(phpdir/ext/icbc)下 第六、七行将ICBC的静态库加入到编译环境中 3.在php_icbc.h中声明我们要导出的函数icbc_sign、icbc_vsign、icbc_getCertID #ifndef PHP_ICBC_H #define PHP_ICBC_H extern zend_module_entry icbc_module_entry; #define phpext_icbc_ptr &icbc_module_entry #ifdef PHP_WIN32 #define PHP_ICBC_API __declspec(dllexport) #else #define PHP_ICBC_API #endif #ifdef ZTS #include \"TSRM.h\" #endif PHP_MINIT_FUNCTION(icbc); PHP_MSHUTDOWN_FUNCTION(icbc); PHP_RINIT_FUNCTION(icbc); PHP_RSHUTDOWN_FUNCTION(icbc); PHP_MINFO_FUNCTION(icbc); /*Modify youself here*/ PHP_FUNCTION(icbc_sign); PHP_FUNCTION(icbc_vsign); PHP_FUNCTION(icbc_getCertID); /****End of Self control section***/ #ifdef ZTS #define ICBC_G(v) TSRMG(icbc_globals_id, zend_icbc_globals *, v) #else #define ICBC_G(v) (icbc_globals.v) #endif #endif /* PHP_ICBC_H */ 涉及到我们也就 PHP_FUNCTION(icbc_sign); PHP_FUNCTION(icbc_vsign); PHP_FUNCTION(icbc_getCertID); 其他的都是PHP各个状态的入口函数声明 4.编写这三个函数的实现: #ifdef HAVE_CONFIG_H #include \"config.h\" #endif #include \"php.h\" #include \"php_ini.h\" #include \"ext/standard/info.h\" #include \"php_icbc.h\" #include \"icbcapi.h\" static int le_icbc; zend_function_entry icbc_functions[] = { PHP_FE(icbc_sign,NULL) PHP_FE(icbc_vsign,NULL) PHP_FE(icbc_getCertID,NULL) {NULL, NULL, NULL} /* Must be the last line in icbc_functions[] */ }; zend_module_entry icbc_module_entry = { #if ZEND_MODULE_API_NO >= 20010901 STANDARD_MODULE_HEADER, #endif \"icbc\", icbc_functions, PHP_MINIT(icbc), PHP_MSHUTDOWN(icbc), PHP_RINIT(icbc), /* Replace with NULL if there’s nothing to do at request start */ PHP_RSHUTDOWN(icbc), /* Replace with NULL if there’s nothing to do at request end */ [Page] PHP_MINFO(icbc), #if ZEND_MODULE_API_NO >= 20010901 \"0.1\", /* Replace with version number for your extension */ #endif STANDARD_MODULE_PROPERTIES }; #ifdef COMPILE_DL_ICBC ZEND_GET_MODULE(icbc) #endif PHP_MINIT_FUNCTION(icbc) { return SUCCESS; } PHP_MSHUTDOWN_FUNCTION(icbc) { return SUCCESS; } PHP_RINIT_FUNCTION(icbc) { return SUCCESS; } PHP_RSHUTDOWN_FUNCTION(icbc) { return SUCCESS; } PHP_MINFO_FUNCTION(icbc) { php_info_print_table_start(); php_info_print_table_header(2, \"icbc support\", \"enabled\"); php_info_print_table_end(); } PHP_FUNCTION(icbc_sign) { char* src; int srclen; char* pkey; int keylen; char* keypass; int keypasslen; char* signedbuf; int signedbuflen; FILE* fp; char key[2000]; int rcc; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,\"sss\",&src,&srclen,&pkey,&keylen,&keypass,&keypasslen) == FAILURE){ return; } fp = fopen(pkey,\"rb\"); if(fp == NULL) { return; } fseek(fp,2,SEEK_SET); fread((void*)key,609,1,fp); fclose(fp); if(rcc = sign(src,srclen,key,607,keypass,&signedbuf,&signedbuflen) >= 0){ base64enc(signedbuf,signedbuflen,&signedbuf,&signedbuflen); src = estrndup(signedbuf,signedbuflen); if(signedbuf != NULL) infosec_free(signedbuf); RETURN_STRING(src,1); [Page] }else{ RETURN_LONG(rcc); } }PHP_FUNCTION(icbc_vsign) { char* src; int srclen; char* cert; int certlen; char* vsignedbuf; int vsignedbuflen; FILE* fp; char vcert[2000]; int rcc; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,\"sss\",&src,&srclen,&cert,&certlen,&vsignedbuf,&vsignedbuflen) == FAILURE){ return; } fp = fopen(cert,\"rb\"); if(fp == NULL) { return; } fread((void*)vcert,1525,1,fp); fclose(fp); base64dec(vsignedbuf,vsignedbuflen,&vsignedbuf,&vsignedbuflen); if(rcc = verifySign(src,srclen,vcert,1525,vsignedbuf,vsignedbuflen) >= 0){ if(vsignedbuf != NULL) infosec_free(vsignedbuf); RETURN_TRUE; }else{ if(vsignedbuf != NULL) infosec_free(vsignedbuf); RETURN_LONG(rcc); } } PHP_FUNCTION(icbc_getCertID) { char* arg; char* certid; int arg_len,certidlen; FILE* fp; char cert[2000]; if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,\"s\", &arg,&arg_len) == FAILURE){ return; } fp = fopen(arg,\"rb\"); if(fp == NULL) { return; } fread((void*)cert,1525,1,fp); fclose(fp); [Page] if(!getCertID(cert,1525,&certid,&certidlen)) { arg = estrndup(certid,certidlen); if(certid != NULL) infosec_free(certid); RETURN_STRING(arg,1); }else{ return; } } 先在zend_function_entry icbc_functions[]数组中放入我们的要实现的函数名,然后是一堆php各个状态入口函数,详情请看Zend的教程。最后是在PHP_FUNCTION宏定义中放我们声明函数的具体实现。具体实现时难点也就是参数的传入和结果传出,还好PHP已经为我们做了很好的抽象。在Zend的教程中也有详尽的说明,俺就不啰嗦了。关键代码照搬icbc的test.c就行了。 5.编译安装我们的库 先将ICBC的头文件考到当前目录,重命名为icbcapi.php,将静态库也cp过来,重命名为*nix的标准形式libicbcapi.a,然后运行 phpize 生成configure,运行 ./configure --enable-icbc 生成Makefile,这里有一个很搞的地方,在生成的Makefile中最后一句中指定ICBC静态库的地方错了,正确的应该是(红色标记地方): $(LIBTOOL) --mode=link $(CC) $(COMMON_FLAGS) $(CFLAGS_CLEAN) $(EXTRA_CFLAGS) $(LDFLAGS) -o $@ -export-dynamic -avoid-version -prefer-pic -module -rpath $(phplibdir) $(EXTRA_LDFLAGS) $(shared_objects_icbc) $(ICBCAPI_SHARED_LIBADD) 改好Makefile后就可以执行 make 如果一切顺利的话会在modules中得到我们的icbc.so,将我们的icbc.so拷贝到/usr/local/lib/php/extensions目录下,然后在php.ini中确认extensions_dir的值是/usr/local/lib/php/extensions,然后加入这句话 extension=icbc.so 重启apache后,就可以在php中直接调用这三个函数了 6.测试程序,要将测试的证书和key文件放到php测试文件的当前目录 FILE__); $key = $realpath.\"/user.key\"; $cert = $realpath.\"/user.crt\"; $src = \"zzz\"; $passwd = \"12345678\"; echo \"The Cert file information is \"; echo icbc_getCertID($cert); echo \"
\"; $b64sdata = icbc_sign($src,$key,$passwd); echo \"The string \".$src.\" encrypt by icbc api is \".$b64sdata.\"(base64 encoded)
\"; echo \"Now we check it weather is correct....
\"; if(icbc_vsign(\"zzz\",$cert,$b64sdata)){ echo \"The signtrue to \".$src.\" is right!!
\"; [Page] }else{ echo \"The signtrue to \".$src.\" is wrong!!
\"; exit(); } ?>

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧