CV学习日志:C语言中数组的深层使用
以三维数组int aaa[7][8][9]为例来分析。
首先需要明确的是不管是多少维数组,其内存都是连续分布的。
1.用数组名表示数组地址
(1)aaa表示地址且aaa=aaa[0]=aaa[0][0]=&aaa[0][0][0]
(2)aaa[i]表示地址且aaa[i]=aaa[i][0]=&aaa[i][0][0],且有aaa[0]<aaa[1] <…<aaa[6]
(3)aaa[i][j]表示地址且aaa[i][j]=&aaa[i][j][0],且aaa[i][0] <aaa[i][2]<…<aaa[i][7]
2.用数组名计算数组尺寸
(1)sizeof(aaa)=7*8*9*sizeof(aaa[0][0][0])
(2)sizeof(aaa[i])=8*9*sizeof(aaa[0][0][0])
(3)sizeof(aaa[i][j])=9*sizeof(aaa[0][0][0])
3.数组维度的形象理解
基于以上分析可知,若要将三维数组aaa看作一栋楼,则应看作一栋共有7层、每层8排、每排9户的楼而不是一栋具有9层、每层8排、每排7户的楼,且第0层应为a[0]而不是a[6],第i层的第0排应是a[i][0]而不是a[i][7],第i层的第j排的第0户应是a[i][j][0]而不是a[i][j][8]
4.多组数组与OpenCV::Mat
基于aaa定义体阵:int szs[3]={7,8,9}; Mat_<int> AAA3D(3, szs, aaa);
则aaa与AAA3D相对应:aaa[i][j][k]==AAA3D(i,j,k)、aaa[i][j]==AAA3D.ptr<i,j>、aaa[i]==AAA3D.ptr<i>
这也同时说明了多维的OpenCV::Mat的每个维度与访问索引的对应关系。
以下样例代码,依赖于C++14、OpenCV4.x和Spdlog。
1 #include <opencv2/opencv.hpp> 2 #include <spdlog/spdlog.h> 3 using namespace std; 4 using namespace cv; 5 6 class AboutCArr 7 { 8 public: 9 template<typename invalidTP = char> static string cvarr2str(InputArray v) { Ptr<Formatted> fmtd = cv::format(v, Formatter::FMT_DEFAULT); string dst; fmtd->reset(); for (const char* str = fmtd->next(); str; str = fmtd->next()) dst += string(str); return dst; } 10 static void TestMe(int argc = 0, char** argv = 0) 11 { 12 //1. 13 int aaa[2][3][4]; 14 15 Mat_<int> AAA1D(1, 24, (int*)aaa); 16 randu(AAA1D, 10, 99); 17 18 //2. 19 spdlog::set_pattern("%v"); 20 string str = fmt::format("aaa_addr:{} aaa_bytes:{}", (void*)aaa, sizeof(aaa)); 21 22 //3. 23 str += fmt::format(" aaa[0]_addr:{} aaa[0]_bytes:{}", (void*)aaa[0], sizeof(aaa[0])); 24 str += fmt::format(" aaa[0][0]_addr:{} aaa[0][0]_bytes:{} ", (void*)aaa[0][0], sizeof(aaa[0][0])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[0][0][k]); 25 str += fmt::format(" aaa[0][1]_addr:{} aaa[0][1]_bytes:{} ", (void*)aaa[0][1], sizeof(aaa[0][1])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[0][1][k]); 26 str += fmt::format(" aaa[0][2]_addr:{} aaa[0][2]_bytes:{} ", (void*)aaa[0][2], sizeof(aaa[0][2])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[0][2][k]); 27 28 str += fmt::format(" aaa[1]_addr:{} aaa[1]_bytes:{}", (void*)aaa[1], sizeof(aaa[1])); 29 str += fmt::format(" aaa[1][0]_addr:{} aaa[1][0]_bytes:{} ", (void*)aaa[1][0], sizeof(aaa[1][0])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[1][0][k]); 30 str += fmt::format(" aaa[1][1]_addr:{} aaa[1][1]_bytes:{} ", (void*)aaa[1][1], sizeof(aaa[1][1])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[1][1][k]); 31 str += fmt::format(" aaa[1][2]_addr:{} aaa[1][2]_bytes:{} ", (void*)aaa[1][2], sizeof(aaa[1][2])); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", aaa[1][2][k]); 32 spdlog::info(str); 33 34 //4. 35 spdlog::info("AAA1D: {}", cvarr2str<>(AAA1D)); 36 37 //5. 38 spdlog::info("Conclusions:"); 39 spdlog::info(" 1.Equivalent address: aaa = aaa[0] = aaa[0][0], aaa[i] = aaa[i][0]"); 40 spdlog::info(" 2.Automatic length: sizeof(aaa), sizeof(aaa[i]), sizeof(aaa[i][j])"); 41 spdlog::info(" 3.Block memory operations(e.g memset and memcpy) are workable for array names: aaa, aaa[i], aaa[i][j]"); 42 43 //6. 44 str = " AAA3D: ["; 45 int szs[3] = { 2, 3, 4 }; 46 Mat_<int> AAA3D(3, szs, (int*)aaa); 47 for (int i = 0; i < szs[0]; ++i) for (int j = 0; j < szs[1]; ++j) for (int k = 0; k < szs[2]; ++k) str += fmt::format("{}, ", AAA3D(i, j, k)); 48 49 //7. 50 str += fmt::format(" AAA3D.ptr<int>(0):{}", (void*)AAA3D.ptr<int>(0)); 51 str += fmt::format(" AAA3D.ptr<int>(0, 0):{} ", (void*)AAA3D.ptr<int>(0, 0)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(0, 0)[k]); 52 str += fmt::format(" AAA3D.ptr<int>(0, 1):{} ", (void*)AAA3D.ptr<int>(0, 1)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(0, 1)[k]); 53 str += fmt::format(" AAA3D.ptr<int>(0, 2):{} ", (void*)AAA3D.ptr<int>(0, 2)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(0, 2)[k]); 54 55 str += fmt::format(" AAA3D.ptr<int>(1):{}", (void*)AAA3D.ptr<int>(1)); 56 str += fmt::format(" AAA3D.ptr<int>(1, 0):{} ", (void*)AAA3D.ptr<int>(1, 0)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(1, 0)[k]); 57 str += fmt::format(" AAA3D.ptr<int>(1, 1):{} ", (void*)AAA3D.ptr<int>(1, 1)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(1, 1)[k]); 58 str += fmt::format(" AAA3D.ptr<int>(1, 2):{} ", (void*)AAA3D.ptr<int>(1, 2)); for (int k = 0; k < 4; ++k) str += fmt::format(" {}", AAA3D.ptr<int>(1, 2)[k]); 59 spdlog::info(str); 60 } 61 }; 62 63 int main(int argc = 0, char** argv = 0) { AboutCArr::TestMe(argc, argv); return 0; }