c/c++语法陷阱及常见编译错误

目录

编译错误

error: jump to label ‘JUMP’ [-fpermissive]

语法陷阱

1、逗号运算符的错误使用

2、结构体类型的变量的初始化

3、free/delete之后一定要赋NULL

4、十六进制数转字符类型的大小写问题

5、容器vector使用的陷阱


编译错误

error: jump to label ‘JUMP’ [-fpermissive]

 问题原因:

goto 语句之后又有新的变量定义, 将 int value1 变量放在 goto 之前即可

语法陷阱

1、逗号运算符的错误使用

先看以下代码

这个代码我的原意是想让循环次数取较小的值,但是结果却发生了偏差,实际项目中就会出现内存越界。

回顾一下 for和逗号运算符的用法

for(表达式1; 表达式2; 表达式3){
    语句块
}
它的运行过程为:
1) 先执行“表达式1”。
2) 再执行“表达式2”,如果它的值为真(非0),则执行循环体,否则结束循环。
3) 执行完循环体后再执行“表达式3”。
4) 重复执行步骤 2) 和 3),直到“表达式2”的值为假,就结束循环。

整个逗号表达式的值为系列中最后一个表达式的值

所以for循环中如果有逗号运算符,那么整个逗号表达式的最后一个表达式为真循环就会继续运行下去。

因此正确写法

2、结构体类型的变量的初始化

常见的两种初始化方式

struct  stList  A = {}; 或者 struct  stList  A;memset(&A, 0, sizeof(struct  stList));

第一种方式实际上只给结构体中的每个成员变量初始化了,由于结构体对齐的原则,成员之间内存碎片是没有初始化的,虽然很多时候系统默认值就是0,但是我们并不能指望所有系统都是这样做的。

第二种则将整个结构体都初始化了。

通过示例程序帮助理解一下:

3、free/delete之后一定要赋NULL

delete/free一个指针之后,只是回收指针指向位置的空间,而指针本身的值不变。如果不赋NULL,后续用到此指针后就会发生莫名其妙的错误。

工作中遇到了一个设置OSD多次后偶现设备挂机的问题,且使用gdb也无法定位到问题。无奈使用打印大法,多次复现后发现以下代码段。

设置osd的时候需要加载用到的字库到内存,最多加载100个,后续如果有新的字需要加载 且100个已经全部占用时,会先销毁后面50个,给新的字形使用。由于销毁的时候delete之后没有赋NULL,导致 p_ttf->stUsedGlyf.p_letter[i]不等于NULL,因此导致重复释放,造成挂机。

4、十六进制数转字符类型的大小写问题

大写的%X转出来就是大写, 小写的x转出来就是小写

#include <stdio.h>
#include <string.h>

int main()
{
		unsigned char source[16] = {};
		unsigned char Out[16] = {};
		unsigned char out[16] = {};
		int pos = 0;

		source[0] = 0x69;
		source[1] = 0x24;
		source[2] = 0x9e;
		source[3] = 0x45;
		source[4] = 0xdd;
		source[5] = 0x8f;
		source[6] = 0x10;
		source[7] = 0x88;

		for (int i = 0; i < 8; ++i)
				printf("%02x ", source[i]);
		printf("\n");

		for (int i = 0; i < 8; ++i)
		{
				sprintf(Out + pos, "%02X", source[i]);//大写X
				pos += 2;
		}
		printf("Out = %s\n", Out);

		pos = 0;
		for (int i = 0; i < 8; ++i)
		{
				sprintf(out + pos, "%02x", source[i]);//小写x
				pos += 2;
		}

		printf("out = %s\n", out);

		return 0;
}

执行结果:

5、容器vector使用的陷阱

erase方法在删除成员时,容器大小会减一,所以如果使用objs.size();判断循环的话, 就会导致判断不完整。正确的判断方法应该如_MTDet_ObjFilter方法所示例

#include <iostream>
#include <vector>

using namespace std;

typedef struct
{
    int frame_id;
    int cls;
}Object;

class VideoCapture
{
	public:
	VideoCapture(void);
	~VideoCapture(void);
};

VideoCapture::VideoCapture(void)
{
	cout << "=====VideoCapture==========" << endl;
}

VideoCapture::~VideoCapture(void)
{
	cout << "======= ~ VideoCapture========" << endl;
}

int _MTDet_ObjPrint(std::vector<Object> &objs)
{
	cout << "\n" << endl;
	for (int i = 0; i < objs.size(); ++i)
	{
		Object obj = objs.at(i);
		
		
		cout << "i = " << i << ", size = " << objs.size() << ", frame_id = " << obj.frame_id  << ", cls = " << obj.cls << endl;
	}
	cout << "=============== " << objs.capacity() << "\n" << endl;
	
	return 0;
}

int _MTDet_DetObject(std::vector<Object> &objs)
{
	for (int i = 0; i < 4; ++i)
	{
		Object obj;
		obj.frame_id = i;
		
		obj.cls = 1;
		
		if ((0 == i) || (1 == i))
			obj.cls = 2;
		
		objs.push_back(obj);
	}
	
	return 0;
}

int _MTDet_ObjFilter(std::vector<Object> &objs)
{
	for (int i = 0; i < objs.size();)
	{
		cout << "i = " << i << ", size = " << objs.size() << endl;
		
		Object obj = objs.at(i);
		if (2 == obj.cls)
		{
			objs.erase(objs.begin() + i);
			//_MTDet_ObjPrint(objs);
			continue;
		}
		//else
		//{
			++i;
		//}
			//objs.erase(objs.begin() + i);
		
	}

	return 0;
}

int main()
{
	std::vector<Object> objs;
	
	_MTDet_DetObject(objs);
	_MTDet_ObjPrint(objs);
	
	_MTDet_ObjFilter(objs);
	_MTDet_ObjPrint(objs);
	
	return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值