C/C++相关概念和易错知识点(36)(list)

C++ STL LIST SORT 排序算法图解 最近看 <<C++性能优化指南>> 留意到上面说 std::list::sort 算法能做到 O(nlog2(n)) 复杂度,而直接对 std::list 套用 std::sort 只能做到 O(n²) 思考后发现如果把 std::sort 套到 std::list 上由于是 Bidirectional Iterator 的原因,计算距离的时候需要一步一步的移动,经典的 ... 阅读详情

1.list易错点

(1)慎用list的sort,list的排序比vector慢得多,尽管两者时间复杂度一样,甚至不如先把list转为vector,用vector排完序后再转为list

(2)splice是剪切链表,将x的部分剪切到pos后,也可以自己剪自己的

(3)list迭代器不支持[]运算符,但相比较vector多支持了push_front和pop_front,原因在于[]效率不高,push_front和pop_front效率高

2.list模拟实现

list实现中我们会用到多个模板,注意每个template定义的模板参数都只能供当前类或函数使用,不存在一个文件中所有T都是一个意思

(1)结点

为了适应不同数据的存储,我们采用模板的方式来定义结点。为了能够体现封装特性,我们将创建结点并赋值作为一个构造函数写入类ListNode中。因为在接下来的class list中会频繁调用lt->next,即在外部访问LIstNode的成员变量,所以我们的ListNode使用struct,默认访问限定符是public

(2)无参构造和析构

我们的list是带头双向循环链表,所以所有的构造都需要定义一个哨兵位

还有很多带参的构造,虽然这里我们可以去实现,但是它们需要使用到的功能和后面的函数相符合,所以我会先实现后续的函数。

析构只需要遍历所有节点,将它们释放即可

(3)迭代器

list的迭代器和指针就拉开了差距,list的数据是不连续存储的,因此无法使用指针的加减来遍历list。我们需要定义一个iterator的类,在这个类里重载运算符++、*等操作,使它们在使用过程中和指针一致但能够正常访问数据。

我们使用ListNode*作为结点的标识,当++时就调用它的_next,--就调用它的_prev,*就返回对应_data的值。有了这个思路,迭代器的大部分功能我们都可以顺利实现了。


	template<class T, class T1 = T>
	struct List_iterator
	{
		typedef ListNode<T> Node;
		typedef List_iterator<T, T1> iterator;

		List_iterator(Node* node)
			:_curnode(node)
		{}

		iterator operator++()
		{
			_curnode = _curnode->_next;
			return _curnode;
		}
		
		iterator operator--()
		{
			_curnode = _curnode->_prev;
			return _curnode;
		}		
		
		iterator operator++(int)
		{
			_curnode = _curnode->_next;
			return _curnode->_prev;
		}		
		
		iterator operator--(int)
		{
			_curnode = _curnode->_prev;
			return _curnode->_next;
		}

		T1& operator*()//对于const T无法进行修改
		{
			return _curnode->_data;
		}

		T1* operator->()//对于const T无法进行修改
		{
			return &(_curnode->_data);
		}

		bool operator!=(const List_iterator lt) const
		{
			return _curnode != lt._curnode;
		}

		bool operator==(const List_iterator lt) const
		{
			return _curnode == lt._curnode;
		}


		Node* _curnode;
	};

但是这里面还有一些代码需要解释

a.operator->()

要理解这里,我们要思考迭代器本身想要模仿的是指向数据的指针,如果存储类型是int,对应iterator和int*的使用方式一模一样,类似地,像char、double、int*等内置类型是这样,那么自定义类型呢?operator->()就是为了模仿自定义类型的指针而专门设计的。

我们先将T1就看成T,T是一个结构体,里面有自己的成员变量,当我们使用结构体指针想要访问它们时,我们首先要拿到这个结构体的地址,再用->访问,这里的iterator也是如此,_data是结构体类型,我们直接先指向这个结构体内容本身,即_curnode->_data,这个表达式的返回值是一个结构体,也就是我们想要访问的结构体,但是我们是要模拟指针的操作,要使用->而不是.,所以我们要再对它取地址,即&(_curnode->_data),这样返回的就是一个指向_data的指针了,当我们调用it.operator->()->(成员变量)时就能访问结构体内部的成员变量了,简化为it->(成员变量),省略了一个->为了易读性。

