软件设计中的可移植性的考虑

可移植性设计 1.      概述我们在讨论系统移植的时候,通常会提到一个概念:平台。平台可以是硬件平台,也可以是软件平台,软件平台通常指的就是操作系统。而按照应用领域的不同,我们又可以将软件平台细分为J2EE、.NET平台,如此等等。衡量系统的可移植性要从两个角度来看待,一个是垂直的,一个是水平的。所谓的垂直移植性,就是如何将一个应用程序从某个平台的一个版本移植到另外一个版本。如将一个应用程序从win 阅读详情

由于在下水平相当有限,不当之处还望大家不吝赐教。


参考Linux内核的思路,对应用程序的可移植性设计做出的思考。

Linux内核中,最前期的启动代码是特定体系结构的代码,还有中断、异常、系统调用的前期都会进入特定体系结构的框架代码,然后再转入体系结构无关的代码。

特定体系结构的代码,位于以体系结构名称命名的文件夹中。

那么对于应用程序的设计,如何借鉴呢?以GUI程序为例。

假如一个C语言写的应用程序,需要支持多种GUI环境(win32、QT、X window等)。那么这些不同的GUI环境中的应用程序,初始启动代码不同,然后运行起来以后各种交互事件的框架代码也不同。因此,可以考虑为不同的GUI环境建立一个以GUI环境名称命名的文件夹,将相关代码放进去。

如果应用比较简单,可以将环境无关的代码(纯业务逻辑,例如扫雷游戏的纯逻辑处理)放在名称为core的文件夹中。

环境相关代码,在调用环境无关的代码计算出结果后,更新GUI界面即可。Linux下用户通过系统调用获取当前时间的例子与此比较相似。


这样一来,构建出的应用程序,由GUI环境相关代码与环境无关代码两部分组成。


如果应用程序比较复杂,core里面还要调用一些外部接口,完成相应的操作,而这些操作如何实现又是与运行环境相关的。那怎么办呢?

内核中,也有类似的情况。例如,中断来了,先会有一些特定体系结构的框架代码被执行,然后进入中断处理的通用代码,然后最终找到相应的驱动程序的处理接口,调用驱动程序的接口。然而,驱动程序要做的事情,内核并不理解(不像扫雷游戏的逻辑处理,上层知道他做的是什么工作),同时驱动要做的事情如何实现还与环境有关。

此时,内核就对外提供一些接口,例如读写寄存器的接口等,从而让驱动无须关心环境相关问题,实现了驱动的可移植性。

那么,应用程序的设计中,同样可以借鉴这种做法。



开发可移植性软件常用方法   1. 读取config文件(控制软件行为)2. 模块配置文件(控制编译,便于配置软件模块)#define eRpTargetGeneric        0#define eRpTargetWin32          (eRpTargetGeneric + 1)#define eRpTargetUnix           (eRpTargetWin32 + 1)#define 阅读详情

相关推荐

C++设计开发规范(6):移植性设计规范

 6.    移植性设计规范本规范中只讨论C++应用程序在不同的操作系统(如Linux和Windos操作系统)平台之间的移植性。l 推荐不要加入移植性设计,如果需求/软件架构没有明确要支持可移植性。l 推荐尽量使用C标准库函数。√ 要求分离出不可移植的代码。       例如,n 汇编代码#ifdef SOMECODE __asm{…}n 文件分隔符WIND

麦田里的守望者 1276

19---可移植性与编程规范

什么是可移植性? 代码从一种体系结构移植到另外一种体系结构上的方便性 字和字长是什么? 字---能够由机器一次完成处理的数据 字长----机器的位数,如Intel i7是64位芯片,是指奔腾的字长是64位,也就是8字节 字长有什么作用? 规定了机器的字长,那么机器所对应的处理器通用寄存器、指针和long类型数据结构都应该与字长位数一样。既使物理地址空间比字长小,虚拟地址空间需要和字长一样...

weixin_42415578的博客 1414

C语言工程化

《C语言编程学习笔记》深入解析了C语言的跨平台特性与工程化实践。文章首先探讨了C语言"平台无关性"的本质,指出其通过标准语法和标准库实现跨平台编译,但数据类型、字节序等底层细节仍与平台相关,并给出了应对策略。随后系统阐述了C程序从三行基础代码到复杂系统的演进路径,重点讲解了模块化编程中的extern和static关键字使用技巧。在工程实践方面,文章详细介绍了分层架构设计、目录结构规范以及并发编程的挑战与解决方案。最后,作者总结了C语言的核心优势在于极简机制的灵活组合,并建议通过构建系统、

hqyj15121的博客 714

软件架构中的可移植和可扩展性:技术和最佳方法

作者:禅与计算机程序设计艺术 在现代软件系统开发中,软件架构一直是一项非常重要的环节。软件架构首先要解决的问题就是如何划分系统的功能模块、确定各个模块之间的联系、以及决定这些模块之间通信的方式和协议。好的软件架构设计可以让系统的不同部分以及不同时期的需求变化都能够被满足,达到高度的可维护性、可扩展性和可重用性。但是好的软件架构还需要考虑到

