C/C++指针与数组(一)
预备知识
1、数据的存储

2、基本内建类型
1)类型的大小
C++ offers a flexible standard with some guaranteed minimum sizes, which it takes from C:
- A short integer is at least 16 bits wide.
- An int integer is at least as big as short.
- A long integer is at least 32 bits wide and at least as big as int.
- A long long integer is at least 64 bits wide and at least as big as long.
Many systems currently use the minimum guarantee, making short 16 bits and long 32 bits.This still leaves several choices open for int. It could be 16, 24, or 32 bits in width and meet the standard. It could even be 64 bits, providing that long and long long are at least that wide.
参考:C++ Primer Plus Sixth Edition
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{cout << "sizeof(char)=" << sizeof(char) << endl;cout << "sizeof(short)=" << sizeof(short) << endl;cout << "sizeof(int)=" << sizeof(int) << endl;cout << "sizeof(float)=" << sizeof(float) << endl;cout << "sizeof(long)=" << sizeof(long) << endl;cout << "sizeof(long long)=" << sizeof(long long) << endl;cout << "sizeof(double)=" << sizeof(double) << endl;return 0;
}

2)类型代表的数据的大小
#include<iostream>
#include <climits> // use limits.h for older systems
using namespace std;
int main(int argc, char *argv[])
{char n_char = CHAR_MAX;short n_short = SHRT_MAX; // symbols defined in climits fileint n_int = INT_MAX; // initialize n_int to max int valuefloat n_float = FLT_MAX;long n_long = LONG_MAX;long long n_llong = LLONG_MAX;double n_double = DBL_MAX;cout << "Value Ranges:\tMinimum\t\t\tMaximum" << endl;cout << "char:\t\t" << CHAR_MIN << "\t\t\t" << CHAR_MAX << endl;cout << "short:\t\t" << SHRT_MIN << "\t\t\t" << n_short << endl;cout << "int:\t\t" << INT_MIN << "\t\t" << n_int << endl;cout << "float:\t\t" << FLT_MIN << "\t\t" << n_float << endl;cout << "long:\t\t" << LONG_MIN << "\t\t" << n_long << endl;cout << "long long:\t" << LLONG_MIN << "\t" <<n_llong << endl;cout << "double:\t\t" << DBL_MIN << "\t\t" << n_double << endl;return 0;
}

一、指向单一对象的指针和该指针的加减算术运算
#include<iostream>
#include <climits> // use limits.h for older systems
using namespace std;
int main(int argc, char *argv[])
{char chr;short sht = 1; // symbols defined in climits fileint in = 2; // initialize n_int to max int valuefloat fl = 3.0f;long lo = 4l;long long lolo = 5ll;double dou = 6.0;char* pChr = &chr;short* pSht = &sht;int* pIn = ∈float* pFl = &fl;long* pLo = &lo;long long* pLolo = &lolo;double* pDou = &dou;cout << "char类型指针及其算术运算:\t" << (void*)(pChr - 1) << '\t' << (void*)(pChr) << '\t' << (void*)(pChr + 1) << endl;cout << "short类型指针及其算术运算:\t" << pSht - 1 << '\t' << pSht << '\t' << pSht + 1 << endl;cout << "int类型指针及其算术运算:\t" << pIn - 1 << '\t' << pIn << '\t' << pIn + 1 << endl;cout << "float类型指针及其算术运算:\t" << pFl - 1 << '\t' << pFl << '\t' << pFl + 1 << endl;cout << "long类型指针及其算术运算:\t" << pLo - 1 << '\t' << pLo << '\t' << pLo + 1 << endl;cout << "longlong类型指针及其算术运算:\t" << pLolo - 1 << '\t' << pLolo << '\t' << pLolo + 1 << endl;cout << "double类型指针及其算术运算:\t" << pDou - 1 << '\t' << pDou << '\t' << pDou + 1 << endl;return 0;
}