b.T1和T的区分

在我们想要创建一个const_iterator时,T1的出现就很重要了。

当不传第二个模板参数时,默认和第一个一样,如果传了const T,那就使用传的参数

对于这两个要返回指针或引用的函数,加上const修饰T可以防止T被修改。那为什么不直接用const T一个参数呢?要注意const int和int是两个类型,对于一些自定义类型来说有很大区别,所以要分成两块来写。

有了上面的基础,反向迭代器也可以很快的完成,思路就是复用,用刚刚实现的正向迭代器稍加修改得到。


	template<class T, class T1 = T>
	struct List_reverse_iterator
	{
		typedef ListNode<T> Node;
		typedef List_iterator<T, T1> iterator;
		typedef List_reverse_iterator<T, T1> reverse_iterator;

		List_reverse_iterator(Node* node)
			:_it(node)
		{}

		List_reverse_iterator(iterator it)
			:_it(it)
		{}

		reverse_iterator operator++()
		{
			return --_it;
		}

		reverse_iterator operator--()
		{
			return ++_it;
		}

		reverse_iterator operator++(int)
		{
			return _it--;
		}

		reverse_iterator operator--(int)
		{
			return _it++;
		}

		T1& operator*()//对于const T无法进行修改
		{
			return *_it;
		}

		T1* operator->()//对于const T无法进行修改
		{
			return &(*_it);
		}

		bool operator!=(const List_reverse_iterator lt) const
		{
			return _it != lt._it;
		}

		bool operator==(const List_reverse_iterator lt) const
		{
			return _it == lt._it;
		}


		iterator _it;
	};

(4)push_back

push_back是非常关键的一个函数,在构造函数中,我们经常用到它

先用val创建一个newnode,找到尾节点并修改尾节点和哨兵位的_prev和_next使得newnode插入链表中

(5)insert

我们实现insert的方式是先实现一个可复用性最强的函数(迭代器版本的insert),再用它实现其它函数

后续的函数只需要调整参数复用即可

iterator insert(iterator pos, int n, int val)//特殊处理,防止定位错误
{
	return insert(pos, (size_t)n, (T)val);
}

iterator insert(iterator pos, size_t n, const T& val)
{
	list<T> tmp;
	for (size_t count = 0; count < n; count++)
	{
		tmp.push_back(val);
	}

	return insert(pos, tmp.begin(), tmp.end());
}		

iterator insert(iterator pos, const T& val)
{
	return insert(pos, 1, val);
}

其中有一个函数需要解释

当我们调用insert(lt.begin(), 1, 3)时,是想在首位置插入1个3,但是编译器会将1,3识别成迭代器(注意看我们之前已经实现了模板函数,1和3同类型是会匹配的),size_t和const int&虽然都能作为1和3的类型,但它们都不叫完美匹配,不完美匹配就会去找模板函数。

注意各大整型家族的区别,10u是unsigned int类型。

因此我们只有针对这一种情况进行单独处理,将它们强转后就可以匹配正确的函数了。

(6)erase

我们的思路也是先实现一个可复用性最强的,再对其它函数复用。这些函数逻辑都很简单,不做过多讲解。

(7)带参构造

这里我们就可以发现,只要有了push_back,insert,我们实现这些带参构造就很快了,我们要学会复用,即实现最关键的几个函数,其它的函数用这几个核心的函数套用就可以了,这不仅节省了我们的时间,还使得代码易于维护,失误率降低。

list(size_t n, const T& val)
{
	_head = new Node;
	_head->_next = _head->_prev = _head;

	for (size_t count = 0; count < n; count++)
	{
		push_back(val);
	}
}

list(const list<T>& lt)
{
	_head = new Node;
	_head->_next = _head->_prev = _head;

	for (const auto& e : lt)
	{
		push_back(e);
	}
}


template<class Init>
list(Init first, Init last)
{
	_head = new Node;
	_head->_next = _head->_prev = _head;

	insert(begin(), first, last);
}
		