AI架构师小马 3007

9、硬件抽象层:概念、应用与实践

本文探讨了硬件抽象层(HAL)的概念、应用与实践,重点分析了 HAL API 在实现软件可移植性方面的重要作用。文章还介绍了现有的商业 HAL 解决方案,以及软件设计和验证的完整流程,包括高级应用程序模型、应用程序软件开发、软件栈组成和软件验证。此外,还讨论了如何在虚拟原型和事务精确的 SystemC 平台上执行和模拟 HAL,以确保在不同硬件架构上的软件复用和性能优化。

jupi8的博客 111

(第十二章)基于架构的软件设计

摘要: 软件设计方法对比与质量属性场景分析 设计方法对比: ABSD是架构级顶层设计框架,关注系统整体结构和质量属性 结构化设计面向过程,侧重功能模块划分 面向对象设计聚焦对象交互和职责分配 三者是"顶层框架+底层实现"的层级关系 质量属性场景标准: 采用6要素结构描述(刺激源/刺激/制品/环境/响应/度量) 可用性:故障恢复时间≤3秒 性能:并发≥5000 QPS 可修改性:修改影响≤1个模块 安全性:攻击拦截率100% 可测试性:用例覆盖率≥90% 可移植性:迁移时间≤1小时 应用建

echo的博客 78

软件设计基本要素

<br />1、软件的上下文<br />OS/DB平台、版本<br />周边子系统的版本<br />2、软件所遵循的约束<br />3、功能需求<br />4、软件设计的质量属性(非功能需求)<br />性能:关键操作的完成时间,一般界面操作的响应时间,管理对象容量<br />安全性:加密,鉴权<br />可用性(Availability):MTTF, MTTR, 高可用性,灾难恢复<br />易用性(Usability)<br />可测试性:依赖于外部环境的系统应该是可以实现独立测试的<br />可维护性

alvanchen的专栏 2158

S32K144 LPI2C Master/Slave模式配置与多设备通信实战

本文详细介绍了NXP S32K144微控制器中LPI2C模块的主从模式配置与多设备通信实战。内容涵盖硬件连接、引脚配置、主从模式深度设置、中断/DMA应用,并通过AT24C16 EEPROM、SHT30传感器等实例,解析了多设备通信中的地址切换、时序控制及常见问题排查技巧,帮助开发者高效实现基于LPI2C的稳定通信。

weixin_29158047的博客 269

软件设计与体系结构知识总结——第七章 Usability and Other Quality Attributes

软件设计与体系结构第七章——Usability and Other Quality Attributes

wubeizi的博客 1277

告别ROS1思维:在ROS2 Humble上,用Python搞定MoveIt2机械臂控制的完整流程

本文详细介绍了在ROS2 Humble环境下使用Python控制MoveIt2机械臂的完整流程。从环境配置、架构变革到实战操作,涵盖URDF适配、Action接口编程及性能优化技巧,帮助开发者高效迁移ROS1项目至ROS2平台,实现工业级机械臂控制。

weixin_30352645的博客 451

拆开华为BBU5900,看看5G基站的大脑里到底装了啥?

本文深度拆解华为BBU5900,揭示5G基站核心处理单元的硬件架构与设计哲学。通过详细解析模块化设计、智能电源系统和动态散热方案,展现其支撑千兆速率、毫秒级时延的技术奥秘,为5G网络部署提供实用参考。

weixin_31456563的博客 564

【架构设计】【程序指标】鲁棒性与健壮性的细节区别

本文转自:http://blog.youkuaiyun.com/bigpudding24/article/details/49069805 一、健壮性 健壮性是指软件对于规范要求以外的输入情况的处理能力。 所谓健壮的系统是指对于规范要求以外的输入能够判断出这个输入不符合规范要求,并能有合理的处理方式。 另外健壮性有时也和容错性,可移植性,正确性有交叉的地方。 比如,一

wffzxyl的博客 5177

Keil5编译报错:ARM Compiler Version 5缺失的完整解决方案

本文提供了Keil5编译报错“ARM Compiler Version 5缺失”的完整解决方案。详细介绍了手动安装ARM Compiler Version 5的步骤,包括下载安装包、配置编译器路径及常见问题排查,帮助开发者快速恢复老项目的编译环境。

bb456的博客 946

软件构建中的设计

1)关键的设计概念 软件的首要技术使命:管理复杂度。     在软件的架构层次上,可以通过把整个系统分解为多个系统来降低问题的复杂度。子系统间的相互依赖越少,你就越容易在同一时间里专注问题的一个小部分。精心设计的对象关系使关注相互分离,从而使你能在每个时刻只专注于一件事情。     保存子程序的短小精悍也能帮助你减少思考的负担。在最高抽象层次上工作,也能减少人的脑力劳动。 理想的设计设计特

wclin88的专栏 549

YOLOv13改进策略【YOLO和Mamba】| 替换骨干 Mamba-YOLOv13-T !!! 最新的发文热点