实际上,由于指针退化,下面所说的各种类型的指针还可以指向对应类型的数组,但此处暂时认为其指向单一对象的指针。由于内存地址在计算机中用十六进制表示,注意十六进制与十进制算术运算的异同。
pChr的类型为char*,即pChr指向一个char类型的对象,而这个对象占1个字节,所以对它-1或者+1,指针只向前或者向后移动1个字节。
pSht的类型为short*,即pSht指向一个short类型的对象,而这个对象占2个字节,所以对它-1或者+1,指针只向前或者向后移动2个字节。
pIn的类型为int*,即pIn指向一个int类型的对象,而这个对象占4个字节,所以对它-1或者+1,指针只向前或者向后移动4个字节。
pFl的类型为float*,即pFl指向一个char类型的对象,而这个对象也占4个字节,所以对它-1或者+1,指针只向前或者向后移动4个字节。
pLo的类型为long*,即pLo指向一个long类型的对象,而这个对象也占4个字节,所以对它-1或者+1,指针只向前或者向后移动4个字节。
pLolo的类型为long long*,即pLolo指向一个long long类型的对象,而这个对象占8个字节,所以对它-1或者+1,指针只向前或者向后移动8个字节。
pDou的类型为double*,即pDou指向一个double类型的对象,而这个对象也占8个字节,所以对它-1或者+1,指针只向前或者向后移动8个字节。
二、指向对象数组的指针和该指针的加减算术运算
1、指向一维数组的指针和该指针的加减算术运算
#include<iostream>
#include <climits>
using namespace std;
int main(int argc, char *argv[])
{char chr[5] = { 'a', 'b', 'c', 'd', 'e' };short sht[5] = { 1, 2, 3, 4, 5 };int in[5] = { 1, 2, 3, 4, 5 };float fl[5] = { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f };long lo[5] = { 1l, 2l, 3l, 4l, 5l, };long long lolo[5] = { 1ll, 2ll, 3ll, 4ll, 5ll };double dou[5] = { 1.0, 2.0, 3.0, 4.0, 5.0 };char(*pChrArr)[5] = &chr; //声明并定义char(*)[5]类型指针,此指针指向该整个数组short(*pShtArr)[5] = &sht; //声明并定义short(*)[5]类型指针,此指针指向该整个数组int(*pInArr)[5] = ∈ //声明并定义int(*)[5]类型指针,此指针指向该整个数组float(*pFlArr)[5] = &fl; //声明并定义float(*)[5]类型指针,此指针指向该整个数组long(*pLoArr)[5] = &lo; //声明并定义long(*)[5]类型指针,此指针指向该整个数组long long(*pLoloArr)[5] = &lolo; //声明并定义longlong(*)[5]类型指针,此指针指向该整个数组double(*pDouArr)[5] = &dou; //声明并定义double(*)[5]类型指针,此指针指向该整个数组cout << "char(*)[5]类型指针及其算术运算:\t\t" << (void*)(pChrArr - 1) << '\t' << (void*)(pChrArr) << '\t' << (void*)(pChrArr + 1) << endl;cout << "short(*)[5]类型指针及其算术运算:\t" << pShtArr - 1 << '\t' << pShtArr << '\t' << pShtArr + 1 << endl;cout << "int(*)[5]类型指针及其算术运算:\t\t" << pInArr - 1 << '\t' << pInArr << '\t' << pInArr + 1 << endl;cout << "float(*)[5]类型指针及其算术运算:\t" << pFlArr - 1 << '\t' << pFlArr << '\t' << pFlArr + 1 << endl;cout << "long(*)[5]类型指针及其算术运算:\t\t" << pLoArr - 1 << '\t' << pLoArr << '\t' << pLoArr + 1 << endl;cout << "longlong(*)[5]类型指针及其算术运算:\t" << pLoloArr - 1 << '\t' << pLoloArr << '\t' << pLoloArr + 1 << endl;cout << "double(*)[5]类型指针及其算术运算:\t" << pDouArr - 1 << '\t' << pDouArr << '\t' << pDouArr + 1 << endl;return 0;
}