(8)全部代码(包含一些边缘性的函数)

注意模板函数是按需实例化,只检查调用的实例化的函数,不调用就不实例化

#pragma once

#include <iostream>
#include <algorithm>
#include <assert.h>

using namespace std;


namespace my_list
{
	template<class T>
	struct ListNode
	{
		ListNode(const T& data = T())
			:_data(data)
			, _next(nullptr)
			, _prev(nullptr)
		{}

		T _data;
		ListNode<T>* _next;
		ListNode<T>* _prev;
	};



	template<class T, class T1 = T>
	struct List_iterator
	{
		typedef ListNode<T> Node;
		typedef List_iterator<T, T1> iterator;

		List_iterator(Node* node)
			:_curnode(node)
		{}

		iterator operator++()
		{
			_curnode = _curnode->_next;
			return _curnode;
		}
		
		iterator operator--()
		{
			_curnode = _curnode->_prev;
			return _curnode;
		}		
		
		iterator operator++(int)
		{
			_curnode = _curnode->_next;
			return _curnode->_prev;
		}		
		
		iterator operator--(int)
		{
			_curnode = _curnode->_prev;
			return _curnode->_next;
		}

		T1& operator*()//对于const T无法进行修改
		{
			return _curnode->_data;
		}

		T1* operator->()//对于const T无法进行修改
		{
			return &(_curnode->_data);
		}

		bool operator!=(const List_iterator lt) const
		{
			return _curnode != lt._curnode;
		}

		bool operator==(const List_iterator lt) const
		{
			return _curnode == lt._curnode;
		}


		Node* _curnode;
	};


	template<class T, class T1 = T>
	struct List_reverse_iterator
	{
		typedef ListNode<T> Node;
		typedef List_iterator<T, T1> iterator;
		typedef List_reverse_iterator<T, T1> reverse_iterator;

		List_reverse_iterator(Node* node)
			:_it(node)
		{}

		List_reverse_iterator(iterator it)
			:_it(it)
		{}

		reverse_iterator operator++()
		{
			return --_it;
		}

		reverse_iterator operator--()
		{
			return ++_it;
		}

		reverse_iterator operator++(int)
		{
			return _it--;
		}

		reverse_iterator operator--(int)
		{
			return _it++;
		}

		T1& operator*()//对于const T无法进行修改
		{
			return *_it;
		}

		T1* operator->()//对于const T无法进行修改
		{
			return &(*_it);
		}

		bool operator!=(const List_reverse_iterator lt) const
		{
			return _it != lt._it;
		}

		bool operator==(const List_reverse_iterator lt) const
		{
			return _it == lt._it;
		}


		iterator _it;
	};

	template<class T>
	class list
	{
	public:

		typedef ListNode<T> Node;

		typedef List_iterator<T> iterator;
		typedef List_iterator<T, const T> const_iterator;

		typedef List_reverse_iterator<T> reverse_iterator;
		typedef List_reverse_iterator<T, const T> const_reverse_iterator;



		list()
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;
		}


		list(size_t n, const T& val)
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;

