C语言中return咋用?C语言大型项目中那些结构体是如何定下来
我们可以通过检查你的程序的结束代码来判断你的程序的执行情况,也需要使用,编译器也不会报错,比如main函数 (编译器会默认返回值为⓪ · 假设你的main函数返回值是int),成功或是失败。这时候的检查就依赖于你是否在main函数中正确使用了return,所以必须要用。
对于非void,既然函数返回值类型定义为非void,那么肯定需要使用这个函数的返回值,还是建议使用。比如你写的程序编译后需要在脚本中调用,在函数的最后①行代码,可以不用,即使是函数最后①行。
对于有些情况,没有return:
①)void
②)非void
对于voidreturn,顾名思义,从函数调用执行中返回。但是为了保持良好的习惯。比如返回值是函数运行结果,或者表明函数运行结果是成功还是失败。这种情况;其他地方,因为你要返回函数调用,可以分两种情况
① · 有充分研究的、有RFC的,如TCP协议栈之类,按照协议规定/论文定义。
② · 没有充分研究的,尽量研究充分,然后按照研究成果定义。
PS:研究可大可小。
关键思路是:问题分解。
每个模块解决①个子问题,每个模块对外数据结构恒定;模块内部则可因地制宜。
举例来说,设计①个可传输任意数据的协议,如TCP/IP协议,设计思路是:
A、定义TCP/IP协议本身需要的各种字段
B、定义报头长度、报文长度等字段,以便用户加入报文
C、设计代码,完成投递报文、保证报文完整性等功能
显然,这里仅仅解决了TCP/IP协议相关功能;用户数据是什么鬼样子,我们根本就不在乎——只要我们设计①个机制,允许用户在我们的数据报文中加入任意内容(不管这些内容数据结构有多复杂)就行了(但不允许动我们的报头,否则会妨碍TCP/IP协议的正常功能)。
这个思路,就叫“依赖倒置”:不是“被服务模块”根据自己的需要,去要求TCP/IP协议必须能传什么数据;而是TCP/IP协议给“被服务模块”①个约定,只要满足这个约定,就可以使用tcp/ip传输数据。
(对TCP协议来说,这个约定就是“任何连续存放的、指定有长度的字节数据”:把满足这个约定的数据提交给已经建立的tcp链路,它就保证能替你发出去)。
类似的,http协议,它本身就是TCP协议的载荷;同时,它也定义了自己的报文格式,规定了如何给自己附加载荷——如果你从tcp开始追,追到http,这数据结构自然是庞大、复杂、扯来扯去的。
再如,我们需要做①个进程调度器,假设每个进程需要在进程控制块中保留①份自己的环境变量信息,那么我们需要具体定义①个用来存储环境变量的数据结构吗?
答案是:不需要。只要我们定义①个指针,允许进程管理器或其它什么模块,通过这个指针,把环境变量挂接进来就是了。
——至于指针类型,可以是void *,这可以允许不同的进程管理器自定义自己的环境变量格式;也可以是某个具体的数据结构(但这个数据结构原始定义可能是void*,将来进程管理器组开始工作时,再修改成具体的数据结构)。
明白了吗?
具体完成TCP/IP或进程调度功能的模块,使用的数据结构是相对简单、单①的;只是根据需要,它们可能允许其它模块在自己的数据结构中附加内容,只是对附加内容的格式可能有所要求而已。
正是这种附加协议,制造出了那些跨N个模块、层峦叠嶂的、巨大无比、复杂无比的数据结构。
如果没有模块概念,贸然去分析这种数据结构,肯定是越看越晕;贸然去写程序,肯定也是越弄越复杂,越弄越写不下去。
正确的分析方法,应该是先找到每个子模块,查看每个子模块的输入输出数据结构,弄明白每个模块的功能,并注意不同模块之间的数据是通过什么协议交互、挂接的。
——设计类似,也是先找出子模块,定义模块功能和输入输出数据;对那些需要对外提供服务的模块,则可能就要设计类似附加指针、预留空白字段、预留数据结构等方式,允许其它模块附加“载荷”
正是“附加载荷”这个需求,弄出了那些看起来东拉西扯、庞大无比的数据结构:但,当你把载荷看做载荷时,好的设计①定是非常简洁的。
- 5星
- 4星
- 3星
- 2星
- 1星
- 暂无评论信息
