C语言 | 陷阱:数组溢出导致内存被意外修改

C语言的指针在提供编程便利的同时,却带来了很多潜在的内存安全问题。见以下例子: 该程序(不正确)的输出为: 上述代码使用sprintf修改了string_buff指针所指向的char型数组。但是由于在申明数组长度的时候,没有考虑到字符串结束符’\0’,所以实际写入时不慎篡改了下一位内存地址的内容(此例中为i_not_zero, 使用MinGW gcc)。在实际程序中,此类b […]

C语言 | 陷阱:数组指针作为函数参数返回

再来看一个指针问题,同样的来自一个本科生的代码。这段代码想要实现将一个全是小写字母的字符串转换成对应的大写字母字符串: 然而这段代码没有能实现期望的功能。原因如下: 主程序调用convert_to_upper_case()函数后,堆栈为p分配了内存空间; 函数体正确修改了p对应字符数组的内容,并将p的首地址作为指针返回; 函数返回后,所有临时变量从堆栈中弹出,包括p[100]; 主程序得到返回的指 […]

C语言 | 指针的一个错误赋值

关于指针总是有说不完的故事。 最近给本科的学生带Embedded System课程设计,遇到了一个非常奇怪的bug。有一段代码需要实现I2C通信,核心代码已经由软件库提供了,学生只需要设置结构体后调用API即可。一个学生的代码是这样的: 初看一下没有什么问题:在I2C_init()函数中首先对结构体cfg进行初始化,而在I2C_send()函数中设置了需要发送的数据指针,之后使用I2C的API发送 […]

C语言 | C/C++变量命名规范

目前主流的C/C++命名风格有两种:一种是Windows风格的匈牙利命名法,主要是采用类型前缀 + 变量名首字母大写,另一个就是Unix/Linux命名习惯。我自己采用的是基于Unix的变种,融合了匈牙利命名法的一些优点,在这里分享给大家。 变量名的组成:(模块名) +  (作用域) + (类型前缀) + 变量名 + (变量名后缀),解释如下: 变量名 以小写的英文字母构成,词与词之间用下划线连接 […]

C语言 | C语言的函数指针

函数指针是C语言指针中的一个分支:函数指针是指向函数地址的指针。和一般的指针一样,函数指针可以大大增强编程时的灵活性。这篇博文根据我的理解,简单介绍了自己对于函数指针的理解。 一、函数名的本质 在介绍函数指针之前,我们先来理解一下究竟什么是函数。以下一段代码定义了名为fun1(),接受int并返回int参数的函数: 从一般的理解角度来看,fun1是函数的函数名。之所以要定义函数名,是因为在程序的其 […]

Processing | 用递归创造复杂图形

在Processing中想要创作复杂的图形元素,除了可以使用循环结构外,还可以使用递归 (recursion) 。递归是一种在函数执行时调用自身的一种特殊设计方法,递归可以解决很多循环结构无法解决的问题,同时在代码实现上也极为简洁。 为了可以更直观的了解什么是递归,这里先给出一个例子: 该代码生成的图形如下: 在上例中,drawCircle() 函数在返回前再次调用了drawCircle(),同时 […]

Processing | The Tree of Mind

九月底我的硕士课程就正式开始了,学业一直比较繁忙,没有精力进行新的研究。近日略有饶兴,抽空重新温习了一下Processing,下一步准备用Processing和Kinect完成一些交互艺术设计。 这个作品历时两天,用了800个粒子做随机运动动态生成。粒子的运动规律是由固定的方向矢量和柏林随机噪声叠加而成的。固定的方向矢量是为了能在自由运动的同时,保证运动的大体角度,从而从总体上呈现出绽放的效果;而 […]

关于编程语言的选择与体会