模块是模型中的一个重要组成部分,其主要作用是在模型的初始阶段对输入图像进行处理,方便后续的特征提取和目标检测。以下是对。

Limiiiing的博客 355

树根互联Java开发面试题及参考答案

说一下 Java 集合类。 Java 集合类是用于存储和操作一组对象的容器。它提供了多种数据结构,方便程序员对数据进行高效的管理和处理。 Java 集合框架主要包括两大接口:Collection 和 Map。 Collection 接口是一组对象的集合,它有三个主要的子接口:List、Set 和 Queue。 List 接口代表有序的集合,可以包含重复的元素。例如 ArrayList,它是基于数组实现的动态数组。它的优点是随机访问效率高,通过索引访问元素的时间复杂度为 O (1)。当

大模型大数据攻城狮的专栏 856

外观模式

在现实生活中,常常存在办事较复杂的例子,如办房产证或注册一家公司,有时要同多个部门联系,这时要是有一个综合部门能解决一切手续问题就好了。 软件设计也是这样,当一个系统的功能越来越强,子系统会越来越多,客户对系统的访问也变得越来越复杂。这时如果系统内部发生改变,客户端也要跟着改变,这违背了“开闭原则”,也违背了“迪米特法则”,所以有必要为多个子系统提供一个统一的接口,从而降低系统的耦合度,这就是外观...

Windsearcher的博客 177

2026华为OD机试真题 9月27日 新系统 【均衡调度】

华为OD机试真题 新系统 9月27号【均衡调度】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题 【均衡调度】多语言题解。

qq_45776114的博客 1770

微软团队:成功秘诀(3)

原文:http://www.blogjava.net/leeguannan/category/29681.html 设计   软件的设计─每一位团队成员都必须参与─这表示团队整体对功能需求的了解程度。    软件设计的第一要诀是:将全团队中最好的想法组织起来,去满足顾客内心最深处的需要。(带领团队做案例研讨,带领大家思考如何解决一切的疑难,让每一件事都在该做的时候做好。)法则十

Chopin's nocturnes 955

QML 果冻抖动:用 Scale 动画模拟 Q 弹反馈

介绍果冻抖动效果:点击后卡片通过多段 ParallelAnimation 实现 Scale X/Y 反向缩放和逐步衰减,模拟果冻弹性形变;进阶版本加入小幅 Rotation 增加活泼感,适合游戏、儿童应用等趣味反馈场景。

u011186532的专栏 426

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

外观模式/门面模式

<br />外观模式:有称为门面模式;<br />定义:把一系列复杂的类包装成一个简单封闭的高层接口;<br />生活中的实例:比如说我们去酒店吃饭,通过服务员进行点菜,点饮料,付款等;<br />                     去学校交学费,直接通过刷卡机刷卡就可以了;<br />jdk中实现:<br />http://stackoverflow.com/questions/1673841/examples-of-gof-design-patterns<br />http://yan578351

panpanhm91的专栏 602

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

程序设计模式(十) C++ 外观(Facade)模式

2.5 Facade <!-- --> 想想我们小时候玩的四驱车,里面的构造很复杂,马达,舵机,电池组等等,而我们控制它却非常简单,只要打开电池开关,他就可以跑。我们其实不 用知道它里面是如何工作,只要知道拨动开关它就可以工作就行了,这个开关其实就四驱车给我们的一个友好的组件,使得我们可以很方便的控制它。 外观模式其实定义了一个高层接口,该接口为子系统中的一组接口提供一个一致的界面,

llg070401046的博客 557

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

外观模式(门面模式)

外观模式(facade): 为子系统中的一组接口提供一个一致的界面,此模式定义了一个高层接口,这个接口使得这一子系统更加容易使用。 其实就是对内部诸多接口进行一个封装,提供一个简单的接口给外部调用。 比如说某个系统中,完成一件事要依次调用接口A,接口B,接口C等等,步骤非常繁杂。 那么可以定义一个新的接口,将这些步骤都封装到内部。 外部系统直接调这个新的接口就行了。 新增一个facade接口,可...

hello world 917

2021-05-26

软件设计

991

浅谈 "高内聚、低耦合" 这对兄弟

想必接触过软件的人,都有意或无意的听说过“高内聚,低耦合”这么一对名词了。从事软件开发的人员,在软件的设计工程中,尽量追求达到“高内聚、低耦合”。但是,究竟什么是“高内聚、低耦合”呢? 查看有关资料之后,本人对这对名词有了一定的理解。下面谈谈我的理解,与大家分享下,如有不当之处,也望有才之士指点! 首先将这对词分开解释吧! 内聚:针对的是一个体内部的子个体之间的联系(如图中左边圆圈内的小圆圈

ding2425的专栏 1026

设计模式之外观模式

外观模式外观模式为子系统中的各类(或结构与方法)提供一个简明一致的界面,隐藏子系统的复杂性,使子系统更加容易使用。

候鸟的专栏 3224
上一篇: 表目管理代码示例(迸发访问,多重索引查找,添加,删除,)
下一篇: Linux内核的启动流程
无忧老猪
博客等级 码龄18年 200粉丝 112原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值