指向一维数组的指针的声明及定义格式:typename (*pointer) [n] = &arrayname; 即指针pointer指向一个含有n个元素的typename类型的一维数组,该数组名称为arrayname。
指向一维数组的指针的类型为typename (*) [n]pChrArr的类型为char(*)[5],即 pChrArr指向一个包含5个char类型对象的数组,这个单一对象占1个字节,但是该数组占1*5个字节,所以对它-1或者+1,指针只向前或者向后移动5个字节。
pShtrArr的类型为short(*)[5],即pShtArr指向一个包含5个short类型对象的数组,这个单一对象占2个字节,但是该数组占2*5个字节,所以对它-1或者+1,指针只向前或者向后移动10个字节。
pInArr的类型为int(*)[5],即pInArr指向一个包含5个int类型对象的数组,这个单一对象占4个字节,但是该数组占4*5个字节,所以对它-1或者+1,指针只向前或者向后移动20个字节。
pFlrArr的类型为float(*)[5],即pFlArr指向一个包含5个char类型对象的数组,这个单一对象也占4个字节,但是该数组占4*5个字节,所以对它-1或者+1,指针只向前或者向后移动20个字节。
pLoArr的类型为long(*)[5],即pLoArr指向一个包含5个long类型对象的数组,这个单一对象占4个字节,但是该数组占4*5个字节,所以对它-1或者+1,指针只向前或者向后移动20个字节。
pLoloArr的类型为long long(*)[5],即pLoloArr指向一个包含5个long long类型对象的数组,这个单一对象占8个字节,但是该数组占8*5个字节,所以对它-1或者+1,指针只向前或者向后移动40个字节。
pDouArr的类型为double(*)[5],即pDouArr指向一个包含5个double类型对象的数组,这个单一对象占8个字节,但是该数组占8*5个字节,所以对它-1或者+1,指针只向前或者向后移动40个字节。
2、指向二维数组的指针和该指针的加减算术运算
#include<iostream>
#include <climits>
using namespace std;
int main(int argc, char *argv[])
{char chr[5][5] = { { 'a', 'b', 'c', 'd', 'e' },{ 'f', 'g', 'h', 'i', 'j' },{},{},{}} //未初始化的元素置空short sht[5][5] = { { 1, 2, 3, 4, 5 },{ 6, 7, 8, 9, 10 },{},{},{}}; //未初始化的元素置0int in[5][5] = { { 1, 2, 3, 4, 5 },{ 6, 7, 8, 9, 10 },{},{},{}}; //未初始化的元素置0float fl[5][5] = { { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f },{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f },{},{},{}}; //未初始化的元素置0long lo[5][5] = { { 1l, 2l, 3l, 4l, 5l, },{ 6l, 7l, 8l, 8l, 10l },{},{},{}}; //未初始化的元素置0long long lolo[5][5] = { { 1ll, 2ll, 3ll, 4ll, 5ll },{ 6ll, 7ll, 8ll, 9ll, 10ll },{},{},{}}; //未初始化的元素置0double dou[5][5] = { { 1.0, 2.0, 3.0, 4.0, 5.0 },{ 6.0, 7.0, 8.0, 9.0, 10.0 },{},{},{}}; //未初始化的元素置0cout << "chr[4][4]:\t" << chr[4][4]<< endl;cout << "sht[4][4]:\t" << sht[4][4] << endl;cout << "in[4][4]:\t" << in[4][4] << endl;cout << "fl[4][4]:\t" << fl[4][4] << endl;cout << "lo[4][4]:\t" << lo[4][4] << endl;cout << "lolo[4][4]:\t" << lolo[4][4] << endl;cout << "dou[4][4]:\t" << dou[4][4] << endl << endl;char(*pChrArr)[5][5] = &chr; //声明并定义char(*)[5][5]类型指针,此指针指向该整个二维数组short(*pShtArr)[5][5] = &sht; //声明并定义short(*)[5][5]类型指针,此指针指向该整个二维数组int(*pInArr)[5][5] = ∈ //声明并定义int(*)[5][5]类型指针,此指针指向该整个二维数组float(*pFlArr)[5][5] = &fl; //声明并定义float(*)[5][5]类型指针,此指针指向该整个二维数组long(*pLoArr)[5][5] = &lo; //声明并定义long(*)[5][5]类型指针,此指针指向该整个二维数组long long(*pLoloArr)[5][5] = &lolo; //声明并定义longlong(*)[5][5]类型指针,此指针指向该整个二维数组double(*pDouArr)[5][5] = &dou; //声明并定义double(*)[5][5]类型指针,此指针指向该整个二维数组cout << "char(*)[5][5]类型指针及其算术运算:\t" << (void*)(pChrArr - 1) << '\t' << (void*)(pChrArr) << '\t' << (void*)(pChrArr + 1) << endl;cout << "short(*)[5][5]类型指针及其算术运算:\t" << pShtArr - 1 << '\t' << pShtArr << '\t' << pShtArr + 1 << endl;cout << "int(*)[5][5]类型指针及其算术运算:\t" << pInArr - 1 << '\t' << pInArr << '\t' << pInArr + 1 << endl;cout << "float(*)[5][5]类型指针及其算术运算:\t" << pFlArr - 1 << '\t' << pFlArr << '\t' << pFlArr + 1 << endl;cout << "long(*)[5][5]类型指针及其算术运算:\t" << pLoArr - 1 << '\t' << pLoArr << '\t' << pLoArr + 1 << endl;cout << "longlong(*)[5][5]类型指针及其算术运算:\t" << pLoloArr - 1 << '\t' << pLoloArr << '\t' << pLoloArr + 1 << endl;cout << "double(*)[5][5]类型指针及其算术运算:\t" << pDouArr - 1 << '\t' << pDouArr << '\t' << pDouArr + 1 << endl;return 0;
}
指向二维数组的指针的声明及定义格式:typename (*pointer) [i][j] = &arrayname; 即指针pointer指向一个含有i个一维数组,并且每个一维数组含有j个的typename类型对象,共i*j个元素。该数组名称为arrayname。
指向二维数组的指针的类型为typename (*)\ [i][j]pChArr的类型为char(*)[5][5],即 pChArr指向含有5个一维数组,并且每个一维数组都含有5个char类型单一对象(共25个元素),这个单一对象占1个字节,但是该二维数组占1*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动25个字节。
pShtArr的类型为short(*)[5][5],即pShtArr指向含有5个一维数组,并且每个一维数组都含有5个short类型单一对象(共25个元素),这个单一对象占2个字节,但是该二维数组占2*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动50个字节。
pInArr的类型为int(*)[5][5],即pInArr指向含有5个一维数组,并且每个一维数组都含有5个int类型单一对象(共25个元素),这个单一对象占4个字节,但是该二维数组占4*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动100个字节。
pFlArr的类型为float(*)[5][5],即pFlArr指向含有5个一维数组,并且每个一维数组都含有5个float类型单一对象(共25个元素),这个单一对象也占4个字节,但是该二维数组占4*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动100个字节。
pLoArr的类型为long(*)[5][5],即pLoArr指向含有5个一维数组,并且每个一维数组都含有5个long类型单一对象(共25个元素),这个单一对象占4个字节,但是该二维数组占4*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动100个字节。
pLoloArr的类型为long long(*)[5][5],即pLoloArr指向含有5个一维数组,并且每个一维数组都含有5个long long类型单一对象(共25个元素),这个单一对象占8个字节,但是该二维数组占8*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动200个字节。
pDouArr的类型为double(*)[5][5],即pDouArr指向含有5个一维数组,并且每个一维数组都含有5个double类型单一对象(共25个元素),这个单一对象占8个字节,但是该二维数组占8*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动200个字节。
3、指向三维数组的指针和该指针的加减算术运算
#include<iostream>
#include <climits>
using namespace std;
int main(int argc, char *argv[])
{char chr[5][5][5] = { { { 'a', 'b', 'c', 'd', 'e' },{ 'f', 'g', 'h', 'i', 'j' },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0short sht[5][5][5] = { { { 1, 2, 3, 4, 5 },{ 6, 7, 8, 9, 10 },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0int in[5][5][5] = { { { 1, 2, 3, 4, 5 },{ 6, 7, 8, 9, 10 },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0float fl[5][5][5] = { { { 1.0f, 2.0f, 3.0f, 4.0f, 5.0f },{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0long lo[5][5][5] = { { { 1l, 2l, 3l, 4l, 5l, },{ 6l, 7l, 8l, 8l, 10l },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0long long lolo[5][5][5] = { { { 1ll, 2ll, 3ll, 4ll, 5ll },{ 6ll, 7ll, 8ll, 9ll, 10ll },{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} },{ {},{},{},{},{} }}; //未初始化的元素置0double dou[5][5][5] = { { { 1.0, 2.0, 3.0, 4.0, 5.0 },{ 6.0, 7.0, 8.0, 9.0, 10.0 },{},{},{} },{ {}, {}, {}, {}, {} },{ {}, {}, {}, {}, {} },{ {}, {}, {}, {}, {} },{ {}, {}, {}, {}, {} }}; //未初始化的元素置0char(*pChrArr)[5][5][5] = &chr; //声明并定义char(*)[5][5]类型指针,此指针指向该整个二维数组short(*pShtArr)[5][5][5] = &sht; //声明并定义short(*)[5][5]类型指针,此指针指向该整个二维数组int(*pInArr)[5][5][5] = ∈ //声明并定义int(*)[5][5]类型指针,此指针指向该整个二维数组float(*pFlArr)[5][5][5] = &fl; //声明并定义float(*)[5][5]类型指针,此指针指向该整个二维数组long(*pLoArr)[5][5][5] = &lo; //声明并定义long(*)[5][5]类型指针,此指针指向该整个二维数组long long(*pLoloArr)[5][5][5] = &lolo; //声明并定义longlong(*)[5][5]类型指针,此指针指向该整个二维数组double(*pDouArr)[5][5][5] = &dou; //声明并定义double(*)[5][5]类型指针,此指针指向该整个二维数组cout << "char(*)[5][5][5]类型指针及其算术运算:\t\t" << (void*)(pChrArr - 1) << '\t' << (void*)(pChrArr) << '\t' << (void*)(pChrArr + 1) << endl;cout << "short(*)[5][5][5]类型指针及其算术运算:\t\t" << pShtArr - 1 << '\t' << pShtArr << '\t' << pShtArr + 1 << endl;cout << "int(*)[5][5][5]类型指针及其算术运算:\t\t" << pInArr - 1 << '\t' << pInArr << '\t' << pInArr + 1 << endl;cout << "float(*)[5][5][5]类型指针及其算术运算:\t\t" << pFlArr - 1 << '\t' << pFlArr << '\t' << pFlArr + 1 << endl;cout << "long(*)[5][5][5]类型指针及其算术运算:\t\t" << pLoArr - 1 << '\t' << pLoArr << '\t' << pLoArr + 1 << endl;cout << "longlong(*)[5][5][5]类型指针及其算术运算:\t" << pLoloArr - 1 << '\t' << pLoloArr << '\t' << pLoloArr + 1 << endl;cout << "double(*)[5][5][5]类型指针及其算术运算:\t\t" << pDouArr - 1 << '\t' << pDouArr << '\t' << pDouArr + 1 << endl;return 0;
}

指向三维数组的指针的声明及定义格式:typename (*pointer)\ [i][j][k] = &arrayname; 即指针pointer指向一个含有i个二维数组,并且这i个二维数组每个都含有j个一维数组,并且这j个一维数组中每个都含有k个单一类型的的typename类型对象,共i*j*k个元素。该数组名称为arrayname。
指向三维数组的指针的类型为typename (*)\ [i][j][k]pChrArr的类型为char(*)[5][5][5],即 pChrArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个char类型单一对象,共125个元素,这个单一对象占1个字节,但是该三维数组占1*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动125个字节。
pShtArr的类型为short(*)[5][5][5],即pShtArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个short类型单一对象,共125个元素,这个单一对象占2个字节,但是该三维数组占2*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动250个字节。
pInArr的类型为int(*)[5][5][5],即pInArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个int类型单一对象,共125个元素,这个单一对象占4个字节,但是该三维数组占4*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动500个字节。
pFlArr的类型为float(*)[5][5][5],即pFlArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个float类型单一对象,共125个元素,这个单一对象占4个字节,但是该三维数组占4*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动500个字节。
pLoArr的类型为long(*)[5][5][5],即pLoArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个long类型单一对象,共125个元素,这个单一对象占4个字节,但是该三维数组占4*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动500个字节。
pLoloArr的类型为long long(*)[5][5][5],即pLoloArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个long long类型单一对象,共125个元素,这个单一对象占8个字节,但是该三维数组占8*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动1000个字节。
pDouArr的类型为double(*)[5][5][5],即pDouArr指向含有5个二维数组,并且每个二维数组都含有5个一维数组,并且每个一维数组中都含有5个double类型单一对象,共125个元素,这个单一对象占8个字节,但是该三维数组占8*5*5*5个字节,所以对它-1或者+1,指针只向前或者向后移动1000个字节。
4、指向n维数组的指针和该指针的加减算术运算
类推地,指向n维数组的指针的声明及定义格式:typename(*pointer) [a(0)][a(1)][a(2)]…[a(n)](共有n个[],每个[]中都要有数字) = &arrayname; 即指针pointer指向一个含有a(0)个n-1维数组,并且这a(0)个n-1维数组中每个都含有a(1)个n-2维数组,并且这a(1)个n-2维数组中每个都含有a(2)个n-3维数组…并且这a(n-1)个一维数组中每个都含有a(n)个单一类型的typename类型对象,共a(0)*a(1)*a(2)…*a(n)个元素。该数组名称为arrayname。
指向n维数组的指针的类型为typename(*)[a(0)][a(1)][a(2)]…[a(n)]pTypenameArr的类型为typename(*)[a(0)][a(1)][a(2)]…[a(n)],即 pTypenameArr指向一个含有a(0)个n-1维数组,并且这a(0)个n-1维数组中每个都含有a(1)个n-2维数组,并且这a(1)个n-2维数组中每个都含有a(2)个n-3维数组…并且这a(n-1)个一维数组中每个都含有typename类型单一对象,共a(0)*a(1)*a(2)…*a(n)个元素。这个单一对象占sizeof(typename)个字节,但是该n维数组占sizeof(typename)*a(0)*a(1)*a(2)…*a(n)个字节,所以对它-1或者+1,指针只向前或者向后移动sizeof(typename)*a(0)*a(1)*a(2)…*a(n)个字节。
参考
《C语言程序设计》(第3版)(谭浩强,清华大学出版社)
《C++程序设计教程》(第3版)(王珊珊,臧洌,张志航,机械工业出版社)
《C++ Primer Plus》(Six Edition)(Stephen Prata)
《C和指针》(Kenneth A. Reek)
广大的CSDN社友们的文章
相关文章:
C/C++指针与数组(一)
预备知识 1、数据的存储 2、基本内建类型 1)类型的大小 C offers a flexible standard with some guaranteed minimum sizes, which it takes from C: A short integer is at least 16 bits wide.An int integer is at least as big as short.A long integer is a…...
Android使用移动智能终端补充设备标识获取OAID
官网http://www.msa-alliance.cn/col.jsp?id120首先到官网注册账号,申请下载相关sdk和授权证书2.把 oaid_sdk_x.x.x.aar 拷贝到项目的 libs 目录,并设置依赖,其中x.x.x 代表版本号3.supplierconfig.json 拷贝到项目 assets 目录下࿰…...
极目智能与锐算科技达成战略合作,4D毫米波成像雷达助力智能驾驶落地
近日,智能驾驶方案提供商武汉极目智能技术有限公司(以下简称“极目智能”)宣布与毫米波成像雷达公司锐算(上海)科技有限公司(以下简称“锐算科技”)达成战略合作,双方将合作开发基于…...
OpenCV基础(一)
1.认识图像(彩色图中每一个像素点都包含三个颜色通道RGB,数值范围为0~255,0代表黑色,255代表白色) import cv2 #opencv 读取的格式为BGRimg cv2.imread(cat.png) #读取图像 cv2.imshow(cat, img) #显示图像img&#x…...
pinia 的使用(笔记)
文章目录1. Pinia 与 Vuex 的区别2. pinia 安装与搭建3. pinia 的使用3.1 基本使用3.2 订阅状态3.3 订阅 actions1. Pinia 与 Vuex 的区别 Pinia 是 Vue 的状态管理库,相当于 Vuex 取消了 mutations,取消了 Module 模块化命名空间现在的 pinia 采用的是…...
DolphinDB 机器学习在物联网行业的应用:实时数据异常率预警
数据异常率预警在工业安全生产中是一项重要工作,对于监控生产过程的稳定性,保障生产数据的有效性,维护生产设备的可靠性具有重要意义。随着大数据技术在生产领域的深入应用,基于机器学习的智能预警已经成为各大生产企业进行生产数…...
新建vite+vue3+ts项目,以及解决过程中遇到的问题
目录 一、新建vitevue3ts项目 二、解决过程中遇到的问题 解决报错:Module ‘“xx.vue“‘ has no default export. 解决报错:Error [ERR_MODULE_NOT_FOUND]: Cannot find package ‘uuid’ imported from xxx的解决 解决报错:[plugin:vi…...
pyppeteer中文文档
目录 1.命令 2.环境变量 3.Launcher(启动器) 4.浏览器类 5.浏览器上下文类 6.页面类 7.Worker 类 8.键盘类 9.鼠标类 10.Tracing类 11.对话框类 12.控制台消息类 13.Frame 类 14.执行上下文类 15.JSHandle 类 16.元素句柄类…...
(二十四)操作系统-吸烟者问题
文章目录一、问题描述二、问题分析1.关系分析2.整理思路3.设置信号量三、实现四、总结一、问题描述 假设一个系统有三个抽烟者进程和一个供应者进程。每个抽烟者不停地卷烟并抽掉它,但是要卷起并抽掉一支烟,抽烟者需要…...
ReentranLock(可重入锁)
一、ReentranLock ReentranLock属于JUC并发工具包下的类,相当于 synchronized具备如下特点 ● 可中断 ● 可以设置超时时间 ● 可以设置为公平锁(防止线程出现饥饿的情况) ● 支持多个条件变量 与 synchronized一样,都支持可重…...
Kafka 入门 (一)
Kafka 入门(一) Apache Kafka起源于LinkedIn,后来于2011年成为开源Apache项目,然后于2012年成为First-class Apache项目。Kafka是用Scala和Java编写的。 Apache Kafka是基于发布订阅的容错消息系统。 它是快速,可扩展…...
linux内核开发入门二(内核KO模块介绍、开发流程以及注意事项)
linux内核开发入门二(内核KO模块介绍、开发流程以及注意事项) 一、什么是内核模块 内核模块:ko模块(Kernel Object Module)是Linux内核中的可加载模块,它可以动态地向内核添加功能。在运行时,可…...
设计模式(十七)----行为型模式之模板方法模式
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为&…...
【嵌入式Linux内核驱动】01_内核模块
内核模块 宏内核&微内核 微内核就是内核中的一部分功能放到应用层 内核小,精简,可扩展性好,安全性好 相互之间通信损耗多 内核模块 Linux是宏内核操作系统的典型代表,所有内核功能都整体编译到一起,优点是效…...
Spring——数据源对象管理和Spring加载properties文件
前面一直都是在管理自己内部创建的对象,这个是管理外部的对象。 这里先使用阿里巴巴的druid来演示。需要在pom.xml中添加如下的依赖 <dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.1…...
Zeek安装、使用与压力测试
Zeek安装与压力测试Zeek安装、简单使用与压力测试环境Zeek安装zeek简单运行安装PF_RING修改Zeek配置文件,使用PF_RING,实现集群流量压力测试查看zeek日志Zeek安装、简单使用与压力测试 科研需要,涉及到Zeek的安装、使用和重放流量压力测试评…...
【javaEE初阶】第三节.多线程 (进阶篇 ) 死锁
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、"死锁"出现的典型场景二、产生 "死锁" 的必要条件 三、解决 "死锁" 问题的办法 总结前言 今天对于多线程进阶的学习&#…...
基于密集连接的轻量级卷积神经网络,用于使用边云架构的露天煤矿服务识别
遥感是快速检测非法采矿行为的重要技术工具。由于露天煤矿的复杂性,目前关于露天煤矿自动开采的研究较少。基于卷积神经网络和Dense Block,我们提出了一种用于从Sentinel-2遥感图像中提取露天煤矿区域的轻量级密集连接网络-AD-Net,并构建了三…...
无刷高速风筒方案介绍--【PCBA方案】
疫情三年过去,春节后,一个新的开始,大家满怀希望畅谈今年好气象。 三年来一波一波的封城、隔离、核酸,经济压抑到了无以复加的地步,也导致了诸多社会问题的出现。消费力被磨平,人们小心翼翼的生活。 常跟…...
花括号展开II[栈模拟dfs]
栈模拟dfs前言一、花括号展开II二、栈模拟dfs总结参考资料前言 递归调用,代码非常的简洁。但是可以通过显式栈来模拟栈中的内容,锻炼自己的代码能力,清楚知道栈帧中需要的内容。 一、花括号展开II 二、栈模拟dfs 每碰到一个左括号…...
通义千问1.5-1.8B-Chat-GPTQ-Int4 Java开发集成:SpringBoot项目实战指南
通义千问1.5-1.8B-Chat-GPTQ-Int4 Java开发集成:SpringBoot项目实战指南 最近在帮一个朋友做项目,他们想在自己的Java应用里加个智能对话功能,看中了通义千问1.5-1.8B-Chat-GPTQ-Int4这个模型。这模型挺有意思的,体积小但能力不弱…...
告别字符串截取!用正则表达式re模块精准提取HTML表格数据的避坑指南
告别字符串截取!用正则表达式re模块精准提取HTML表格数据的避坑指南 在数据抓取的世界里,HTML解析就像一场永无止境的猫鼠游戏。每当开发者费尽心思用字符串截取搞定一个网站,前端工程师稍微调整下标签结构,整个爬虫就崩溃了。这种…...
【PyO3/Rust-Python测试权威框架】:Rust生态下Python扩展的零信任CI流水线设计
第一章:Python 扩展模块测试Python 扩展模块(如用 C/C、Rust 或 Cython 编写的模块)在提升性能的同时,也引入了跨语言交互的复杂性。对其开展系统性测试,是保障功能正确性、内存安全性和 ABI 兼容性的关键环节。测试环…...
经典蓝牙Sniff Mode的功耗优化策略与应用场景解析
1. 经典蓝牙Sniff Mode基础原理 蓝牙设备在保持连接状态时,即使没有数据传输也会定期交换POLL-NULL数据包来维持链路。这种机制虽然保证了连接稳定性,却带来了不必要的功耗开销。Sniff Mode就像给蓝牙设备装了个"智能闹钟"——平时让设备睡觉&…...
如何在Python中正确调用DeepSeek-Reasoner获取思考过程(附完整代码示例)
深度解析:Python调用DeepSeek-Reasoner获取思维链的工程实践 当开发者需要构建具备复杂推理能力的AI应用时,获取模型完整的思考过程(Reasoning Content)往往比最终答案更有价值。DeepSeek-Reasoner作为专为逻辑推理优化的模型&…...
YOLOv8模型训练避坑指南:GTX16系列显卡兼容性问题解决方案
GTX16系列显卡用户必读:YOLOv8模型训练全流程避坑手册 当你在GTX16系列显卡上运行YOLOv8训练脚本时,是否遇到过这样的场景:训练过程看似正常,但最终输出的P(精确率)、R(召回率)、mAP…...
YOLOv8实战:Anchor-Free与Anchor-Based到底怎么选?附完整对比实验代码
YOLOv8技术选型指南:Anchor-Free与Anchor-Based深度对比与实战决策 在目标检测领域的技术选型过程中,工程师们常常面临一个关键抉择:是采用传统的Anchor-Based方法,还是转向新兴的Anchor-Free架构?这个看似简单的选择背…...
前端HTML精讲01:别再乱 div 一把抓,吃透语义化标签才是进阶第一步
前端HTML精讲01:别再乱 div 一把抓,吃透语义化标签才是进阶第一步 文章目录前端HTML精讲01:别再乱 div 一把抓,吃透语义化标签才是进阶第一步一、什么是HTML语义化?二、为什么要做HTML语义化?1\. 提升代码可…...
4个突破性功能步骤:全面兼容让Switch手柄实现跨平台操控自由
4个突破性功能步骤:全面兼容让Switch手柄实现跨平台操控自由 【免费下载链接】BetterJoy Allows the Nintendo Switch Pro Controller, Joycons and SNES controller to be used with CEMU, Citra, Dolphin, Yuzu and as generic XInput 项目地址: https://gitcod…...
保姆级教程:手把手教你用万物识别镜像搭建智能图片识别工具
保姆级教程:手把手教你用万物识别镜像搭建智能图片识别工具 1. 准备工作与环境配置 1.1 镜像基本信息介绍 万物识别-中文-通用领域镜像是一个基于cv_resnest101_general_recognition算法构建的预装环境,能够识别超过5万种日常物体。它封装了完整的推理…...