			for (size_t count = 0; count < n; count++)
			{
				push_back(val);
			}
		}

		list(const list<T>& lt)
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;

			for (const auto& e : lt)
			{
				push_back(e);
			}
		}


		template<class Init>
		list(Init first, Init last)
		{
			_head = new Node;
			_head->_next = _head->_prev = _head;

			insert(begin(), first, last);
		}
		
		~list()
		{
			Node* cur = _head->_next, * next = _head->_next->_next;

			while (cur != _head)
			{
				delete cur;
				cur = next, next = next->_next;
			}

			delete _head;

			_head = nullptr;
		}

		size_t size()
		{
			size_t count = 0;

			for (const auto& e : *this)
			{
				count++;
			}

			return count;
		}

		bool empty()
		{
			return _head->_next == _head;
		}


		list<T>& operator=(const list<T>& lt)
		{
			if (lt._head != _head)
			{
				clear();

				for (const auto& e : lt)
				{
					push_back(e);
				}
			}

			return *this;
		}

		T& front()
		{
			return *begin();
		}		
		
		T& back()
		{
			return *(--end());
		}		
		
		const T& front() const
		{
			return *begin();
		}		
		
		const T& back() const
		{
			return *(--end());
		}

		void swap(const list<T>& lt)
		{
			std::swap(_head, lt._head);
		}

		iterator begin()
		{
			return iterator(_head->_next);
		}
		
		iterator end()
		{
			return iterator(_head);
		}		
		
		const_iterator begin() const
		{
			return const_iterator(_head->_next);
		}
		
		const_iterator end() const
		{
			return const_iterator(_head);
		}


		reverse_iterator rbegin()
		{
			return reverse_iterator(_head->_prev);
		}

		reverse_iterator rend()
		{
			return reverse_iterator(_head);
		}

		const_reverse_iterator rbegin() const
		{
			return const_reverse_iterator(_head->_prev);
		}

		const_reverse_iterator rend() const
		{
			return const_reverse_iterator(_head);
		}

		void push_back(const T& val)
		{
			Node* newnode = new Node(val);
			Node* tail = _head->_prev;

			tail->_next = newnode;
			newnode->_prev = tail;

			newnode->_next = _head;
			_head->_prev = newnode;
		}		
		
		void push_front(const T& val)
		{
			insert(begin(), 1, val);
		}

		void pop_front()
		{
			erase(begin());
		}

		void pop_back()
		{
			erase(--end());
		}

		template<typename Input>
		iterator insert(iterator pos, Input first, Input last)
		{
			Node* cur = pos._curnode->_prev, * next = cur->_next;
			Node* ret = cur;

			while (first != last)
			{
				Node* newnode = new Node((T)(*first));

				cur->_next = newnode, newnode->_prev = cur;
				newnode->_next = next, next->_prev = newnode;

				cur = cur->_next;
				first++;
			}

			return ret->_next;//新插入的第一个结点对应的迭代器,有隐式类型转换
		}

		iterator insert(iterator pos, int n, int val)//特殊处理,防止定位错误
		{
			return insert(pos, (size_t)n, (T)val);
		}

		iterator insert(iterator pos, size_t n, const T& val)
		{
			list<T> tmp;
			for (size_t count = 0; count < n; count++)
			{
				tmp.push_back(val);
			}

			return insert(pos, tmp.begin(), tmp.end());
		}		
		
		iterator insert(iterator pos, const T& val)
		{
			return insert(pos, 1, val);
		}

		iterator erase(iterator first, iterator last)
		{

			Node* cur = first._curnode->_prev, * next = last._curnode;
			
			iterator nextit = first;

			while (first != last)
			{
				nextit++;

				delete first._curnode, first = nextit;
			}

			cur->_next = next, next->_prev = cur;

			return cur->_next;
		}


		iterator erase(iterator pos)
		{
			iterator cur = pos;

			return erase(pos, ++cur);
		}


		void clear()
		{
			erase(begin(), end());
		}

	private:
		Node* _head;
	};


}

C/C++不定参技术详解:从宏函数到可变参数模板的实战指南 在C/C++编程中,可变参数处理是提升代码灵活性和复用性的关键技术。其核心原理在于允许函数或宏接受数量不定的参数,从而适应不同调用场景。从技术实现层面看,主要分为预处理阶段展开的不定参宏函数和运行时处理的C风格不定参函数。不定参宏函数通过__VA_ARGS__等预处理器机制实现,虽然性能零开销,但存在类型安全缺失和调试困难等陷阱;而C风格不定参函数依赖va_list等标准库API,虽兼容性好却存在参数类型安全隐患。现代C++通过可变参数模板提供了类型安全的编译期解决方案,结合std::initializer 阅读详情

相关推荐

VSCode C++头文件路径配置:IntelliSense includePath详解

C++开发中,#include错误提示本质是IntelliSense智能感知引擎因头文件路径缺失导致的静态分析预警,而非编译器错误。其原理在于IntelliSense独立维护头文件索引数据库,需显式配置includePath才能定位标准库(如<iostream>)和第三方头文件。技术价值体现在提升代码补全、跳转定义、悬停提示等编辑体验;典型应用场景包括Linux/macOS下g++-v提取路径、Windows下MinGW或MSVC路径展开、跨平台项目动态变量适配,以及Boost/OpenCV等第三方库的层级

