C/C++
文章平均质量分 61
smstong
创新来自于夯实的基础。
展开
-
对于C++拷贝构造函数的思考
【代码】对于C++拷贝构造函数的思考。原创 2022-09-15 22:13:10 · 536 阅读 · 0 评论 -
1987年C语言乱码大赛之最优秀单行代码
转自:http://blog.sina.com.cn/s/blog_6adee4450100m6o9.html看这行代码:printf(&unix["\021%six\012\0"], (unix)["have"] + "fun" - 0x60);看下面解释:首先看一段代码:代码:#includeint main(){ int a[5]={1,2,3,4,5}; prin转载 2016-02-04 19:24:40 · 7962 阅读 · 0 评论 -
C语言隐式函数声明带来的错误实例(当隐式声明遇到printf)
关于C语言隐式函数声明的基本问题,请参见我的博文万恶之源:C语言中的隐式函数声明。 下面是最近遇到的一个实例之一。 client_sock = accept(server_sock, (struct sockaddr*)&client_name, &client_name_len); printf("from %s:%d\n", inet_ntoa(client_nam原创 2016-03-01 14:55:52 · 10144 阅读 · 1 评论 -
纯C语言实现简单封装继承机制
0 继承是OO设计的基础继承是OO设计中的基本部分,也是实现多态的基础,C++,C#,Objective-C,Java,PHP,JavaScript等为OO而设计的语言,其语言本身对实现继承提供了直接支持。而遵循C/Unix设计哲学的语言,从不限定编程风格,而且提供了实现OO的基本支持。下面我们就来看看如何用C语言实现继承。1 内存布局层面上继承的含义如今几乎所有程序员都知道继承的抽象含义,对于被用原创 2016-02-21 12:09:53 · 11667 阅读 · 6 评论 -
C语言开发函数库时利用不透明指针对外隐藏结构体细节
1 模块化设计要求库接口隐藏实现细节作为一个函数库来说,尽力减少和其调用方的耦合,是最基本的设计标准。C语言,作为经典“程序=数据结构+算法”的践行者,在实现函数库的时候,必然存在大量的结构体定义,接口函数需要对这些结构体进行操作。同时,程序设计的模块化要求库接口尽量少的暴露其实现细节,接口参数尽量使用基本数据类型,尽量避免在形参中暴露库内结构体的定义。2 隐藏结构体的两种方法以笔者粗浅的认识,有两原创 2016-02-21 12:15:24 · 6303 阅读 · 2 评论 -
C/C++程序开发中实现信息隐藏的三种类型
无论是模块化设计,还是面向对象设计,还是分层设计,实现子系统内部信息的对外隐藏都是最关键的内在要求。以本人浅显的经验,把信息隐藏按照程度的不同分成(1)不可见不可用(2)可见不可用(3)可见可用。1 不可见不可用就是说模块内部的变量、结构体、类定义对外部而已完全隐藏,外部对此一无所知。常用的实现方法就是利用不透明指针,请参见我的博文C语言开发函数库时利用不透明指针对外隐藏结构体细节。这种方法同样适用原创 2016-02-21 12:52:29 · 6391 阅读 · 0 评论 -
C语言中利用setjmp和longjmp做异常处理
错误处理是任何语言都需要解决的问题,只有不能保证100%的正确运行,就需要有处理错误的机制。异常处理就是其中的一种错误处理方式。1 过程活动记录(Active Record)C语言中每当有一个函数调用时,就会在堆栈(Stack)上准备一个被称为AR的结构,抛开具体编译器实现细节的不同,这个AR基本结构如下所示。 每当遇到一次函数调用的语句,C编译器都会产生出汇编代码来在堆栈上分配这个AR。例如下面原创 2016-02-24 14:55:46 · 7898 阅读 · 0 评论 -
C/C++,Java,PHP,JavaScript,Json数组、对象赋值时,最后一个元素后面是否可以带逗号?
1 C,C++,Java,PHP都能容忍末尾的逗号C,C++,Java中对数组赋值时,最后一个元素末尾的逗号可有可无。下面两行代码对这些语言来说是等效的。int a[] = {1,2,3}; /* 正确 */int a[] = {1,2,3,}; /* 正确 */PHP这一点也继承了C的特点,下面的两行代码等效。$a = array(1,2,3); /* 正确 */$a = a原创 2016-03-22 09:49:27 · 4604 阅读 · 0 评论 -
C语言可变参函数的实现
1 C语言中函数调用的原理函数是大多数编程语言都实现的编程要素,调用函数的实现原理就是:执行跳转+参数传递。对于执行跳转,所有的CPU都直接提供跳转指令;对于参数传递,CPU会提供多种方式,最常见的方式就是利用栈来传递参数。C语言标准实现了函数调用,但是却没有限定实现细节,不同的C编译器厂商可以根据底层硬件环境自行确定实现方式。函数调用的一般实现原理,请参考我的博文 C语言中利用setjmp和lon原创 2016-02-26 19:11:56 · 10590 阅读 · 6 评论 -
纯C语言简单模拟C++的虚函数表
多态,面向接口编程等设计方法并没有绑定到任何特定的语言上,使用纯C也可以实现简单的多态概念。下面给出一个非常简单粗糙的例子,只为说明概念。父类Animal定义 文件:animal.h#ifndef ANIMAL_H#define ANIMAL_H/* 方法表, 类似于C++的虚函数表 */typedef struct vtable vtable;struct vtable{ v原创 2016-02-15 18:14:37 · 7890 阅读 · 3 评论 -
万恶之源:C语言中的隐式函数声明
1 什么是C语言的隐式函数声明在C语言中,函数在调用前不一定非要声明。如果没有声明,那么编译器会自动按照一种隐式声明的规则,为调用函数的C代码产生汇编代码。下面是一个例子:int main(int argc, char** argv){ double x = any_name_function(); return 0;}单纯的编译上述源代码,并没有任何报错,只是在链接阶段因为找原创 2016-01-15 14:49:33 · 41649 阅读 · 5 评论 -
VC++导出具有命名空间的函数
1 问题现象导出具有命名空间的函数和类。源代码如下:头文件MiniMFC.hnamespace MiniMFC{ __declspec(dllexport) void f(); class __declspec(dllexport) MyClass { public: void Mf(); };}实现文件MiniMFC.cpp#includ原创 2015-03-17 11:16:58 · 6804 阅读 · 0 评论 -
8年后战争又起:Linus Torvalds was (sorta) wrong about C++
语言之争永远是热门的话题,无论你是脱离了语言限制的老手,还是初入IT的新人。2007年的时候,Linus曾在一封邮件中大骂C++。原文链接From: Linus Torvalds <torvalds <at> linux-foundation.org>Subject: Re: [RFC] Convert builin-mailinfo.c to use The Better String Libr原创 2015-03-13 20:46:47 · 2612 阅读 · 2 评论 -
C++11中万能的可调用类型声明std::function<...>
在C++11中,callable object 包括传统C函数,C++成员函数,函数对象(实现了()运算符的类的实例),lambda表达式(特殊函数对象)共4种。程序设计,特别是程序库设计时,经常需要涉及到回调,如果针对每种不同的callable object单独进行声明类型,代码将会非常散乱,也不灵活。如下示例:#include <iostream>#include <functional>u原创 2015-04-09 15:32:14 · 21474 阅读 · 1 评论 -
C++、PHP、Javascript、...、对lambda表达式的支持
lambdalambda表达式,也叫Closure(闭包),也叫匿名函数。由于其强大之处,几乎被所有主流开发语言支持,本文试图列出大部分语言中lambda表达式的样例代码,后续持续更新。PHP对lambda的支持<?php$i = 12;$j = 33;$callable = function () use ($i, &$j){ echo $i . "\n"; echo $j原创 2015-04-09 18:30:49 · 4254 阅读 · 2 评论 -
对C++的一点抱怨
一段时间不写C++代码了,写起来感觉有些陌生了,特别是对于C++的模板实现更是心中没底,各种错误出现、效率底下让我不得不有些后悔当初项目采用了C++并且使用了STL。然而毕竟项目已经成型,完全推倒并用纯C重构在时间上和精力上已经不太可行。选择一种语言,就像是选择一个爱人,即使后来觉得不太称心,还是要坚持到最后。好在语言的选择只是在一个项目上,随着项目的结束而结束;而爱人是一辈子,应该更加慎重抉择:)原创 2015-10-10 15:49:30 · 1973 阅读 · 2 评论 -
如何区分 const char * p, char * const p, const char * * p?
C++之父Bjarne在他的《The C++ Programming Language》里面给出过一个助记的方法: 把一个声明从右向左读。 遇到 * 读成 pointer to。估计C编译器也是按照这个方法来解析的。char ** p1; // pointer to pointer to char const char **p2; // pointer to原创 2015-10-11 17:30:27 · 2120 阅读 · 0 评论 -
如何让软件绑定计算机硬件
软件绑定计算机硬件标识是不少软件采用的防拷贝方法。然而如何确定计算机硬件的唯一标识却不是简单的事情。下面是常采用的方法及其优缺点。1 计算机唯一性标识的方法1.1 CPU序列号可用性目前存在的CPU几乎都支持CPUID指令。这个指令不仅可以获取CPU生产厂商等基本信息,还可以获取其他有关CPU的硬件信息,包括CPU序列号。首先需要说明的是,CPU批号和CPU序列号是不同的东西,同样型号的CPU具有相原创 2015-11-15 12:35:01 · 22933 阅读 · 1 评论 -
C/C++语言中变量作用域:局部变量,全局变量,文件级变量
C/C++语言中的变量分为全局变量和局部变量。这种划分方式的依据是变量的可见范围或者叫做作用域。1 局部变量局部变量指的是定义在{}中的变量,其作用域也在这个范围内。虽然常见的局部变量都是定义在函数体内的,也完全可以人为的增加一对大括号来限定变量作用域。如下所示:void f(){ float x = 0; { int a; }}别小看这个作用域问题,这对原创 2016-01-14 15:03:49 · 13180 阅读 · 4 评论 -
C语言实现的数据结构之------哈希表
1 哈希表原理这里不讲高深理论,只说直观感受。哈希表的目的就是为了根据数据的部分内容(关键字),直接计算出存放完整数据的内存地址。试想一下,如果从链表中根据关键字查找一个元素,那么就需要遍历才能得到这个元素的内存地址,如果链表长度很大,查找就需要更多的时间.void* list_find_by_key(list,key){ for(p=list;p!=NULL; p=p->next){原创 2016-04-13 19:27:32 · 54830 阅读 · 16 评论 -
打算使用纯C开发一个数据结构及算法库,欢迎大家指正
1 项目由来使用了一段时间的C++强大的STL库,也看过一些STL源码剖析的书籍,可受能力所限,始终未能掌握。每次使用STL都是提心吊胆,虽然通过STL完成了一些项目,但总是心里没底,生怕编译器背后做了什么小动作。再加上STL属于编译器多态,虽然生成的代码运行效率很高,但是在跨编译器甚至统一编译器的不同版本时,往往不怎么顺利,一大堆外星人才能看懂的编译警告,让人不寒而栗。虽然本人最早接触的计算机编程原创 2016-04-27 19:38:34 · 9474 阅读 · 0 评论 -
TQ2440开发板学习纪实(0.0)--- GNU ARM交叉汇编环境的搭建与测试
对ARM进行裸机开发时,汇编是必不可少的,因为C语言无法直接操作CPU的内置寄存器,也就无法完成很多硬件初始化的功能,如内存控制器的初始化。市面上大多数讲解ARM汇编开发的书籍都把ADS作为开发环境,因此使用的汇编语言也就是ARMASM,开发平台也限制到了Windows。然而在嵌入式领域,Linux作为开发环境更加普及,那么如何在Linux下进行ARM的汇编程序设计呢?其实,Linux平台上早就有了原创 2016-12-13 07:03:25 · 1184 阅读 · 0 评论 -
TQ2440开发板学习纪实(0.1)--- GNU Freestanding(Naked)C ARM交叉开发环境创建与测试
0 由来在我的博文 GNU ARM交叉汇编环境的搭建与测试中,详细讲解了GNU ARM汇编环境的创建与使用方法。实际开发中,直接使用汇编语言写的代码往往很少,尽在系统启动和性能要求极其苛刻的时候才会用到汇编代码。在可读性、可移植性、逻辑表达能力方面,C语言的表现要比汇编强太多,正是C语言的这种优势造就了Unix世界,造就了Linux在多种平台上顺利编译运行的活泼场面。所以,在嵌入式开发领域,C语言是原创 2016-12-13 14:41:37 · 2809 阅读 · 0 评论 -
紧急求助!ARM-GCC对于函数指针调用的编译有错误?【已经找到原因】
函数指针是实现回调函数的基础,回调函数是C程序架构的基础。所以函数指针的重要性不言而喻。然而最近在ARM开发板上测试程序时,发现函数指针虽然能编译通过,但是运行时确总是报错。如下是一个最简单的测试程序源码。static void test(){ puts("test\n");}static void(*f)() = test;void Main(void){ led_init原创 2016-12-27 17:17:28 · 1981 阅读 · 0 评论 -
TQ2440开发板学习纪实(8)--- 从NAND Flash读取数据,把代码搬运到SDRAM运行
因为依赖于S3C2440的开机自动从Nandflash复制数据到片内SRAM执行,目前我们的可执行程序体积仍然不能大于4KB的限制。而我们的程序目前已经非常接近这个限制大小了,为了能够继续开发,必须突破这个限制。为此需要实现代码搬运功能,把程序从Nandflash搬运到SDRAM中去,并跳转到SDRAM执行。本文为啥不实现NandFlash写? 因为对于我们的实现目前尚未需求。更重要的是,写操作涉及原创 2016-12-30 16:39:15 · 2711 阅读 · 0 评论 -
TQ2440开发板学习纪实(2)--- 设置堆栈并调用C函数
本文根据上一篇TQ2440开发板学习纪实(1)—最简单的独立运行汇编程序进化而来。0 ARM堆栈(Stack)基础知识ARM支持满减类型的堆栈,满的意思是说堆栈指针SP(即R13)总是指向刚刚入栈的数据单元。与满相对应的就是不满,这种类型的栈指针SP指向栈顶的下一个空白单元。减的意思是说,栈底的内存地址大,栈顶地址小,压入数据时,栈向地址小的方向扩展。目前我们只有4KB的内存可用,范围为:0x000原创 2016-12-20 18:39:46 · 1105 阅读 · 0 评论 -
一个C语言运算符优先级导致的问题
检测某个数的某个二进制位是否为0,是常见的控制逻辑,如下代码所示:if (x & (1<<2) == 0) { printf("x的第2个二进制位为0\n");}然而实际上,上述代码永远不会执行printf,也就是说 x & (1<<2) == 0这个表达式始终为0。原因在于在C语言里,==运算符的优先级高于&,导致上面的表达式相当于:if ( x & ((1<<2) == 0) )因为1原创 2016-12-21 09:24:23 · 1326 阅读 · 0 评论 -
C语言中通过全局变量引用汇编语言中的全局标签
汇编语言和C语言混合编程中,在C语言中通过全局变量来引用汇编中的数据定义非常普遍,然而却存在同名不同义的陷阱。1 测试代码在汇编语言中的定义整数变量studentID,并赋初值,如下: .global studentID .datastudentID: .word 12345678 .text ldr r0, =studentID /* studentID被当原创 2017-01-13 09:43:44 · 5578 阅读 · 1 评论 -
TQ2440开发板学习纪实(10)--- 实现多任务处理,最简单OS模型
Keywords: Mutitasking,Context Switch,Thread0 多任务(多线程,多进程)基本概念0.1 CPU与多任务对于“多任务(Multitasking)”,不同的应用领域有不同术语。在操作系统领域,一般称为“多任务”;在应用程序设计领域,一般称为“多线程”;而在Unix领域,更多的人喜欢用“多进程”来表示相同的意思。本文着眼于OS层,所以使用“多任务原创 2017-01-13 11:16:53 · 1618 阅读 · 0 评论 -
TQ2440开发板学习纪实(9)--- 利用Undefined异常模拟BLX指令
在博文 《紧急求助!ARM-GCC对于函数指针调用的编译有错误?》中,我提到了GCC在编译函数指针调用的时候,会生成绝对地址跳转指令BLX。而S3C2440A这款CPU不支持BLX指令,从而导致陷入Undefined异常。本文就利用这个Undefined异常,来模拟BLX指令,从而让使用BLX指令的程序可以正常运行在S3C2440上。1 Undefined异常的处理流程ARM9在执行未定义指令时,会原创 2017-01-03 14:51:33 · 1282 阅读 · 1 评论 -
TQ2440开发板学习纪实(4)--- 初始化片外RAM,让程序有更大内存空间
到目前为止,我们的程序只能使用S3C2440的片内4KB的RAM。这么小的内存空间,显然不能应付实际的应用。是时候使用片外的RAM了,本文将详细介绍片外RAM的初始化过程。0 ROM,RAM,SRAM,DRAM,SDRAM傻傻分不清作为软件出身的软男,很难从根本上弄清楚ROM,RAM,SDRAM,SRAM等等的原理,这里我们只要了解基本的特性就可以了。ROM,NorFlash: 只读内存,掉电不丢原创 2016-12-22 15:10:49 · 2156 阅读 · 1 评论 -
C与C++函数声明时的几个小的语法差异
1 无参函数的声明void f(){}int main(void){ f(10,“hello"); return 0;}上述代码在C语言中是完全正确的。但是在C++中确是错误的。void f() * 在C中表示函数f可以接受任何类型,任意数量的参数。(然而并没有提供如何利用这些参数的机制,如果想使用可变参数函数,格式为 void f(type a1,…))。 * 而在C+原创 2016-06-08 17:35:51 · 3519 阅读 · 0 评论 -
(void)printf("hello world"); int a=2; void(a);中的(void)有什么用?
1 函数调用时前面加(void)#include <stdio.h>int main(void){ (void)printf("hello"); return 0;}函数调用时,前面加个(void)到底是做什么用的?其实对于程序的编译运行没有任何影响,目的很简单就是让源代码顺利通过一些严格的检查工具的检查如lint。如果返回值不被处理,有些检查工具就会报警告,为了消除这种无所谓原创 2016-06-08 17:46:01 · 5640 阅读 · 1 评论 -
标准C函数库和POSIX函数库的关系
The C POSIX library is a specification of a C standard library for POSIX systems. It was developed at the same time as the ANSI C standard. Some effort was made to make POSIX compatible with standard C原创 2016-06-08 18:07:16 · 12245 阅读 · 1 评论 -
没有前九条的第十条编程规则:Greenspun's tenth rule
1993年Philip Greenspun提出了编程第十条规则:Any sufficiently complicated C or Fortran program contains an ad hoc, informally-specified, bug-ridden, slow implementation of half of Common Lisp.有意思的是,虽然名为“第十条”,但是并不存在原创 2016-06-15 15:01:36 · 4719 阅读 · 0 评论 -
最详尽解释Linux内核源码中的container_of宏及其标准C版本实现
在Linux内核源码文件 include/linux/kernel.h中,定义了container_of宏,源码如下:/** * container_of - cast a member of a structure out to the containing structure * @ptr: the pointer to the member. * @type:原创 2016-10-22 10:58:22 · 3024 阅读 · 0 评论 -
GCC和C99中结构体的标签式初始化语法差异
GCC很早就支持标签式初始化结构体,标准C则是C99之后才对此进行了支持。两者语法不同,效果相同。例子:struct Student { char *name; int age; float score; double money;};传统GCC初始化代码:struct Student s1 = { age: 18, money: 100.23,}原创 2016-10-15 14:42:49 · 2765 阅读 · 0 评论 -
Freestanding C与交叉编译器的生成原理分析
0 问题由来以前也用过C51写过简单的裸机程序,但是并没有认真的考虑过其与Linux环境下一般C语言程序的不同,只是想当然地认为C是跨平台的语言,并没有考虑过C语言的标准问题。今天在编译GCC交叉编译器时,遇到了种种问题,不得不重新考虑C语言的实现标准,否则很难清晰的了解交叉编译器的编译过程。1 C编译器的两种实现要求C语言标准的正式文档中明确提出了C编译器的两种实现标准:1.1 conformin原创 2016-12-12 10:00:27 · 5369 阅读 · 0 评论 -
TQ2440开发板学习纪实(3)--- 设置时钟频率,让CPU运行的更快
0 原理0.1 时钟源自哪里所谓的时钟,就是电压高低的变化,只有不断的0,1交替变化,CPU才能被驱动运行。S3C2440支持多种时钟源,这通过CPU针脚OM3和OM3来选择。对于QT2440板子来说,OM3和OM2均直接接地,这就意味着时钟源来自针脚XTIpll和XTOpll,这两个针脚在TQ2440的核心板上被连接上了一个12MHz的晶振。0.2 S3C2440的时钟原理与设置CPU、RAM、U原创 2016-12-21 14:03:36 · 6841 阅读 · 1 评论 -
通过静态局部变量看C,C++,C#,Java,PHP的特点
通过静态局部变量看C,C++,C#,Java,PHP的特点。原创 2015-02-10 19:58:09 · 2049 阅读 · 0 评论