extern void * memcpy(void *dest,void *src,unsigned int count)

这篇博客详细解释了 C 语言中的 memcpy 函数,包括其原型、功能和使用方法,并通过示例展示了如何正确使用 memcpy 复制字符串。讨论了在不同情况下,如目的字符串长度大于源字符串长度时可能出现的问题,以及如何避免这些问题。

 原型:extern void *memcpy(void *dest, void *src, unsigned int count);

  用法:#include <string.h>
   
  功能:由src所指内存区域复制count个字节到dest所指内存区域。
   
  说明:src和dest所指内存区域不能重叠,函数返回指向dest的指针。
   
  举例:

 

 

   clrscr()在 #include <syslib.h>中。但是gcc找不到。

/*-------------------------------------------------------------------------- STRING.H String functions for C251 Version 4. Copyright (c) 1995-2007 Keil Elektronik GmbH and Keil Software, Inc. All rights reserved. --------------------------------------------------------------------------*/ #pragma SAVE #pragma PARM251 #ifndef _SIZE_T #define _SIZE_T typedef unsigned int size_t; #endif #ifndef NULL #define NULL ((void *) 0L) #endif #if (__C251__ >= 200) extern char *strcat (char *s1, const char *s2) reentrant; extern char *strncat (char *s1, const char *s2, size_t n) reentrant; extern char strcmp (const char *s1, const char *s2) reentrant; extern char strncmp (const char *s1, const char *s2, size_t n) reentrant; extern char *strcpy (char *s1, const char *s2) reentrant; extern char *strncpy (char *s1, const char *s2, size_t n) reentrant; extern size_t strlen (const char *) reentrant; extern char *strchr (const char *s, char c) reentrant; extern int strpos (const char *s, char c) reentrant; extern char *strrchr (const char *s, char c) reentrant; extern int strrpos (const char *s, char c) reentrant; extern size_t strspn (const char *s, const char *set) reentrant; extern size_t strcspn (const char *s, const char *set) reentrant; extern char *strpbrk (const char *s, const char *set) reentrant; extern char *strrpbrk (const char *s, const char *set) reentrant; extern char memcmp (const void *s1, const void *s2, size_t n) reentrant; extern void *memcpy (void *s1, const void *s2, size_t n) reentrant; extern void *memchr (const void *s, char val, size_t n) reentrant; extern void *memccpy (void *s1, const void *s2, char val, size_t n) reentrant; extern void *memmove (void *s1, const void *s2, size_t n) reentrant; extern void *memset (void *s, char val, size_t n) reentrant; extern void far *fmemset (void far *s, char val, unsigned int n) reentrant; extern void xdata *xmemset (void xdata *s, char val, unsigned int n) reentrant; extern void far *fmemcpy (void far *s1, void far *s2, unsigned int n) reentrant; extern void xdata *xmemcpy (void xdata *s1, void xdata *s2, unsigned int n) reentrant; extern unsigned long hstrlen (const char huge *s) reentrant; extern char hstrcmp (const char huge *s1, const char huge *s2) reentrant; extern char huge *hstrcpy (char huge *s1, const char huge *s2) reentrant; #pragma PARM4 // allow a maximum of 4 long as register parameters extern char huge *hstrncpy (char huge *s1, const char huge *s2, unsigned long n) reentrant; extern char hmemcmp (const void huge *s1, const void huge *s2, unsigned long len) reentrant; extern void huge *hmemcpy (void huge *s1, const void huge *s2, unsigned long len) reentrant; extern void huge *hmemchr (const void huge *ptr, char val, unsigned long len) reentrant; extern char huge *hmemccpy (char huge *dest, const char huge *src, char val, unsigned long len) reentrant; extern void huge *hmemmove (void huge *s1, const void huge *s2, unsigned long len) reentrant; extern void huge *hmemset (void huge *ptr, char val, unsigned long len) reentrant; #else extern char *strcat (char *s1, char *s2); extern char *strncat (char *s1, char *s2, int n); extern char strcmp (char *s1, char *s2); extern char strncmp (char *s1, char *s2, int n); extern char *strcpy (char *s1, char *s2); extern char *strncpy (char *s1, char *s2, int n); extern int strlen (char *); extern char *strchr (const char *s, char c); extern int strpos (const char *s, char c); extern char *strrchr (const char *s, char c); extern int strrpos (const char *s, char c); extern int strspn (char *s, char *set); extern int strcspn (char *s, char *set); extern char *strpbrk (char *s, char *set); extern char *strrpbrk (char *s, char *set); extern char memcmp (void *s1, void *s2, int n); extern void *memcpy (void *s1, void *s2, int n); extern void *memchr (void *s, char val, int n); extern void *memccpy (void *s1, void *s2, char val, int n); extern void *memmove (void *s1, void *s2, int n); extern void *memset (void *s, char val, int n); #endif #pragma RESTORE C:\Keil_v5\C251\Inc\string.h(22): error C25: syntax error near '"string"' 编译错误
最新发布
08-27
把这一个arp.c的代码拆分为多个文件,显得专业.h .c /*!Copyright(c) 2022-2023 Shenzhen TP-LINK Technologies Co.Ltd. *All rights reserved. * *\file arp.c *\brief An solution of task. * *\author liuyan <liuyan11@tp-link.com.hk> *\version 1.0.0 *\date 22/8/2024 * *\history \arg 1.0.0 22/8/2024. liuyan. Create the file. */ /**************************************************************************************************/ /* INCLUDE_FILES */ /**************************************************************************************************/ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <sys/socket.h> #include <netinet/if_ether.h> #include <net/if.h> #include <sys/ioctl.h> #include <linux/if_packet.h> #include <time.h> #include <pthread.h> #include <libubox/blobmsg_json.h> #include <libubus.h> #include <libubox/blobmsg.h> /**************************************************************************************************/ /* DEFINES */ /**************************************************************************************************/ #define ARP_REQUEST 1 #define ARP_REPLY 2 #define INTERFACES "eth0" /* 系统中可用的网络接口 */ #define MAX_ARP_ENTRIES 256 /**************************************************************************************************/ /* TYPES */ /**************************************************************************************************/ typedef struct { int enable; /* 功能开关 */ int scan_interval; /* 扫描周期(秒)*/ int entry_timeout; /* 有效期(秒)__ARP_CONFIG_MAX */ int packet_interval; /* 发包间隔(毫秒) */ struct in_addr start_ip; /* 起始IP */ struct in_addr end_ip; /* 结束IP */ } arp_config_t; typedef struct { struct in_addr ip_addr; unsigned char mac_addr[6]; time_t last_seen; } arp_entry_t; /* 在全局变量 g_arp_config 的定义处添加默认值 */ static arp_config_t g_arp_config = { .enable = 0, .scan_interval = 60, .entry_timeout = 300, .packet_interval = 100, .start_ip = { .s_addr = 0x0A000201 }, /* 10.0.2.1 */ .end_ip = { .s_addr = 0x0A0002FF } /* 10.0.2.255 */ }; enum { ARP_CONFIG_ENABLE, ARP_CONFIG_SCAN_INTERVAL, ARP_CONFIG_ENTRY_TIMEOUT, ARP_CONFIG_PACKET_INTERVAL, ARP_CONFIG_START_IP, ARP_CONFIG_END_IP, __ARP_CONFIG_MAX }; static const struct blobmsg_policy arp_config_policy[__ARP_CONFIG_MAX] = { [ARP_CONFIG_ENABLE] = { .name = "enable", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_SCAN_INTERVAL] = { .name = "scan_interval", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_ENTRY_TIMEOUT] = { .name = "entry_timeout", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_PACKET_INTERVAL] = { .name = "packet_interval", .type = BLOBMSG_TYPE_INT32 }, [ARP_CONFIG_START_IP] = { .name = "start_ip", .type = BLOBMSG_TYPE_STRING }, [ARP_CONFIG_END_IP] = { .name = "end_ip", .type = BLOBMSG_TYPE_STRING }, }; static arp_entry_t g_arp_entries[MAX_ARP_ENTRIES]; static int g_arp_entry_count = 0; static pthread_mutex_t arp_mutex = PTHREAD_MUTEX_INITIALIZER; /**************************************************************************************************/ /* LOCAL_PROTOTYPES */ /**************************************************************************************************/ /* 发送arp请求 */ void send_arp_request(int sock, struct sockaddr_ll *socket_address, unsigned char *src_mac, unsigned char *src_ip, unsigned char *dst_ip); /* 处理arp回复 */ void process_arp_reply(unsigned char *buffer, size_t length); /* arp回复线程 */ void* arp_reply_thread(void* arg); /* arp扫描线程 */ void* arp_scan_thread(void* arg); /* 开始arp扫描 */ void start_arp_scan(); /* 停止arp扫描 */ void stop_arp_scan(); /* 清除历史结果 */ void clear_arp_entries(); /* 设置arp的config */ void set_arp_config(arp_config_t *config); /* 获取arp的config */ void get_arp_config(arp_config_t *config); /* UBUS服务接口实现 */ int ubus_set_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_start_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_stop_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_scan_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_get_scan_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); int ubus_clear_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg); /**************************************************************************************************/ /* PUBLIC_FUNCTIONS */ /**************************************************************************************************/ /* 发送arp请求 */ void send_arp_request(int sock, struct sockaddr_ll *socket_address, unsigned char *src_mac, unsigned char *src_ip, unsigned char *dst_ip) { unsigned char buffer[42]; struct ethhdr *eth = (struct ethhdr *)buffer; struct arp_header { unsigned short hw_type; unsigned short proto_type; unsigned char hw_len; unsigned char proto_len; unsigned short opcode; unsigned char src_mac[6]; unsigned char src_ip[4]; unsigned char dst_mac[6]; unsigned char dst_ip[4]; } *arp = (struct arp_header *)(buffer + 14); /* 填充以太网头部 */ memset(eth->h_dest, 0xff, 6); /* 广播地址 */ memcpy(eth->h_source, src_mac, 6); eth->h_proto = htons(ETH_P_ARP); /* 填充ARP报文 */ arp->hw_type = htons(1); arp->proto_type = htons(ETH_P_IP); arp->hw_len = 6; arp->proto_len = 4; arp->opcode = htons(ARP_REQUEST); memcpy(arp->src_mac, src_mac, 6); memcpy(arp->src_ip, src_ip, 4); memset(arp->dst_mac, 0x00, 6); /* 目标MAC地址未知 */ memcpy(arp->dst_ip, dst_ip, 4); /* 发送ARP请求 */ if (sendto(sock, buffer, 42, 0, (struct sockaddr *)socket_address, sizeof(struct sockaddr_ll)) < 0) { perror("sendto failed"); exit(1); } } /* 处理arp回复 */ void process_arp_reply(unsigned char *buffer, size_t length) { struct ethhdr *eth = (struct ethhdr *)buffer; int i; if (ntohs(eth->h_proto) == ETH_P_ARP) { struct arp_header { unsigned short hw_type; unsigned short proto_type; unsigned char hw_len; unsigned char proto_len; unsigned short opcode; unsigned char src_mac[6]; unsigned char src_ip[4]; unsigned char dst_mac[6]; unsigned char dst_ip[4]; } *arp = (struct arp_header *)(buffer + 14); if (ntohs(arp->opcode) == ARP_REPLY) { pthread_mutex_lock(&arp_mutex); /* 检查是否已经存在该IP的条目 */ int found = 0; for (i = 0; i < g_arp_entry_count; ++i) { if (memcmp(&g_arp_entries[i].ip_addr, arp->src_ip, sizeof(struct in_addr)) == 0) { memcpy(g_arp_entries[i].mac_addr, arp->src_mac, 6); g_arp_entries[i].last_seen = time(NULL); found = 1; break; } } /* 如果是新主机,打印到串口并添加到条目 */ if (!found && g_arp_entry_count < MAX_ARP_ENTRIES) { printf("New host found: %d.%d.%d.%d with MAC address %02x:%02x:%02x:%02x:%02x:%02x\n", arp->src_ip[0], arp->src_ip[1], arp->src_ip[2], arp->src_ip[3], arp->src_mac[0], arp->src_mac[1], arp->src_mac[2], arp->src_mac[3], arp->src_mac[4], arp->src_mac[5]); memcpy(&g_arp_entries[g_arp_entry_count].ip_addr, arp->src_ip, sizeof(struct in_addr)); memcpy(g_arp_entries[g_arp_entry_count].mac_addr, arp->src_mac, 6); g_arp_entries[g_arp_entry_count].last_seen = time(NULL); ++g_arp_entry_count; } pthread_mutex_unlock(&arp_mutex); } } } /* arp回复线程 */ void* arp_reply_thread(void* arg) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket failed"); return NULL; } struct ifreq ifr; strncpy(ifr.ifr_name, INTERFACES, IFNAMSIZ); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } struct sockaddr_ll socket_address; socket_address.sll_ifindex = ifr.ifr_ifindex; socket_address.sll_halen = ETH_ALEN; memset(socket_address.sll_addr, 0xff, 6); unsigned char buffer[1500]; while (1) { ssize_t length = recvfrom(sock, buffer, sizeof(buffer), 0, NULL, NULL); if (length < 0) { perror("recvfrom failed"); close(sock); return NULL; } process_arp_reply(buffer, length); } close(sock); return NULL; } /* arp扫描线程 */ void* arp_scan_thread(void* arg) { int sock = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ARP)); if (sock < 0) { perror("socket failed"); return NULL; } struct ifreq ifr; strncpy(ifr.ifr_name, INTERFACES, IFNAMSIZ); if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } struct sockaddr_ll socket_address; socket_address.sll_ifindex = ifr.ifr_ifindex; socket_address.sll_halen = ETH_ALEN; memset(socket_address.sll_addr, 0xff, 6); unsigned char src_mac[6]; if (ioctl(sock, SIOCGIFHWADDR, &ifr) < 0) { perror("ioctl failed"); close(sock); return NULL; } memcpy(src_mac, ifr.ifr_hwaddr.sa_data, 6); unsigned char src_ip[4]; inet_pton(AF_INET, "10.0.2.15", src_ip); /* 这里使用实际的源IP地址 */ while (g_arp_config.enable) { struct in_addr current_ip = g_arp_config.start_ip; while (memcmp(&current_ip, &g_arp_config.end_ip, sizeof(struct in_addr)) <= 0) { unsigned char dst_ip[4]; memcpy(dst_ip, &current_ip, 4); send_arp_request(sock, &socket_address, src_mac, src_ip, dst_ip); /* 更新IP地址 */ uint32_t ip_int = ntohl(current_ip.s_addr); current_ip.s_addr = htonl(ip_int + 1); usleep(g_arp_config.packet_interval * 1000); } sleep(g_arp_config.scan_interval); } close(sock); return NULL; } /* 开始arp扫描 */ void start_arp_scan() { pthread_t thread_id; g_arp_config.enable = 1; pthread_create(&thread_id, NULL, arp_scan_thread, NULL); pthread_detach(thread_id); } /* 停止arp扫描 */ void stop_arp_scan() { g_arp_config.enable = 0; } /* 清除历史结果 */ void clear_arp_entries() { pthread_mutex_lock(&arp_mutex); g_arp_entry_count = 0; pthread_mutex_unlock(&arp_mutex); } /* 配置管理功能 */ /* 设置arp的config */ void set_arp_config(arp_config_t *config) { memcpy(&g_arp_config, config, sizeof(arp_config_t)); if (config->enable) { start_arp_scan(); } else { stop_arp_scan(); } } /* 获取arp的config */ void get_arp_config(arp_config_t *config) { memcpy(config, &g_arp_config, sizeof(arp_config_t)); } /* UBUS服务接口实现 */ int ubus_set_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_attr *tb[__ARP_CONFIG_MAX]; arp_config_t config; blobmsg_parse(arp_config_policy, __ARP_CONFIG_MAX, tb, blob_data(msg), blob_len(msg)); if (tb[ARP_CONFIG_ENABLE]) { config.enable = blobmsg_get_u32(tb[ARP_CONFIG_ENABLE]); } if (tb[ARP_CONFIG_SCAN_INTERVAL]) { config.scan_interval = blobmsg_get_u32(tb[ARP_CONFIG_SCAN_INTERVAL]); } if (tb[ARP_CONFIG_ENTRY_TIMEOUT]) { config.entry_timeout = blobmsg_get_u32(tb[ARP_CONFIG_ENTRY_TIMEOUT]); } if (tb[ARP_CONFIG_PACKET_INTERVAL]) { config.packet_interval = blobmsg_get_u32(tb[ARP_CONFIG_PACKET_INTERVAL]); } if (tb[ARP_CONFIG_START_IP]) { inet_pton(AF_INET, blobmsg_get_string(tb[ARP_CONFIG_START_IP]), &config.start_ip); } if (tb[ARP_CONFIG_END_IP]) { inet_pton(AF_INET, blobmsg_get_string(tb[ARP_CONFIG_END_IP]), &config.end_ip); } set_arp_config(&config); return 0; } int ubus_get_arp_config(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { arp_config_t config; struct blob_buf b = { 0 }; get_arp_config(&config); blob_buf_init(&b, 0); blobmsg_add_u32(&b, "enable", config.enable); blobmsg_add_u32(&b, "scan_interval", config.scan_interval); blobmsg_add_u32(&b, "entry_timeout", config.entry_timeout); blobmsg_add_u32(&b, "packet_interval", config.packet_interval); char ip_str[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &config.start_ip, ip_str, sizeof(ip_str)); blobmsg_add_string(&b, "start_ip", ip_str); inet_ntop(AF_INET, &config.end_ip, ip_str, sizeof(ip_str)); blobmsg_add_string(&b, "end_ip", ip_str); ubus_send_reply(ctx, req, b.head); return 0; } int ubus_start_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { start_arp_scan(); return 0; } int ubus_stop_scan(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { stop_arp_scan(); return 0; } int ubus_get_scan_status(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_buf b = { 0 }; blob_buf_init(&b, 0); printf("scan_running: %d (1:enable; 0:disable)\n", g_arp_config.enable); blobmsg_add_u32(&b, "scan_running", g_arp_config.enable); if (req == NULL) { fprintf(stderr, "ubus_get_scan_status: req is NULL, this might be a test environment.\n"); return -1; } ubus_send_reply(ctx, req, b.head); return 0; } int ubus_get_scan_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { struct blob_buf b = { 0 }; blob_buf_init(&b, 0); pthread_mutex_lock(&arp_mutex); printf("host number:%d\n", g_arp_entry_count); printf("print ip and mac:\n"); if (0 == g_arp_entry_count) { printf("ip:None\tmac:None\n"); } int i; for (i = 0; i < g_arp_entry_count; ++i) { char ip_buf[INET_ADDRSTRLEN]; char mac_buf[18]; inet_ntop(AF_INET, &g_arp_entries[i].ip_addr, ip_buf, sizeof(ip_buf)); printf("ip address: %s\t", ip_buf); printf("mac address: %02x:%02x:%02x:%02x:%02x:%02x\n", g_arp_entries[i].mac_addr[0], g_arp_entries[i].mac_addr[1], g_arp_entries[i].mac_addr[2], g_arp_entries[i].mac_addr[3], g_arp_entries[i].mac_addr[4], g_arp_entries[i].mac_addr[5]); snprintf(mac_buf, sizeof(mac_buf), "%02x:%02x:%02x:%02x:%02x:%02x", g_arp_entries[i].mac_addr[0], g_arp_entries[i].mac_addr[1], g_arp_entries[i].mac_addr[2], g_arp_entries[i].mac_addr[3], g_arp_entries[i].mac_addr[4], g_arp_entries[i].mac_addr[5]); void *entry_table = blobmsg_open_table(&b, NULL); blobmsg_add_string(&b, "ip", ip_buf); blobmsg_add_string(&b, "mac", mac_buf); blobmsg_close_table(&b, entry_table); } pthread_mutex_unlock(&arp_mutex); if (req == NULL) { fprintf(stderr, "ubus_get_scan_result: req is NULL, this might be a test environment.\n"); return -1; } ubus_send_reply(ctx, req, b.head); return 0; } int ubus_clear_result(struct ubus_context *ctx, struct ubus_object *obj, struct ubus_request_data *req, const char *method, struct blob_attr *msg) { clear_arp_entries(); return 0; } static const struct ubus_method arp_methods[] = { UBUS_METHOD("set_arp_config", ubus_set_arp_config, arp_config_policy), UBUS_METHOD_NOARG("get_arp_config", ubus_get_arp_config), UBUS_METHOD_NOARG("start_scan", ubus_start_scan), UBUS_METHOD_NOARG("stop_scan", ubus_stop_scan), UBUS_METHOD_NOARG("get_scan_status", ubus_get_scan_status), UBUS_METHOD_NOARG("get_scan_result", ubus_get_scan_result), UBUS_METHOD_NOARG("clear_result", ubus_clear_result), }; static struct ubus_object_type arp_object_type = UBUS_OBJECT_TYPE("arp", arp_methods); struct ubus_object arp_object = { .name = "arp", .type = &arp_object_type, .methods = arp_methods, .n_methods = ARRAY_SIZE(arp_methods), }; static int arp_init() { /* 创建一个线程来处理ARP回复 */ pthread_t thread_id; pthread_create(&thread_id, NULL, arp_reply_thread, NULL); pthread_detach(thread_id); /* 初始化UBus */ uloop_init(); struct ubus_context *ctx = ubus_connect(NULL); if (!ctx) { fprintf(stderr, "Failed to connect to ubus\n"); return -1; } return 1; } struct ubus_context *ctx = NULL; static void arp_start() { /* 开始扫描 */ printf("\nStarting ARP scan...\n"); start_arp_scan(); printf("ARP scan started.\n"); } static void arp_stop() { /* 停止扫描 */ printf("\nStopping ARP scan...\n"); ubus_stop_scan(ctx, &arp_object, NULL, NULL, NULL); printf("ARP scan stopped.\n"); } static void arp_main() { DS_MOD_DESC arp_module = DS_STRUCT_MOD("arp", arp_init, NULL, NULL, arp_start, arp_stop, NULL, NULL); /* 将模块注册到ds_roor的链表上 */ MODULE *module_node = ds_register_module("arp", &arp_module); SDM_ASSERT(NULL != module_node); } NSD_INIT(arp_main); /* 注册到init_array,在init阶段对数据模型的参数进行初始化 */
08-26
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

等风来不如迎风去

你的鼓励是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值