weixin_34174422的博客 406

C++List原理和坑点

list采用的是链表,没错就是数据结构中的链表。但是不是单链表是双向循环链表。接下来我们自己实现一个简化版的的list。紧接着我们就需要构建list类了。这就是list的实现了。

zengkui198513的博客 241

零成本本地运行Gemma 4:Ollama/llama.cpp/MLX三方案实操指南

大语言模型本地部署正从‘能跑’迈向‘好用’阶段,核心在于脱离中心化API、实现端侧可控推理。其技术基础是轻量化模型架构(如Gemma系列)与高效推理框架(Ollama、llama.cpp、MLX)的协同演进——前者优化KV缓存与量化兼容性,后者提供跨平台、低依赖的执行能力。这种组合显著降低硬件门槛,使MacBook Air、RTX 3090等主流设备即可承载12B级模型,兼顾响应速度与隐私安全。典型应用场景包括私有知识库问答、离线编程辅助、政务/金融文档摘要等对数据不出域、低延迟、高可控性有强需求的工程实践

weixin_30915275的博客 389

C++初阶(10)/STL(三) :list

文章聚焦C++标准库双向链表容器std::list,剖析其核心特性与使用要点。阐述其作为双向链表的特性,如O(1)时间复杂度的任意位置插入/删除、不支持随机访问等;详解构造方法、迭代器操作等常用接口,强调insert/erase用法及迭代器失效问题;展示反向迭代器、链表节点等模拟实现细节;并与vector从底层结构、性能、空间利用等方面展开全面对比。

2401_86650143的博客 1102

2023-02-07 mysql5.7.36-代码概括分析

考虑到现在项目的情况, 对所使用的mysql5.7.36代码做总体上的概括分析.方式上是采用先总体,后局部的做法。

悟世之路 324

VS Code配置C/C++开发环境:Windows与Linux完整指南

C/C++开发环境本质是编辑器、编译器与调试器的协同系统。VS Code作为轻量级编辑器,需手动集成GCC/Clang工具链、配置tasks.json构建任务、launch.json调试流程及c_cpp_properties.json头文件路径,才能实现写代码→编译→调试的完整闭环。核心原理在于分离‘编译执行’与‘智能感知’:gcc负责生成可执行文件和调试符号(-g),IntelliSense则依赖includePath独立解析头文件。技术价值体现在跨平台一致性、工业级调试能力及对C17/C++20等新标准

weixin_33770878的博客 423

LeetCode 36. 有效的数独:一次遍历校验 9×9 棋盘的行、列与 3×3 宫格(doocs/leetcode 多语言题解全解析)

本篇技术指南聚焦 LeetCode 第 36 题「有效的数独(Valid Sudoku)」:在只验证已填入数字的前提下,如何依据行、列、3×3 宫格三条规则判断一个 `9 x 9` 数独棋盘是否有效。文章以 doocs/leetcode 仓库中该题的官方题解为骨架,完整继承题目约束、双示例与一次遍历(单次扫描 + 三张布尔表)的解法思路,并逐语言解析仓库内 Python3、Java、C++、Go、

gitblog_00426的博客 432

华为云Stack交付实战:从工勘到上线的全流程拆解

本文详细拆解华为云Stack交付全流程,从项目启动、工勘、LLD设计到硬件部署和软件安装,提供实战技巧与避坑指南。重点解析华为云Stack交付流程中的关键环节,如标准化工具使用、规范化文档管理和流程化协作,帮助团队高效完成从工勘到上线的复杂项目交付。

weixin_29243063的博客 156

ChatLLM.cpp:C++原生GLM+OCR融合架构解析

OCR(光学字符识别)作为多模态理解的基础能力,其核心价值在于将图像中的文字结构化为可计算语义。传统方案依赖Python胶水层串联Tesseract、PaddleOCR等引擎与大语言模型,导致延迟高、内存开销大、部署复杂。而基于C++原生实现的GLM-OCR融合架构,通过改造tokenizer引入空间坐标special token、复用视觉特征图作为visual prefix,实现了OCR结构化输出与大模型token流的零拷贝直通。该技术显著降低端侧推理延迟与资源占用,适用于边缘设备、古籍数字化、企业私有化

