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.Mnist分类任务 网络基本构建与训练方法,常用函数解析 torch.nn.functional模块 nn.Module模块 学习方法:边用边查,多打印,duogua 使用jupyter的优点,可以打印出每一个步骤。 2.读取数据集 自动下载 %matplotl…...

FCN网络(Fully Convolutional Networks)
首个端到端的针对像素级预测的全卷积网络 原理:将图片进行多次卷积下采样得到chanel为21的特征层,再经过上采样得到和原图一样大的图片,最后经过softmax得到类别概率值 将全连接层全部变成卷积层:通常的图像分类网络最后几层是全…...

随想录二刷Day15——二叉树
文章目录二叉树2. 递归遍历二叉树3. 二叉树的迭代遍历4. 二叉树的统一迭代法二叉树 2. 递归遍历二叉树 144. 二叉树的前序遍历 class Solution { public:vector<int> preorderTraversal(TreeNode* root) {vector<int> result;preorder(root, result);return res…...

docker-compose部署kafka服务时如何同时允许内外网访问?
背景 最近在学习kafka相关知识,需要搭建自己的kafka环境。综合考虑后决定使用docker-compose来管理维护这个环境。 docker-compose.yml Bitnami的yml文件就很不错,这里直接拿来用了。 version: "2"services:zookeeper:image: docker.io/bi…...

数据结构刷题(二十):17电话号码的字母组合、39组合总和、40组合总和II
一、电话号码的字母组合题目链接思路:回溯三部曲。确定回溯函数参数:题目中给的 digits,还要有一个参数就是int型的index(记录遍历第几个数字,就是用来遍历digits的,同时也代表了递归的深度)&am…...

Java面试总结(五)
sleep() 方法和 wait() 方法对比 相同点 两者都可以暂停线程的执行;两者都可以响应中断。 不同点 sleep()方法不会释放锁,wait()方法会释放锁; sleep()方法主要用于暂停线程的执行,wait()方法主要用于线程之间的交互/通信&…...

三维人脸实践:基于Face3D的渲染、生成与重构 <二>
face3d: Python tools for processing 3D face git code: https://github.com/yfeng95/face3d paper list: PaperWithCode 3DMM方法,基于平均人脸模型,可广泛用于基于关键点的人脸生成、位姿检测以及渲染等,能够快速实现人脸建模与渲染。推…...

在linux上部署Java项目
在Linux部署Java环境 要是想要部署java web程序,首先要配置环境 jdk tomcat mysql 安装jdk 推荐的方法是使用yum直接安装openjdk(开源的,与官方的jdk功能差不多),目前使用的最多的就是jdk8系列 yum list | grep jdk 在源上搜索所有关于jdk的文件 devel表示development的意思…...

线性表的接口
线性表的实现方式 顺序表 顺序表是一种线性表的实现方式,它是用一组地址连续的存储单元依次存储线性表中的数据元素,使得逻辑上相邻的元素在物理上也相邻⁴。顺序表可以用数组来实现,它的优点是可以快速定位第几个元素,但是缺点…...

spark三种操作模式的不同点分析
通常情况下,由于mapreduce计算引擎的效率问题,大部分公司使用的基本都是hive数仓spark计算引擎的方式搭建集群,所以对于spark的三种操作方式来进行简单的分析。在日常开发中,使用最多的方式取决于具体的需求和场景。以下是每种方式的一些常见用途:Spark …...