struct mtd_partition {
const char *name; /* identifier string */
uint64_t size; /* partition size */
uint64_t offset; /* offset within the master MTD space */
};
static struct mtd_partition parts[] = {
{name: "boot", offset: 0, size:0x500000,},
{name: "setting", offset: 0x500000, size:0x300000,},
{name: "linux", offset: 0x800000, size:0x500000,},
{name: "config", offset: 0xd00000, size:0x100000,},
{name: "rootfs", offset: 0xe00000, size:0x3200000,},
{name: "app", offset: 0x4e00000, size:0x800000,},
};
static struct resource pxa27x_resource_ohci[] = {
[0] = {
.start = 0x4C000000,
.end = 0x4C00ff6f,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = IRQ_USBH1,
.end = IRQ_USBH1,
.flags = IORESOURCE_IRQ,
},
};
这些方法虽然不知道是C的哪个标准引入的,但是见到有代码这样用。
sanitizers是Google推出的调试工具。已集成到各主流编译器之中,无需安装。
代码:
https://github.com/google/sanitizers
参考:
https://zhuanlan.zhihu.com/p/257939964
编译器自带的调试神器sanitizers
spaceship operator: <=>
C++20引入了spaceship operator:
a<b
,返回std::strong_ordering::less。a>b
,返回std::strong_ordering::greater。这和strcmp
的设计理念类似。
此外,还有关系运算符的重载推导,定义了<=>
之后,其他诸如==
、!=
、<
、<=
、>
、>=
的关系运算自动成立,无需再写相应的重载函数了。同理,如果定义了==
,那么!=
就自动成立了。
参考:
https://cloud.tencent.com/developer/article/1352324
C++20草案中的宇宙飞船运算符(<=>,spaceship operator)
线程安全注解是现代C++开发的机制,可以在代码编译阶段检查锁的使用情况,从而发现线程同步的相关问题。该功能目前只有clang编译器支持。
https://blog.csdn.net/qq_32648921/article/details/109114887
线程安全注解
Implementation-defined:C标准没有明确规定,但是要求编译器必须对此做出明确规定,并写在编译器的文档中。
Unspecified:C标准没有明确规定,编译器可以自己决定,不必写在编译器的文档中。
Undefined:C标准没规定怎么处理,编译器很可能也没规定。
https://www.cnblogs.com/MagicLetters/archive/2011/08/03/2126471.html
C语言中关于Implementation-defined、Unspecified和Undefined
struct CLS
{
int m_i;
CLS( int i ) : m_i(i){}
CLS()
{
CLS(0);
}
};
如上,在CLS()
调用CLS(0);
会创建一个新的临时对象,达不到重载的目的。
应该怎么做呢?new (this)CLS(0);
https://www.cnblogs.com/stemon/p/4834043.html
在构造函数内部调用构造函数
如果基类析构函数不是虚函数,则当通过父类指针或引用指向子类时,在调用析构函数时只调用父类的析构函数,所以只释放父类在堆区开辟的内存,子类在堆区开辟的内存没有被释放。
string test()
{
return "abc";
}
int main()
{
const char *p = test().c_str();
cout << p << endl;
return 0;
}
string("abc")
是一个临时对象,在执行完const char *p = string("abc").c_str();
这个语句后,临时对象就析构了,而不会等到块结束。
https://blog.csdn.net/stpeace/article/details/46461167
聊聊C++临时对象的析构时间点
switch (reg) {
case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR:
return 1;
case TAS5086_INPUT_MUX:
case TAS5086_PWM_OUTPUT_MUX:
return 4;
}
可以用上面的办法,少写一些case语句。
https://www.zhihu.com/question/300975864
为什么很多程序员不用 switch,而是大量的 if…else if …?
对于要求严格位宽的场合,应用程序可以使用uint8_t,uint16_t,uint32_t来获得移植时的一致性。它的头文件是inttypes.h。
https://blog.csdn.net/qq_38231713/category_10001159.html
一个C++11并发与多线程的专栏
在C语言的函数定义上,我们通常用的函数定义方式为ANSI C的函数定义方式。但是在C语言之父创立C语言之时,函数的定义形式并非现在我们所见到的形式。
这种风格被称为K&R风格,多见于一些历史悠久的项目或者老的书籍中。出于兼容性考虑,现代的C编译器仍然支持K&R风格。
记得大学学C语言,用的是谭浩强的书。当时,授课老师看不上谭的书,于是另外推荐了一本,那本书更古老,用的就是所谓的K&R风格。。。但在实际工作中,从来没见过K&R风格的代码。。。
详见:
http://blog.chinaunix.net/uid-7426920-id-2627743.html
ANSI和K&R两种函数定义风格
SFINAE:Substitution failure is not an error
template <
typename scalar_t,
typename index_t,
typename std::enable_if_t<!std::is_same_v<c10::Half, scalar_t> && !std::is_same_v<c10::BFloat16, scalar_t>>* =
nullptr>
__device__ __forceinline__ void fastSpecializedAtomicAdd(
scalar_t* tensor,
index_t index,
const index_t numel,
scalar_t value)
第三个模板参数用于在编译时对模板参数进行约束。它的作用是限制模板参数scalar_t的类型,确保它不能是c10::Half或c10::BFloat16。
https://en.cppreference.com/w/cpp/language/sfinae
官方文档
https://zhuanlan.zhihu.com/p/21314708
C++模板进阶指南:SFINAE
CRTP:Curiously Recurring Template Pattern是C++模板编程中的一种惯用法。基本特征表现为:基类是一个模板类;派生类在继承该基类时,将派生类自身作为模板参数传递给基类。
template <typename ChildType> struct VectorBase {
ChildType &underlying() { return static_cast<ChildType &>(*this); }
inline ChildType &operator+=(const ChildType &rhs) {
this->underlying() = this->underlying() + rhs;
return this->underlying();
}
};
struct Vec3f : public VectorBase<Vec3f> {
float x{}, y{}, z{};
Vec3f() = default;
Vec3f(float x, float y, float z) : x(x), y(y), z(z) {}
};
inline Vec3f operator+(const Vec3f &lhs, const Vec3f &rhs) {
Vec3f result;
result.x = lhs.x + rhs.x;
result.y = lhs.y + rhs.y;
result.z = lhs.z + rhs.z;
return result;
}
本质上CRTP中的多个派生类并不是同一个基类,只是共用一部分模板代码而已。它省去了动态绑定、查询虚函数表带来的开销。
auto vec = make_index_vector(std::make_index_sequence<10>());
for(auto i : vec) {std::cout << i << ' ';}
std::cout << std::endl;
std::iota(vec.begin(), vec.end(), 999);
std::copy(vec.begin(), vec.end(), std::ostream_iterator<int>(std::cout, " "));
std::cout << std::endl;
std::for_each(std::begin(vec),std::end(vec),[](int n){std::cout<<n<<" ";});
std::cout << std::endl;
两者都是动态分配内存。
主要的不同:malloc不初始化分配的内存,已分配的内存中可以是任意的值。calloc初始化已分配的内存为0。
次要的不同:calloc返回的是一个数组,而malloc返回的是一个对象。
常用的malloc实现主要有:
在多线程环境使用tcmalloc和jemalloc效果非常明显。
当线程数量固定,不会频繁创建退出的时候, 可以使用jemalloc;反之使用tcmalloc可能是更好的选择。
malloc是用户层面而不是系统层面的东西,系统调用里并没有malloc。
https://www.cnblogs.com/cthon/p/10563946.html
内存优化总结:ptmalloc、tcmalloc和jemalloc
std::vector<int> return_vector(void)
{
std::vector<int> tmp {1,2,3,4,5};
return tmp;
}
std::vector<int> rval_ref = return_vector();
如果按照一般的返回值传递的规则,tmp作为局部变量是传不到外面去的,因此返回的时候,会在外部创建一个同类型的变量,并将tmp的内容复制过去。从而带来了一次复制的开销。
RVO(Return Value Optimization)就是用来优化这种情况的。上述代码执行RVO之后,就等价于:
void return_vector(std::vector<int>& tmp)
{
tmp = std::vector<int>({1,2,3,4,5});
}
std::vector<int> rval_ref;
return_vector(rval_ref);
https://www.zhihu.com/question/27000013
什么时候应当依靠返回值优化(RVO)?
class Base
{
public:
void something(Base& b){}
};
int main()
{
Base b;
b.something(Base());
return 0;
}
上面的代码在编译时,会出现如下错误信息:
abc.cpp:12:20: error: no matching function for call to ‘Base::something(Base)’
abc.cpp:12:20: note: candidate is:
abc.cpp:6:7: note: void Base::something(Base&)
abc.cpp:6:7: note: no known conversion for argument 1 from ‘Base’ to ‘Base&’
这是由于Base()
生成的是临时变量,将之赋值给一个non-const的引用是不行的。
解决方法是
void something(const Base& b){}
可以参看下文:
http://stackoverflow.com/questions/20247525/about-c-conversion-no-known-conversion-for-argument-1-from-some-class-to
有些类库出于兼容性的考虑,仍然保留了对旧函数的支持。但是继续使用这些函数,显然不是作者的初衷。因此,有必要在编译时,给出废弃的提示。
近日浏览cocos2d-x v3的代码,发现可以这样做:
宏定义:
#if defined(__GNUC__) && ((__GNUC__ >= 4) || ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)))
#define CC_DEPRECATED_ATTRIBUTE __attribute__((deprecated))
#elif _MSC_VER >= 1400 //vs 2005 or higher
#define CC_DEPRECATED_ATTRIBUTE __declspec(deprecated)
#else
#define CC_DEPRECATED_ATTRIBUTE
#endif
宏使用:
CC_DEPRECATED_ATTRIBUTE static TextureCache * getInstance();
您的打赏,是对我的鼓励