weixin_30595035的博客 408

【Zephyr 系列 29】低功耗调试指南:电流测量、系统睡眠与功耗分析

Zephyr低功耗调试指南(150字摘要) 针对物联网设备续航需求,本文解析Zephyr低功耗调试方法:1️⃣ 机制:启用PM子系统和tickless idle,配置睡眠策略;2️⃣ 测量:推荐功耗分析仪捕捉μA级电流波动;3️⃣ 优化:管理唤醒源(如GPIO/RTC)、调整BLE广播/连接参数,挂起闲置外设;4️⃣ 分析:建立功耗文档,对比不同模式电流(如待机0.6mA vs广播3.2mA)。强调低功耗需系统性设计,初期即需纳入测试流程。下期将探讨Zephyr OTA升级实现。

hemoparrot的专栏 1180

避免踩坑!WIN11 22H2更新后共享打印机失效的终极解决方案

本文详细解析了WIN11 22H2更新后共享打印机失效的问题,特别是常见的0x00000709错误代码。通过系统更新机制分析、错误代码解读,提供从基础到高级的完整解决方案,包括注册表修复、组策略调整和驱动兼容性处理,帮助用户彻底解决打印机共享问题并预防未来故障。

pp12345的博客 533

结合 Cpp-Primer 仓库源码,精讲《C++ Primer(第 5 版)》第 3 章:字符串、向量与数组

《C++ Primer(第 5 版)》第 3 章是全书的第一个"库类型"章节,围绕 `string`、`vector`、迭代器与数组这四大主题,通过 45 道习题引导读者建立 C++ 标准库的底层直觉。本文以本仓库 [ch03/README.md](https://link.gitcode.com/i/4240a5718add045336c11d6e723f0806) 的习题清单与解答为骨架,逐一

gitblog_00708的博客 182

那些年-SAP固定资产导入AS91 OASV

固定资产起初导入步骤: 第一部分:资产数据导入 1)两个日期配置 填写图片摘要(选填) Specify transfer date/last closed fiscal year 这里的日期填写系统切换日期,如果系统是2015-10-01上线,这里填写2015-09-3 填写图片摘要(选填) Specifylast period posted in prv system 这里指定系统切换的上一期间。这里写2015-09 填写图片摘要(选填) ​2)AS91新增 填写固定资产的分类,公司

阿土工作室 7947

GenieX 运行指南:在 Snapdragon 上选择 NPU/GPU/CPU 计算单元并运行 llama_cpp 与 QAIRT 模型

