‘壹’ c/c++多线程编程中,为什么基本类型不用加锁
先 你描述的不对 严格来说是在对应的cpu体系下遵循了正确的内存对齐的方式的数据才有不需要加锁的可能
加锁主要是防止partial read/.1;write 请参考《intel开发者手册》第三卷8;write以及cpu乱序带来的cpu操作可见性问题
举x86-64的例子来说 一个基本类型如果地址无cache splite(落在两个cacheline中) 都可以保证无partial read/.1
‘贰’ C语言编程技术的优势和劣势
随着互联网编程技术的不断发展,现在大多数的软件开发都是通过编程语言来实现的,今天我们就一起来了解一下C语言编程开发技术都有哪些优势和劣势。
C语言的一些好的体验
一次通过阅读POV-Ray源代码学会如何在C语言中实现面向对象编程。
通过阅读GTK+源代码了解C语言代码的清晰、干净和可维护性。
通过阅读SIOD和Guile的源代码,知道如何使用C语言实现Scheme解析器。
使用C语言写出GNOMEEye的初始版本,并对MicroTile渲染进行调优。
C语言的一些不好的体验
在Evolution团队时,很多东西老是崩溃。那个时候还没有Valgrind,为了得到Purify这个软件,需要购买一台Solaris机器。
调试gnome-vfs线程死锁问题。
调试Mesa,却无果。
接手Nautilus-share的初始版本,却发现代码里面居然没有使用free()。
想要重构代码,却不知道该如何管理好内存。
想要打包代码,却发现到处是全局变量,而且没有静态函数。
但不管怎样,还是来说说那些Rust里有但C语言里没有的东西吧。
自动资源管理
Rust从C++那里借鉴了一些想法,如RAII(,资源获取即初始化)和智能指针,并加入了值的单一所有权原则,还提供了自动化的决策性资源管理机制。
自动化:不需要手动调用free()。内存使用完后会自动释放,文件使用完后会自动关闭,互斥锁在作用域之外会自动释放。如果要封装外部资源,基本上只要实现Drop这个trait就可以了。封装过的资源就像是编程语言的一部分,因为你不需要去管理它的生命周期。
决策性:资源被创建(内存分配、初始化、打开文件等),然后在作用域之外被销毁。根本不存在垃圾收集这回事:代码执行完就都结束了。程序数据的生命周期看起来就像是函数调用树。
如果在写代码时老是忘记调用这些方法(free/close/destroy),或者发现以前写的代码已经忘记调用,甚至错误地调用,那么以后我再也不想使用这些方法了。
泛型
Vec真的就是元素T的vector,而不只是对象指针的数组。在经过编译之后,它只能用来存放类型T的对象。
在C语言里需要些很多代码才能实现类似的功能,所以我不想再这么干了。
trait不只是interface
Rust并不是一门类似那样的面向对象编程语言,它有trait,看起来就像是里的interface——可以用来实现动态绑定。如果一个对象实现了Drawable,那么就可以肯定该对象带有draw()方法。
不过不管怎样,trait的威力可不止这些。
依赖管理
以前实现依赖管理需要:
手动调用或通过自动化工具宏来调用g-config。
指定头文件和库文件路径。
基本上需要人为确保安装了正确版本的库文件。
而在Rust里,只需要编写一个Cargo.toml文件,然后在文件里指明依赖库的版本。这些依赖库会被自动下载下来,或者从某个指定的地方获取。
测试
C语言的单元测试非常困难,原因如下:
内部函数通常都是静态的。也就是说,它们无法被外部文件调用。测试程序需要使用#include指令把源文件包含进来,或者使用#ifdefs在测试过程中移除这些静态函数。
需要编写Makefile文件将测试程序链接到其中的部分依赖库或部分代码。
需要使用测试框架,并把测试用例注册到框架上,还要学会如何使用这些框架。
卫生宏(HygienicMacro)
Rust的卫生宏避免了C语言宏可能存在的问题,比如宏中的一些东西会掩盖掉代码里的标识符。Rust并不要求宏中所有的符号都必须使用括号,比如max(5+3,4)。
没有自动转型
在C语言里,昆明北大青鸟http://www.kmbdqn.cn/发现很多bug都是因为在无意中将int转成short或char而导致,而在Rust里就不会出现这种情况,因为它要求显示转型。
不会出现整型溢出
这个就不用再多作解释了。
‘叁’ c/c++多线程编程中,为什么基本类型不用加锁
首先 你描述的不对 严格来说是在对应的cpu体系下遵循了正确的内存对齐的方式的数据才有不需要加锁的可能
加锁主要是防止partial read/write以及cpu乱序带来的cpu操作可见性问题
举x86-64的例子来说 一个基本类型如果地址无cache splite(落在两个cacheline中) 都可以保证无partial read/write 请参考《intel 开发者手册》第三卷8.1.1.1章
另外一个功能就是杜绝cpu乱序引起的可见性问题了 仅局限于x86-64来说 如果你操控的这个基本类型对于storeload乱序不敏感 做到良好对齐就足够了 当然cpu乱序又是一个更深入的问题了 手机上说不清 一般来说 lock 都带有 mb-aquire的语意 unlock都带有mb-release的语意 因此加锁可以解决乱序问题
另外 题主怀疑多个缓存数据会不一致 这一点是不会发生的 这一点不是由操作系统保证的 而是每种cpu硬件都会遵守类似于mesi的缓存一致性协议 缓存的数据更改会在fsb上传递给各个其他cpu 这种复杂的一致性方式带来了性能问题 于是又引入了storebuffer和invalidate queue等机制来优化 从而导致cpu乱序的发生 又引入了各种memory barrior指令在必要时防止乱序的发生 在应用层这些被封装在各种锁里
上面所说局限于smp结构
‘肆’ 昆明北大青鸟分享C语言编程技术的优势和劣势
随着互联网编程技术的不断发展,现在大多数的软件开发都是通过编程语言来实现的,今天我们就一起来了解一下C语言编程开发技术都有哪些优势和劣势。
C语言的一些好的体验
一次通过阅读POV-Ray源代码学会如何在C语言中实现面向对象编程。
通过阅读GTK+源代码了解C语言代码的清晰、干净和可维护性。
通过阅读SIOD和Guile的源代码,知道如何使用C语言实现Scheme解析器。
使用C语言写出GNOME Eye的初始版本,并对MicroTile渲染进行调优。
C语言的一些不好的体验
在Evolution团队时,很多东西老是崩溃。那个时候还没有Valgrind,为了得到Purify这个软件,需要购买一台Solaris机器。
调试gnome-vfs线程死锁问题。
调试Mesa,却无果。
接手Nautilus-share的初始版本,却发现代码里面居然没有使用free()。
想要重构代码,却不知道该如何管理好内存。
想要打包代码,却发现到处是全局变量,而且没有静态函数。
但不管怎样,还是来说说那些Rust里有但C语言里没有的东西吧。
自动资源管理
Rust从C++那里借鉴了一些想法,如RAII(Resource Acquisition Is Initialization,资源获取即初始化)和智能指针,并加入了值的单一所有权原则,还提供了自动化的决策性资源管理机制。
自动化:不需要手动调用free()。内存使用完后会自动释放,文件使用完后会自动关闭,互斥锁在作用域之外会自动释放。如果要封装外部资源,基本上只要实现Drop这个trait就可以了。封装过的资源就像是编程语言的一部分,因为你不需要去管理它的生命周期。
决策性:资源被创建(内存分配、初始化、打开文件等),然后在作用域之外被销毁。根本不存在垃圾收集这回事:代码执行完就都结束了。程序数据的生命周期看起来就像是函数调用树。
如果在写代码时老是忘记调用这些方法(free/close/destroy),或者发现以前写的代码已经忘记调用,甚至错误地调用,那么以后我再也不想使用这些方法了。
泛型
Vec真的就是元素T的vector,而不只是对象指针的数组。在经过编译之后,它只能用来存放类型T的对象。
在C语言里需要些很多代码才能实现类似的功能,所以我不想再这么干了。
trait不只是interface
Rust并不是一门类似那样的面向对象编程语言,它有trait,看起来就像是里的interface——可以用来实现动态绑定。如果一个对象实现了Drawable,那么就可以肯定该对象带有draw()方法。
不过不管怎样,trait的威力可不止这些。
依赖管理
以前实现依赖管理需要:
手动调用或通过自动化工具宏来调用g-config。
指定头文件和库文件路径。
基本上需要人为确保安装了正确版本的库文件。
而在Rust里,只需要编写一个Cargo.toml文件,然后在文件里指明依赖库的版本。这些依赖库会被自动下载下来,或者从某个指定的地方获取。
测试
C语言的单元测试非常困难,原因如下:
内部函数通常都是静态的。也就是说,它们无法被外部文件调用。测试程序需要使用#include指令把源文件包含进来,或者使用#ifdefs在测试过程中移除这些静态函数。
需要编写Makefile文件将测试程序链接到其中的部分依赖库或部分代码。
需要使用测试框架,并把测试用例注册到框架上,还要学会如何使用这些框架。
卫生宏(Hygienic Macro)
Rust的卫生宏避免了C语言宏可能存在的问题,比如宏中的一些东西会掩盖掉代码里的标识符。Rust并不要求宏中所有的符号都必须使用括号,比如max(5 + 3, 4)。
没有自动转型
在C语言里,昆明北大青鸟http://www.kmbdqn.com/发现很多bug都是因为在无意中将int转成short或char而导致,而在Rust里就不会出现这种情况,因为它要求显示转型。
不会出现整型溢出
这个就不用再多作解释了。
‘伍’ 武汉北大青鸟分享C语言编程技术的优势和劣势
随着互联网编程技术的不断发展,现在大多数的软件开发都是通过编程语言来实现的,今天我们就一起来了解一下C语言编程开发技术都有哪些优势和劣势。
C语言的一些好的体验一次通过阅读POV-Ray源代码学会如何在C语言中实现面向对象编程。
通过阅读GTK+源代码了解C语言代码的清晰、干净和可维护性。
通过阅读SIOD和Guile的源代码,知道如何使用C语言实现Scheme解析器。
使用C语言写出GNOMEEye的初始版本,并对MicroTile渲染进行调优。
C语言的一些不好的体验在Evolution团队时,很多东西老是崩溃。
那个时候还没有Valgrind,为了得到Purify这个软件,需要购买一台Solaris机器。
调试gnome-vfs线程死锁问题。
调试Mesa,却无果。
接手Nautilus-share的初始版本,却发现代码里面居然没有使用free()。
想要重构代码,却不知道该如何管理好内存。
想要打包代码,却发现到处是全局变量,而且没有静态函数。
但不管怎样,还是来说说那些Rust里有但C语言里没有的东西吧。
自动资源管理Rust从C++那里借鉴了一些想法,如RAII(,资源获取即初始化)和智能指针,并加入了值的单一所有权原则,还提供了自动化的决策性资源管理机制。
自动化:不需要手动调用free()。
内存使用完后会自动释放,文件使用完后会自动关闭,互斥锁在作用域之外会自动释放。
如果要封装外部资源,基本上只要实现Drop这个trait就可以了。
封装过的资源就像是编程语言的一部分,因为你不需要去管理它的生命周期。
决策性:资源被创建(内存分配、初始化、打开文件等),然后在作用域之外被销毁。
根本不存在垃圾收集这回事:代码执行完就都结束了。
程序数据的生命周期看起来就像是函数调用树。
如果在写代码时老是忘记调用这些方法(free/close/destroy),或者发现以前写的代码已经忘记调用,甚至错误地调用,那么以后我再也不想使用这些方法了。
泛型Vec真的就是元素T的vector,而不只是对象指针的数组。
在经过编译之后,它只能用来存放类型T的对象。
在C语言里需要些很多代码才能实现类似的功能,所以我不想再这么干了。
trait不只是interfaceRust并不是一门类似那样的面向对象编程语言,它有trait,看起来就像是里的interface——可以用来实现动态绑定。
如果一个对象实现了Drawable,那么就可以肯定该对象带有draw()方法。
不过不管怎样,trait的威力可不止这些。
依赖管理以前实现依赖管理需要:手动调用或通过自动化工具宏来调用g-config。
指定头文件和库文件路径。
基本上需要人为确保安装了正确版本的库文件。
而在Rust里,只需要编写一个Cargo.toml文件,然后在文件里指明依赖库的版本。
这些依赖库会被自动下载下来,或者从某个指定的地方获取。
测试C语言的单元测试非常困难,原因如下:内部函数通常都是静态的。
也就是说,它们无法被外部文件调用。
测试程序需要使用#include指令把源文件包含进来,或者使用#ifdefs在测试过程中移除这些静态函数。
需要编写Makefile文件将测试程序链接到其中的部分依赖库或部分代码。
需要使用测试框架,并把测试用例注册到框架上,还要学会如何使用这些框架。
卫生宏(HygienicMacro)Rust的卫生宏避免了C语言宏可能存在的问题,比如宏中的一些东西会掩盖掉代码里的标识符。
Rust并不要求宏中所有的符号都必须使用括号,比如max(5+3,4)。
没有自动转型在C语言里,武汉北大青鸟http://www.kmbdqn.cn/发现很多bug都是因为在无意中将int转成short或char而导致,而在Rust里就不会出现这种情况,因为它要求显示转型。
不会出现整型溢出这个就不用再多作解释了。
‘陆’ 西安北大青鸟分享C语言编程技术的优势和劣势
随着互联网编程技术的不断发展,现在大多数的软件开发都是通过编程语言来实现的,今天我们就一起来了解一下C语言编程开发技术都有哪些优势和劣势。
C语言的一些好的体验一次通过阅读POV-Ray源代码学会如何在C语言中实现面向对象编程。
通过阅读GTK+源代码了解C语言代码的清晰、干净和可维护性。
通过阅读SIOD和Guile的源代码,知道如何使用C语言实现Scheme解析器。
使用C语言写出GNOMEEye的初始版本,并对MicroTile渲染进行调优。
C语言的一些不好的体验在Evolution团队时,很多东西老是崩溃。
那个时候还没有Valgrind,为了得到Purify这个软件,需要购买一台Solaris机器。
调试gnome-vfs线程死锁问题。
调试Mesa,却无果。
接手Nautilus-share的初始版本,却发现代码里面居然没有使用free()。
想要重构代码,却不知道该如何管理好内存。
想要打包代码,却发现到处是全局变量,而且没有静态函数。
但不管怎样,还是来说说那些Rust里有但C语言里没有的东西吧。
自动资源管理Rust从C++那里借鉴了一些想法,如RAII(,资源获取即初始化)和智能指针,并加入了值的单一所有权原则,还提供了自动化的决策性资源管理机制。
自动化:不需要手动调用free()。
内存使用完后会自动释放,文件使用完后会自动关闭,互斥锁在作用域之外会自动释放。
如果要封装外部资源,基本上只要实现Drop这个trait就可以了。
封装过的资源就像是编程语言的一部分,因为你不需要去管理它的生命周期。
决策性:资源被创建(内存分配、初始化、打开文件等),然后在作用域之外被销毁。
根本不存在垃圾收集这回事:代码执行完就都结束了。
程序数据的生命周期看起来就像是函数调用树。
如果在写代码时老是忘记调用这些方法(free/close/destroy),或者发现以前写的代码已经忘记调用,甚至错误地调用,那么以后我再也不想使用这些方法了。
泛型Vec真的就是元素T的vector,而不只是对象指针的数组。
在经过编译之后,它只能用来存放类型T的对象。
在C语言里需要些很多代码才能实现类似的功能,所以我不想再这么干了。
trait不只是interfaceRust并不是一门类似那样的面向对象编程语言,它有trait,看起来就像是里的interface——可以用来实现动态绑定。
如果一个对象实现了Drawable,那么就可以肯定该对象带有draw()方法。
不过不管怎样,trait的威力可不止这些。
依赖管理以前实现依赖管理需要:手动调用或通过自动化工具宏来调用g-config。
指定头文件和库文件路径。
基本上需要人为确保安装了正确版本的库文件。
而在Rust里,只需要编写一个Cargo.toml文件,然后在文件里指明依赖库的版本。
这些依赖库会被自动下载下来,或者从某个指定的地方获取。
测试C语言的单元测试非常困难,原因如下:内部函数通常都是静态的。
也就是说,它们无法被外部文件调用。
测试程序需要使用#include指令把源文件包含进来,或者使用#ifdefs在测试过程中移除这些静态函数。
需要编写Makefile文件将测试程序链接到其中的部分依赖库或部分代码。
需要使用测试框架,并把测试用例注册到框架上,还要学会如何使用这些框架。
卫生宏(HygienicMacro)Rust的卫生宏避免了C语言宏可能存在的问题,比如宏中的一些东西会掩盖掉代码里的标识符。
Rust并不要求宏中所有的符号都必须使用括号,比如max(5+3,4)。
没有自动转型在C语言里,西安北大青鸟http://www.kmbdqn.cn/发现很多bug都是因为在无意中将int转成short或char而导致,而在Rust里就不会出现这种情况,因为它要求显示转型。
不会出现整型溢出这个就不用再多作解释了。
‘柒’ c语言的编程开发
GCC,GNU组织开发的开源免费的编译器
MinGW,Windows操作系统下的GCC
Clang,开源的BSD协议的基于LLVM的编译器
Visual C++ :: cl.exe,Microsoft VC++自带的编译器 CodeBlocks,开源免费的C/C++ IDE
CodeLite,开源、跨平台的C/C++集成开发环境
Orwell Dev-C++,可移植的C/C++IDE
C-Free
Light Table
Visual Stdio系列 起初,C语言没有官方标准。1978年由美国电话电报公司(AT&T)贝尔实验室正式发表了C语言。布莱恩·柯林汉(Brian Kernighan) 和 丹尼斯·里奇(Dennis Ritchie) 出版了一本书,名叫《The C Programming Language》。这本书被 C语言开发者们称为K&R,很多年来被当作 C语言的非正式的标准说明。人们称这个版本的 C语言为K&R C。
K&R C主要介绍了以下特色:
结构体(struct)类型
长整数(long int)类型
无符号整数(unsigned int)类型
把运算符=+和=-改为+=和-=。因为=+和=-会使得编译器不知道使用者要处理i = -10还是i =- 10,使得处理上产生混淆。
即使在后来ANSI C标准被提出的许多年后,K&R C仍然是许多编译器的最 准要求,许多老旧的编译器仍然运行K&R C的标准。 1970到80年代,C语言被广泛应用,从大型主机到小型微机,也衍生了C语言的很多不同版本。
1983年,美国国家标准协会(ANSI)成立了一个委员会X3J11,来制定 C语言标准。
1989年,美国国家标准协会(ANSI)通过了C语言标准,被称为ANSI X3.159-1989 Programming Language C。因为这个标准是1989年通过的,所以一般简称C89标准。有些人也简称ANSI C,因为这个标准是美国国家标准协会(ANSI)发布的。
1990年,国际标准化组织(ISO)和国际电工委员会(IEC)把C89标准定为C语言的国际标准,命名为ISO/IEC 9899:1990 - Programming languages -- C 。因为此标准是在1990年发布的,所以有些人把简称作C90标准。不过大多数人依然称之为C89标准,因为此标准与ANSI C89标准完全等同。
1994年,国际标准化组织(ISO)和国际电工委员会(IEC)发布了C89标准修订版,名叫ISO/IEC 9899:1990/Cor 1:1994 ,有些人简称为C94标准。
1995年,国际标准化组织(ISO)和国际电工委员会(IEC)再次发布了C89标准修订版,名叫ISO/IEC 9899:1990/Amd 1:1995 - C Integrity ,有些人简称为C95标准。 1999年1月,国际标准化组织(ISO)和国际电工委员会(IEC)发布了C语言的新标准,名叫ISO/IEC 9899:1999 - Programming languages -- C ,简称C99标准。这是C语言的第二个官方标准。
在C99中包括的特性有: 增加了对编译器的限制,比如源程序每行要求至少支持到 4095 字节,变量名函数名的要求支持到 63 字节(extern 要求支持到 31)。 增强了预处理功能。例如: 宏支持取可变参数 #define Macro(...) __VA_ARGS__ 使用宏的时候,允许省略参数,被省略的参数会被扩展成空串。 支持 // 开头的单行注释(这个特性实际上在C89的很多编译器上已经被支持了) 增加了新关键字 restrict, inline, _Complex, _Imaginary, _Bool 支持 long long, long double _Complex, float _Complex 等类型 支持不定长的数组,即数组长度可以在运行时决定,比如利用变量作为数组长度。声明时使用 int a[var] 的形式。不过考虑到效率和实现,不定长数组不能用在全局,或 struct 与 union 里。 变量声明不必放在语句块的开头,for 语句提倡写成 for(int i=0;i<100;++i) 的形式,即i 只在 for 语句块内部有效。 允许采用(type_name){xx,xx,xx} 类似于 C++ 的构造函数的形式构造匿名的结构体。 复合字面量:初始化结构的时候允许对特定的元素赋值,形式为:
struct test{int a[3],b;} foo[] = { [0].a = {1}, [1].a = 2 }; struct test{int a, b, c, d;} foo = { .a = 1, .c = 3, 4, .b = 5 }; // 3,4 是对 .c,.d 赋值的 格式化字符串中,利用 u 支持 unicode 的字符。 支持 16 进制的浮点数的描述。 printf scanf 的格式化串增加了对 long long int 类型的支持。 浮点数的内部数据描述支持了新标准,可以使用 #pragma 编译器指令指定。 除了已有的 __line__ __file__ 以外,增加了 __func__ 得到当前的函数名。 允许编译器化简非常数的表达式。 修改了 /% 处理负数时的定义,这样可以给出明确的结果,例如在C89中-22 / 7 = -3, -22% 7 = -1,也可以-22 / 7= -4, -22% 7 = 6。 而C99中明确为 -22 / 7 = -3, -22% 7 = -1,只有一种结果。 取消了函数返回类型默认为 int 的规定。 允许 struct 定义的最后一个数组不指定其长度,写做 [](flexible array member)。 const const int i 将被当作 const int i 处理。 增加和修改了一些标准头文件,比如定义 bool 的 <stdbool.h> ,定义一些标准长度的 int 的 <inttypes.h> ,定义复数的 <complex.h> ,定义宽字符的 <wctype.h> ,类似于泛型的数学函数 <tgmath.h>, 浮点数相关的 <fenv.h>。 在<stdarg.h> 增加了 va_ 用于复制 ... 的参数。里增加了 struct tmx ,对 struct tm 做了扩展。 输入输出对宽字符以及长整数等做了相应的支持。 GCC和其它一些商业编译器支持C99的大部分特性。 2011年12月8日,国际标准化组织(ISO)和国际电工委员会(IEC)再次发布了C语言的新标准,名叫ISO/IEC 9899:2011 - Information technology -- Programming languages -- C ,简称C11标准,原名C1X。这是C语言的第三个官方标准,也是C语言的最新标准。
新的标准提高了对C++的兼容性,并增加了一些新的特性。这些新特性包括: 对齐处理(Alignment)的标准化(包括_Alignas标志符,alignof运算符, aligned_alloc函数以及<stdalign.h>头文件。 _Noreturn 函数标记,类似于 gcc 的 __attribute__((noreturn))。 _Generic 关键字。 多线程(Multithreading)支持,包括: _Thread_local存储类型标识符,<threads.h>头文件,里面包含了线程的创建和管理函数。 _Atomic类型修饰符和<stdatomic.h>头文件。 增强的Unicode的支持。基于C Unicode技术报告ISO/IEC TR 19769:2004,增强了对Unicode的支持。包括为UTF-16/UTF-32编码增加了char16_t和char32_t数据类型,提供了包含unicode字符串转换函数的头文件<uchar.h>. 删除了 gets() 函数,使用一个新的更安全的函数gets_s()替代。 增加了边界检查函数接口,定义了新的安全的函数,例如 fopen_s(),strcat_s() 等等。 增加了更多浮点处理宏。 匿名结构体/联合体支持。这个在gcc早已存在,C11将其引入标准。 静态断言(static assertions),_Static_assert(),在解释 #if 和 #error 之后被处理。 新的 fopen() 模式,(“…x”)。类似 POSIX 中的 O_CREAT|O_EXCL,在文件锁中比较常用。 新增 quick_exit() 函数作为第三种终止程序的方式。当 exit()失败时可以做最少的清理工作。
‘捌’ 佳音北大青鸟分享C语言编程技术的优势和劣势
随着互联网编程技术的不断发展,现在大多数的软件开发都是通过编程语言来实现的,今天我们就一起来了解一下C语言编程开发技术都有哪些优势和劣势。
C语言的一些好的体验一次通过阅读POV-Ray源代码学会如何在C语言中实现面向对象编程。
通过阅读GTK+源代码了解C语言代码的清晰、干净和可维护性。
通过阅读SIOD和Guile的源代码,知道如何使用C语言实现Scheme解析器。
使用C语言写出GNOMEEye的初始版本,并对MicroTile渲染进行调优。
C语言的一些不好的体验在Evolution团队时,很多东西老是崩溃。
那个时候还没有Valgrind,为了得到Purify这个软件,需要购买一台Solaris机器。
调试gnome-vfs线程死锁问题。
调试Mesa,却无果。
接手Nautilus-share的初始版本,却发现代码里面居然没有使用free()。
想要重构代码,却不知道该如何管理好内存。
想要打包代码,却发现到处是全局变量,而且没有静态函数。
但不管怎样,还是来说说那些Rust里有但C语言里没有的东西吧。
自动资源管理Rust从C++那里借鉴了一些想法,如RAII(,资源获取即初始化)和智能指针,并加入了值的单一所有权原则,还提供了自动化的决策性资源管理机制。
自动化:不需要手动调用free()。
内存使用完后会自动释放,文件使用完后会自动关闭,互斥锁在作用域之外会自动释放。
如果要封装外部资源,基本上只要实现Drop这个trait就可以了。
封装过的资源就像是编程语言的一部分,因为你不需要去管理它的生命周期。
决策性:资源被创建(内存分配、初始化、打开文件等),然后在作用域之外被销毁。
根本不存在垃圾收集这回事:代码执行完就都结束了。
程序数据的生命周期看起来就像是函数调用树。
如果在写代码时老是忘记调用这些方法(free/close/destroy),或者发现以前写的代码已经忘记调用,甚至错误地调用,那么以后我再也不想使用这些方法了。
泛型Vec真的就是元素T的vector,而不只是对象指针的数组。
在经过编译之后,它只能用来存放类型T的对象。
在C语言里需要些很多代码才能实现类似的功能,所以我不想再这么干了。
trait不只是interfaceRust并不是一门类似那样的面向对象编程语言,它有trait,看起来就像是里的interface——可以用来实现动态绑定。
如果一个对象实现了Drawable,那么就可以肯定该对象带有draw()方法。
不过不管怎样,trait的威力可不止这些。
依赖管理以前实现依赖管理需要:手动调用或通过自动化工具宏来调用g-config。
指定头文件和库文件路径。
基本上需要人为确保安装了正确版本的库文件。
而在Rust里,只需要编写一个Cargo.toml文件,然后在文件里指明依赖库的版本。
这些依赖库会被自动下载下来,或者从某个指定的地方获取。
测试C语言的单元测试非常困难,原因如下:内部函数通常都是静态的。
也就是说,它们无法被外部文件调用。
测试程序需要使用#include指令把源文件包含进来,或者使用#ifdefs在测试过程中移除这些静态函数。
需要编写Makefile文件将测试程序链接到其中的部分依赖库或部分代码。
需要使用测试框架,并把测试用例注册到框架上,还要学会如何使用这些框架。
卫生宏(HygienicMacro)Rust的卫生宏避免了C语言宏可能存在的问题,比如宏中的一些东西会掩盖掉代码里的标识符。
Rust并不要求宏中所有的符号都必须使用括号,比如max(5+3,4)。
没有自动转型在C语言里,佳音北大青鸟http://www.kmbdqn.cn/发现很多bug都是因为在无意中将int转成short或char而导致,而在Rust里就不会出现这种情况,因为它要求显示转型。
不会出现整型溢出这个就不用再多作解释了。
‘玖’ 数字密码锁C语言编程
近年来,随着生活水平的不断改善,个人财富日益增长,人们对安全防盗的要求也逐渐提高。安全可靠、使用方便的电子密码锁成了人们防盗的首选。以Max +PlusⅡ(Multiple Array Matrix and ProgrammingLogic User SystemⅡ,多阵列矩阵及可编程逻辑用户系统Ⅱ)为工作平台,使用PLD可编程器件和VHDL语言设计的带音乐的电子密码锁具有密码预置,误码锁死及开锁音乐提示等功能。这种设计不仅简化了系统结构,降低了成本,更提高了系统的可靠和保密性。采用PLD可编程逻辑器件开发的数字系统,可以方便地升级和改进。
1 设计思路
密码锁电路由键盘控制、密码设置和音乐演奏三大功能模块组成,原理如图1所示。Count,Keyvalue,Contrl,Smdisplay构成键盘控制模块,Songer是音乐演奏模块,Set是密码设置模块。
1.1 键盘控制
键盘主要完成向系统输入数据,传送命令等功能。它是一个机械弹性按键开关的集合,利用机械触点的合、断作用产生高、低电平。通过对电平高低状态的检测,以确认按键按下与否。一个电压信号通过机械触点的断开、闭合过程的波形如图2所示。
在该键盘电路中,Count模块提供键盘的行扫描信号Q[3..0]。在没有按键按下时,信号EN为高电平,行扫描输出信号Q[3..0]的循环变化顺序为0001 OO100100 1000 0001(依次扫描4行按键);当有按键按下时,信号EN为低电平,行扫描输出信号Q[3..0]停止扫描,并锁存当前的行扫描值。例如按下第一行的按键,那么Q[3..O]=0001。
Keyvalue模块的主要功能是对输入按键的行信号Q[3..0]和列信号14[3..0]的当前组合值进行判断来确定输入按键的键值。
Contrl模块的主要功能是实现按键的消抖,判断是否有按键按下。确保对按键的提取处于图2所示的闭合稳定时间范围内,这就对本模块的输入时钟信号有一定的要求,在本设计中该模块输入的时钟信号频率为64 Hz。Smdisplay模块主要是完成数码管动态扫描和七段译码显示的功能。
1.2 音乐演奏电路Songer
根据声乐学知识,组成乐曲的每个音符的发音频率值及其持续的时间是乐曲能连续演奏所需的两个基本要素。获得这两个要素所对应的数值以及通过纯硬件的手段来利用这些数值实现所希望乐曲的演奏效果是关键。如图3所示,该电路需要由NOTETABS(音调发生器)、TONETABA、SPEAKER(数控分频器)三个模块组成,分别实现了声音产生、节拍控制、音调控制的功能。
1.3 密码设置
Set模块是实现密码锁功能的核心模块。其主要作用是设置密码,Set为设置密码的有效信号,可以实现修改密码的功能。En为输入密码确认信号,当输入完六位密码后确认输入,一旦输入的密码跟所设置的密码一致时,则输出信号OP有效(高电平);OP控制演奏音乐,此时音乐响起。若密码不正确,则指示输入错误及输入次数,输完三次无效后密码锁锁死,必须由RESET信号(启动信号,给一个低电平)重新打开密码锁功能。
2 电路的VHDL描述
键盘控制电路,音乐演奏电路以及密码设置模块均使用硬件描述语言VHSIC Hardware Description Lan-guage(VHDL)设计而成。例如:TONETABA的VHDL模型如下:
VHDL语言具有很强的电路描述和建模能力,能从多个层次对数字系统进行建模和描述,支持各种模式的设计方法:自顶向下与自底向上或混合方法,从而大大简化了硬件的设计任务,提高了设计效率和可靠性。它同时具有与具体硬件电路无关和与设计平台无关的特性,所以用VHDL进行电子系统设计,设计者可以专心致力于其功能的实现,而不需要对其他相关因素花费过多的时间和精力。
设计步骤
3.1 设计输入
首先在合适的路径下建立本设计的文件夹,然后用VHDL语言编辑Count,Keyvalue,Contrl,Smdisplay等电路,并在Max+PlusⅡ软件中使用文本编辑器输入上述各电路模块的VHDL程序,编译生成各模块;最后在Max+PlusⅡ软件中使用图形编辑器以自底向上的方法编辑原理图。先编辑图3电路,以Singer.gdf命名,其次使用“Create default Symbol”生成Songer模块,然后再编辑如图1所示原理电路图。
3.2 仿真测试及编程下载配置
将设计好的项目存盘,并将其设置成Project。选择目标器件为ACEX系列中的EP1K30QC208-2,启动编译,如果发现编译出现错误,修正后再次编译。编译后即可对波形文件进行仿真,并进行测试和波形分析。分析完成后进行编程下载配置。
3.3 硬件测试
在高电平时,通过键盘的0~F号键进行6位密码输入,密码输入完毕后通过单击确认键进行密码设置确认。当输入的密码与设置的密码一致时,扬声器开始循环演奏乐曲,且数码管SM8显示输入密码的次数,数码管SM7显示密码输入是否正确。如果密码正确,则SM7显示‘0’;如果密码错误,则SM7显示‘E’。数码管SM6~SM1显示输入的6位密码。在密码输入正确开始演奏乐曲时,如果将拨位开关KD4拨向上,则数码管SM8显示乐曲的音符,而此时若将拨位开关KD3拨向上则停止演奏乐曲。发光二极管LED1~LED4显示输入按键的键值,LED16监控是否有按键按下。
4 结 语
使用Max+PlusⅡ软件和VHDL语言设计电路,思路简单,功能明了;不仅可以进行逻辑仿真,还可以进行时序仿真;使用PLD器件不仅省去了电路制作的麻烦,还可以反复多次进行硬件实验,非常方便地修改设计,且设计的电路保密性很强。总之,采用Max+PlusⅡ软件和VHDL语言使得复杂的电子系统的设计变得简单容易,大大提高了设计效率。
如果对您有帮助,请记得采纳为满意答案,谢谢!祝您生活愉快!
‘拾’ 密码锁c语言编程代码
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
intmain()
{
charpassword[10],password2[10];
memset(password,0,sizeof(password));
memset(password2,0,sizeof(password2));
printf("请设置8位数以内密码: ");
scanf("%s",password);
printf("请设置校验密码: ");
scanf("%s",password2);
if(atoi(password2)==atoi(password))
{
printf("密码输入正确!: ");
}
else
{
printf("密码输入错误!: ");
}
return0;
}