从我最早接触编程至今已有近10年时间,当时是在初中时,通过文曲星编写了几款基于文字和简单图形的游戏。高中时因没有相关条件与指导,慢慢就荒废了下来,中途曾经因为计算机考试学过一段时间VB,但就当时的知识能力,并没有学习的很深入。上大学以后,学校开设了C语言和VB的相关课程,加之之后对单片机和嵌入式系统的狂热,让我更加深入的接触了计算机编程的原则与方法。 我虽然不是计算机专业出生,但在学习、工作中还是 […]

C语言 | 陷阱:一个Break在if语句中的误用

C语言以高效著称,但其也存在很多晦涩的语法。让我们来看下面这段(真实的)代码: 以上代码的break意外跳出了case语句。之所以会产生这样的错误,是因为break在for和while中有类似的应用。我的这位朋友是在没有意识的情况下写出了上面这段代码。不仅如此,编译器(甚至高级的排错工具)对此也不会产生疑问,因为break在case语句之中是可以合法存在的。这里我用VS 2010测试了一下,如果该 […]

C语言 | 陷阱:一个优先级导致的BUG

虽然我在工作中已经非常注意优先级的问题,可还是不小心犯了一个优先级导致的错误: 这句话的本意是等待SR寄存器的某位变为1才继续往下执行,而实际上,因为”==”的优先级大于”&”,这句话等同于: 即 while (0); 所以每次执行到该句话时,不管当前SR寄存器的内容是什么,都会直接跳过while。为了防止出现优先级错误,正确的写法应该是: […]

C语言 | C语言运算符优先级

运算符优先级是C语言重要的组成部分,也是程序bug的常见产生源。需要特别注意的有: 赋值在C语言中的优先级是最低的; 位运算的优先级高于逻辑运算; 关系运算符的优先级低于移位,但是高于位运算; 单目运算的优先级最高; 同优先级的运算符按照从左向右的顺序解释。 Table 1. C语言运算符优先级 成员括号 ()   []   ->   . 单目运算  !   ~   ++   — […]

C语言 | 简易拼音输入法

Automatic.dai : 之前在Ourdev论坛上看到有人用C51设计了拼音输入法,代码还没有看,但是对于其实现原理很感兴趣,所以自己简单尝试了一下。 主要原理: 建立一张汉字索引表,主键为拼音,如”bao”,内容为汉字码表,如”包宝饱报抱保苞胞褒雹堡豹鲍暴爆剥薄瀑”。根据用户输入的拼音去查找对应的汉字码表,之后再根据用户输入的数字输出对应的汉字。这种方式很像LUA的table数据结构,用L […]

当printf()遇到多线程

一、本文背景 printf()这个函数我想大家再熟悉不过了,可是对于如何在多线程中使用printf(),各位可能就没怎么接触过了。本文以VC6.0为开发平台,旨在利用多线程完成一个最简单的任务:在屏幕上一直输出”Hello,world!”。 因为个人水平有限,本文涉及的内容非常肤浅,不过我还是尽量将原理讲清楚,希望对初学者略有帮助。为了提高大家的兴趣、降低理解难度,文章的结 […]

字节序:理解大端与小端

本文背景: 对于嵌入式工程师来说,不仅要熟悉各种数据类型,还需要熟谙各种数据在内存中的表达形式。软件高手们通过内存与指针微妙的配合,总能摩擦出惊艳的火花。在讨论数据的存储结构时,必然会涉及到大端模式(Big-Endian)和小端模式(Little-Endian)的问题。平时编程时对于这个概念并不会有太多接触,但是在通讯协议的处理、可移植性方面就必须要考虑到字节序的问题。以下就来讨论这个问题。 一、 […]

数据库 | SQLite BLOB的使用、出现乱码问题并解决

 (*)本文系本博客原创,如需转载请注明原作者! 原文作者:戴晓天,云飞实验室 联系方式:automatic.dai@gmail.com 原文来自:www.yfworld.com SQLite是轻量级数据库,但其功能齐全,当然也包括了对BLOB对象的操作功能。但今天在做SQLite的BLOB功能测试时,出现了读取出的数据与写入数据不一致的情况,这让我十分费解。 测试程序将一幅图片文件读入内存,写入 […]