本文以 [notes/run.md](https://link.gitcode.com/i/a5d4bc6aa213101510cdb0aa1eaf1605) 为核心,系统讲解 GenieX 在 Snapdragon(如 X Elite 的 X1E80100,以及 SM8750、SM8850 等 SoC)上运行前沿 LLM/VLM 的核心知识:两种运行时(`llama_cpp` 与 `qairt`

gitblog_00321的博客 1029

信捷CODESYS平台伺服电机转矩控制模式应用与切换

信捷CODESYS二次开发软件:XS Studio 在运动控制中的转矩控制案例

weixin_64614866的博客 1万+

Diffusion、VAE与GAN:三大生成模型的原理对比与应用场景解析

本文深入解析了Diffusion、VAE与GAN三大生成模型的核心原理与特性。Diffusion模型通过逆向去噪过程实现高质量图像生成,但计算成本较高;VAE擅长学习概率潜空间,训练稳定但图像偏模糊;GAN通过对抗训练生成锐利图像,但存在模式崩溃风险。文章结合实战场景,为图像生成、修复、超分辨率等任务提供了清晰的模型选择指南。

weixin_29063979的博客 342

c++ 参数列表_Python第三天 list列表

所谓列表就相当于是一个C或者Java的数组创建方式a = []如此简单下面写两个带元素的列表a=[2,3,4] list = [1,3,'chenhaiyun',a]可知列表a是一个三个数字的列表,而list列表里不仅包含数字,也包含字符串,还包含了a列表。(理解一下这句话)上图是在conda notebook编辑的list列表里有4个元素,下标从0开始,0-3;list[3]就是a列表list[...

weixin_35291771的博客 159

OpenCV实战之人脸美颜美型(八)——大眼(上)

从大众审美的角度来看,眼睛适当的“变大”会让人显得更加年轻。因此美型中就有一项大眼功能,其效果就是让眼睛适当变大,这章内容就围绕着大眼算法展开。

On my way 1211

va_list/va_start/va_arg/va_end深入分析

原文地址::http://www.cnblogs.com/justinzhang/archive/2011/09/29/2195969.html va_list/va_start/va_arg/va_end这几个宏,都是用于函数的可变参数的。 我们来看看在vs2008中,它们是怎么定义的: 1: ///stdarg.h 2: #define

xqhrs232的专栏 349

RK3588在线更新系统内核的方法

《RK3588设备在线升级系统内核方法》 本文介绍了RK3588设备在线升级系统内核的简易方法。通过将新内核文件boot.img拷贝至目标主机后,使用dd命令配合关键参数(fsync确保写入磁盘、notrunc避免截断分区)进行安全更新,更新后需执行sync同步操作并重启生效。文章特别强调操作过程中断电风险,并扩展说明了Uboot的类似更新方法。该方法避免了现场设备拆卸的麻烦,为嵌入式系统维护提供了实用解决方案。

荻夜的博客 1047

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Wand-Enhancer 完整解锁 WeMod Pro 指南:5分钟手把手上手

Wand-Enhancer 是一个面向 Wand(WeMod)客户端的开源本地补丁工具:不用购买 Pro,就能在你自己的机器上解锁 Pro 功能集,还附带开发者工具、禁用更新、手机远程面板等可选项。整个过程只改本机安装目录里的文件,打补丁前会先备份原始内容。 [![Wand-Enhancer WeMod Pro 补丁工具主界面](https://raw.gitcode.com/GitHub_Tr

gitblog_00233的博客 197

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

c++ list用法_Python第三天 list列表

所谓列表就相当于是一个C或者Java的数组创建方式a 如此简单下面写两个带元素的列表a=[2,3,4] list = [1,3,'chenhaiyun',a]可知列表a是一个三个数字的列表,而list列表里不仅包含数字,也包含字符串,还包含了a列表。(理解一下这句话)上图是在conda notebook编辑的list列表里有4个元素,下标从0开始,0-3;list[3]就是a列表list[3][0...

weixin_39631689的博客 299

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

C语言从零到实战:系统学习路径与核心概念精讲

编程语言是计算机科学的基础工具,其核心在于通过语法规则将人类逻辑转化为机器可执行的指令。C语言作为一门接近硬件、高效灵活的系统级语言,其设计原理直接映射了计算机底层的内存管理和执行机制,这使得它在操作系统、嵌入式开发和高性能计算等对效率要求极高的场景中具有不可替代的技术价值。理解C语言不仅是为了掌握一门编程工具,更是为了深入理解计算机系统的工作原理,为学习数据结构、算法乃至高级语言打下坚实基础。本文围绕C语言的核心概念,如指针、内存管理和函数模块化,结合初学者常见的热点问题,提供了从环境搭建、语法精讲到实战

wangqiaowqo的专栏 368

LeetCode 36. 有效的数独:一次遍历判定 9x9 棋盘的行、列与宫格不重复约束

本文以 [LeetCode 36. Valid Sudoku(有效的数独)](https://link.gitcode.com/i/e7e6d1e8ecc32c8cd437e34c7b60965f) 题解文档为核心,结合 doocs/leetcode 仓库中 Python3、Java、C++、Go、TypeScript、Rust、JavaScript、C#、PHP 共 9 种语言的完整实现,深入讲

gitblog_00971的博客 231
上一篇: C/C++相关概念和易错知识点(35)(sort、vector模拟实现)
下一篇: C/C++相关概念和易错知识点(37)(适配器模式、仿函数)
-SGlow-
博客等级 码龄3年 1513粉丝 118原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值