
C/C++
文章平均质量分 68
winwonnn
这个作者很懒,什么都没留下…
展开
-
Hacker‘s Delight中的Trick
Hacker's Delight里的各种技巧真有意思。原创 2022-09-25 20:51:29 · 161 阅读 · 0 评论 -
C++仿函数真好用
仿函数(functor),就是使一个类的使用看上去像一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为。原创 2022-09-04 23:12:42 · 785 阅读 · 0 评论 -
[踩坑]整型提升
C was designed to implicitly and silently change the integer types of the operands used in expressions. ……These rules are often not even known by the average C programmer and therefore causing all manner of very subtle bugs.——stackoverflow/implicit-type.原创 2022-04-17 21:02:34 · 902 阅读 · 0 评论 -
static和inline在C++头文件中的使用
先上例子:// foo.hpp#ifndef FOO_HPP#define FOO_HPPvoid foo(){ //}#endif// a.cpp#include "foo.hpp"void func_a(){ foo();}// b.cpp#include "foo.hpp"void func_b(){ foo();}// main.cppextern void func_a();extern void func_b();int main原创 2021-12-23 23:32:16 · 1249 阅读 · 0 评论 -
C/C++中的全局变量与符号
0 引言起因是在头文件中定义了全局变量,而又有多个不同的源文件包含了这个头文件,这样显然会出现multiple definition的问题。以下是对上述问题的探索,文中若有不对的地方烦请指正。总的来说,一个变量是不能被多次定义的。以及,C和C++在关于multiple definition/redefinition的处理上会略有不同,原因在于tentative definition。1 Declaration & Definition既然谈论的是multiple definition的问题原创 2020-06-23 00:11:26 · 1281 阅读 · 0 评论 -
C语言函数传参与指针
C语言的函数传参只有传值的方式,想要在函数中修改参数值的话就需要传入参数的地址也就是指向这个参数的指针了。需要注意的情况是待修改的参数本身就是一个指针的时候,要传入这个指针本身的地址,也就是指向指针的指针。看这样的一个例子:当希望用init函数对传入的指针int型ptr分配空间,init接受的参数是int **arr,是一个指向指针的指针,而调用init函数时,需要传入的参数是&ptr,也就是ptr的地址。#include <stdio.h>#include <stdlib原创 2020-06-13 15:35:09 · 446 阅读 · 0 评论 -
C++与C的一些不同点
也是将C++改写为C时需要注意的一些地方。1.布尔类型C++中有原生的布尔类型bool,同时也有true和false关键字。然而C语言中直到C99才引入了布尔类型_Bool,同时还增加了一个头文件stdbool.h,其中定义了bool、true和false,以便与C++兼容。假如编译器不支持C99的话,可以这样来定义布尔类型:typedef enum { false, true } bool;2.结构体C++中可以在定义结构体的时候对结构体成员进行初始化,例如://cppstruct A_原创 2020-05-28 00:03:38 · 222 阅读 · 0 评论 -
C&C++中的const关键字
const关键字在C和C++中并非相同的含义。从字面含义上,const很容易让人认为它所限定的量是一个常量Constant,这样的理解在C++中是正确的,而在C语言中则是错误的。在C语言中,const的作用,更准确地说是将变量限定为read-only。Let’s look at what is meant when const is used. It’s really quite simpl...原创 2020-05-04 23:40:09 · 205 阅读 · 0 评论 -
case label does not reduce to an integer constant
一开始发现这个问题,是在switch中使用了const int类型的量作为case,举例如下:int main(void){ const int c[3] = {0, 1, 2}; int a = 0; switch (a) { case c[0]: a = c[1]; break; case c[1]: a = c[2]; break; c...原创 2020-05-02 18:19:34 · 21050 阅读 · 1 评论 -
使用memset初始化数组
写在前面的ATTENTION:用memset初始化非char型(eg. int型、float型…)数组时,假如初始化值非0,可能导致错误的结果。先举个通常用法的栗子, 将int型数组arr的元素初始化为0:int arr[5];memset(arr, 0, sizeof(int) * 5);假如初始值不为0,会如何呢?例如设置为1:使用memset(arr, 1, sizeof(int...原创 2020-04-05 17:00:00 · 3548 阅读 · 0 评论 -
BUG!符号数与无符号数混合运算
写了一段类似这样的代码: vector<int> vec; for (int i = 0; i < 3; i++) { vec.push_back(i); } int div; div = -3 / vec.size();想当然地认为div结果是1?大错特错,其实结果是0x55555554!问题出在哪里?注意vec.size(),是unsigned!所...原创 2020-03-10 00:40:56 · 166 阅读 · 0 评论 -
数据拼接与处理Tips
最近搞了几个传感器,各个的数据格式都不太一样,记录一下处理数据的tips。1 注意是否溢出遇到这样的情况:原始数据本身是8bit,然而需要加上offset才能得到真实数据,一疏忽用了uint8_t来存放数据,显然就会存在溢出的风险。2 使用struct比如原始数据是这样的:每个data是12bit,byte1是data1的高8位,byte2是data2的高8位,byte3[3:0]是da...原创 2020-03-01 17:20:21 · 467 阅读 · 0 评论 -
__no_init
__no_init 是给编译器linker使用,为禁止系统启动时初始化,是定义在不初始化的区域。可用于硬件复位或看门狗异常复位标记状态,但是在系统上电复位时为不定值。__no_init unsigned int ram_val1;__no_init unsigned int ram_val2 @0x20000400;int main(void){ printf("ram_val1:%d,...转载 2019-12-08 17:02:04 · 642 阅读 · 0 评论 -
vector的基本操作
今日工作感想:一顿操作猛如虎,结果还是最蠢的方法最好用。就当是复习了一下vector的用法吧。1.push_back()最基础的在末尾追加元素,不必多说。2.begin(),end(),rbegin(),rend()注意区间是左闭右开的,借用C++ Primer的图示如下:3.insert()在指定的位置之前插入元素,也可以用来拼接两个vector。vector<int>...原创 2020-04-05 23:36:52 · 373 阅读 · 0 评论 -
&和!=的优先级
写了个小bug,基础知识再复习。这样的一段程序:#include <stdio.h>#include <stdint.h>int main(){ _Bool flag1, flag2; flag1 = (0x54 & 0x10 != 0); flag2 = ((0x54 & 0x10) != 0); return 0;}结果是fl...原创 2019-11-13 23:52:46 · 5349 阅读 · 0 评论 -
使用malloc的注意事项
有时候在函数中使用malloc时,如果分配内存失败,可能会打算让函数直接返回,例如: char *T; T = malloc(4); if (T == NULL) return -1; else //...但是如果使用了多次malloc,就要注意在判断到某次分配失败而导致返回时,将已经分配了的空间释放掉。虽然通常在函数的结尾处不会忘记free,但是却很容易在这种中途返回时疏忽了...原创 2019-11-12 23:12:11 · 542 阅读 · 0 评论 -
static关键字
复习一下基础知识。1.用static修饰的局部变量,要分清它的生存期和作用域。在函数或者代码块中定义的变量,假如没有static的修饰,那么在函数或者代码块执行完毕后,变量就会被销毁。若是使用了static修饰,那么该变量直到程序结束才会被销毁。但是,无论是否采用了static修饰,变量的作用域都仍然是在这个函数或者代码块中。注意事项,参考C语言static 关键字总结:程序运行很重要...原创 2019-11-06 23:56:11 · 108 阅读 · 0 评论 -
函数调用与自增运算
最近写代码的时候本想着用点小trick,结果一不小心踩了个坑。一个例子:#include <stdio.h>int main(){ int id = 0; printf("%d,%d\n", id++, id++); printf("%d,%d\n", id++, id); printf("%d,%d\n", id, id++); printf("%d,%d\n"...原创 2019-09-01 22:37:13 · 477 阅读 · 0 评论 -
QZXing不适用于C++11语法?
重新整理写过的程序,发现了一个诡异的问题。将使用了QZXing的源程序包移动到另一个文件夹后,build,出现QZXing中的某个文件出现错误。一步步回溯问题可能出现的地方。发现这个程序最开始的版本中并没有需要C++11支持的语法(如lambda表达式),因此.pro文件中也没有CONFIG += c++11这一句,也许就是这里出了问题。删去.pro文件中的CONFIG += c++11,并且...原创 2019-02-22 22:17:11 · 306 阅读 · 0 评论 -
C++内部类和外部类的互相访问(d指针和q指针)
d指针和q指针式Qt中常见的封装方法,由此引出了C++内部类和外部类的互相访问。其实也是Pimpl(pointer to implementation, 指向实现的指针)方法。实验代码:Inner类为Outter类的私有内部类。Inner类中有一个public字符串变量In,Outter类中有一个private字符串变量Out。通过Outter类中的d指针访问Inner类,实现对In的读写;...原创 2019-02-21 13:06:44 · 3534 阅读 · 0 评论 -
C++中delete指针后将指针置0的作用
Qt学习之路2中访问网络的章节中有这样的代码:NetWorker::~NetWorker(){ delete d; d = 0;}其中d是一个指针。d = 0;的作用,参考百度知道:delete之后的指针指向一个不确定的位置,叫悬垂指针,如果后面不经意引用了,会导致程序崩溃。置0使其成为空指针,后面的程序可通过判断该指针是否为NULL来确定它是否有效。更加全面的解...原创 2019-02-21 00:02:52 · 1340 阅读 · 0 评论 -
case语句不要忘记break!
陷阱啊陷阱!一般必须在case语句结尾添加break语句。因为一旦通过switch语句确定了入口点,所有进一步的case都会被忽略,并且除非遇到关键字break,否则会执行满足这个case之后的其他case的语句,直到switch结束或者遇到break为止。如果在switch中省略了break语句,那么匹配的case值后的所有情况(包括default情况)都会被执行。...原创 2019-02-27 11:34:26 · 1146 阅读 · 0 评论 -
关于malloc和new的几个Tips
1.使用 malloc/calloc 等分配内存的函数时,一定要检查其返回值是否为NULL(亦即检查分配内存的操作是否成功),这是良好的编程习惯,也是编写可靠程序所必需的。例如DSAA in C中SearchTree Insert函数是是这么写的: T = malloc(sizeof(struct TreeNode)); if (T == NULL) FatalError("Out of...原创 2019-03-15 22:39:35 · 180 阅读 · 0 评论 -
派生类、基类和对象成员的构造/析构顺序
构造时:基类构造函数→对象成员构造函数→派生类本身的构造函数析构时:派生类本身的析构函数→对象成员析构函数→基类析构函数写个小程序验证一下:#include <iostream>using namespace std;class component{public: component() {cout << "construct component" <...原创 2019-03-20 16:11:20 · 5415 阅读 · 1 评论 -
C/C++之从源文件到可执行程序
学习了一下makefile的写法,跟我一起写 Makefile(一),顺便看看源文件是怎么变成可执行程序的。GCC干了些什么事情呢?在CSAPP的1.2节中讲得很清楚了:有四个阶段:预处理——编译——汇编——链接。于是在makefile中可以明显地看到最终的可执行目标程序依赖于一堆.o文件(可重定位目标程序),这一堆.o文件是由链接器ld来进行组合打包的,而.o文件又依赖于对应的.c文件(源文...原创 2019-03-13 17:43:13 · 388 阅读 · 0 评论 -
不安全的strcat()所引出的缓冲区溢出
做The C Programming Language中的习题5-3时,程序跑出了个 stack smashing detected,于是探究一下。最初出现stack smashing detected的代码是这样的:#include &amp;amp;lt;stdio.h&amp;amp;gt;void strcats(char *s, char *t);int main(){ char s1[] = &amp;quot;Hello.原创 2019-03-12 11:00:01 · 3969 阅读 · 0 评论 -
指针和数组小记
DSAA in C 看到hash table的建立,对Figure5.8的程序中二级指针、一级指针和数组下标的用法有些疑惑,梳理一下指针和数组的关系。写段代码看看:int main(){ int a0 = 0; int a1 = 1; int a[2]; //a is the name of an int array, also a int const pointer a[0] ...原创 2019-03-21 11:36:25 · 302 阅读 · 0 评论 -
侯捷-C++ 面向对象高级编程-笔记
大纲以良好的方式编写C++ class - Object based (基于对象)对于class without pointer members 和 with pointer members有所不同(考虑浅拷贝和深拷贝问题)classes 之间的关系 - Object oriented (面向对象)继承(is-a)、复合(has-a)和委托(composition by referenc...原创 2019-03-22 17:34:23 · 343 阅读 · 0 评论 -
C语言数据结构的套路
跟着DSAA in C写代码,总结起来各种数据结构大概都是这个套路:首先是定义:typedef struct XXXXX{ //数据结构包含的元素} XXX然后分配空间,malloc(sizeof(XXX))对于用到数组来存储数据元素的,还要额外给数组分配空间,比如队列:Q->array = malloc(sizeof(int) * max);最后用完之后一定要记得fre...原创 2019-06-26 22:42:41 · 292 阅读 · 0 评论 -
Bug Record
1.容易不小心写错的几个运算符赋值 = 判断 ==条件与 && 位与 &条件或 || 位或 |2.vector的insert方法如果想要把vec1追加到vec2的末尾,却不小心写成vec2.insert(vec2.end(),vec2.begin(),vec2.end());,就会吧原先vec2的内容再复制一遍,正确的写法是vec2.insert(vec2....原创 2019-08-20 23:02:51 · 131 阅读 · 0 评论 -
大小端-An Example
参考:大端 小端 与memcpy来看这样一段代码:本意是想把uint8_t a[2]中的内容合成一个uint16_t b#include <stdlib.h>#include <stdio.h>#include <stdint.h>int main(){ uint8_t a[2] = { 0x11, 0x22 }; uint16_t b;...原创 2019-08-31 23:57:21 · 1087 阅读 · 5 评论 -
new和delete、new[]和delete[]的使用
实验代码如下,可以试试不配对使用的后果。#include&lt;iostream&gt;using namespace std; class Test{public: ~Test() { cout &lt;&lt; "调用析构函数" &lt;&lt; endl; }}; int main(){ Test *ptr = new Te原创 2019-03-04 23:10:57 · 1279 阅读 · 0 评论