草庐IT

c++ - 二维数组作为函数的参数

coder 2023-11-16 原文

为什么不能像处理普通数组那样在函数中声明二维数组参数?

 void F(int bar[]){} //Ok
 void Fo(int bar[][]) //Not ok
 void Foo(int bar[][SIZE]) //Ok

为什么需要声明列的大小?

最佳答案

静态数组:

你似乎没有完全明白这一点。我想试着解释一下。正如上面的一些答案所描述的,2D ArrayC++作为 1D Array 存储在内存中.

int arr[3][4] ;   //consider numbers starting from zero are stored in it

在内存中看起来有点像这样。
1000    //ignore this for some moments       1011  
^                                             ^
^                                             ^

0   1   2   3   4   5   6   7   8   9   10   11
|------------|  |-----------|   |-------------|
  First Array    Second Array     Third Array

|----------------------------------------------|    
                Larger 2D Array

考虑到这里,更大的 2D Array存储为连续的内存单元。它由总数12元素,来自 011 .行是 3和列是 4 .如果要访问第三个数组,则需要跳过整个第一个和第二个数组。也就是说,您需要跳过与您的 cols 数量相等的元素。乘以要跳过的数组数。出来是cols * 2 .

现在,当您指定维度以访问数组的任何单个索引时,您需要事先告诉编译器确切地跳过多少元素。所以你给它准确的数字 cols执行其余的计算。

那么它是如何进行计算的呢?假设它适用于 column major order ,也就是说,它需要知道要跳过的列数。当您将此数组的一个元素指定为...
arr[i][j] ;

编译器自动执行此计算。
Base Address + (i * cols + j) ;

让我们尝试一个指标的公式来检验它的真实性。我们要访问 3rd 2nd 的元素大批。我们会这样做...
arr[1][2] ;   //access third element of second array

我们把它放在公式中......
  1000 + ( 1 * 4 + 2 )
= 1000 + ( 6 )
= 1006   //destination address

我们到达地址 1006哪里6位于。
简而言之,我们需要告诉编译器cols的数量。对于这个计算。所以我们把它作为一个函数的参数发送。

如果我们正在处理 3D Array , 像这样...
int arr[ROWS][COLS][HEIGHT] ;

我们必须在函数中将数组的最后两个维度发送给它。
void myFunction (int arr[][COLS][HEIGHT]) ;

现在的公式会变成这样..
Base Address + ( (i * cols * height) + (j * height) + k )  ;

要像这样访问它...
arr[i][j][k] ;
COLS告诉编译器跳过 2D Array 的数量, 和 HEIGHT告诉它跳过 1D Arrays 的数字.
对于任何维度,依此类推。

动态数组:

当您询问动态数组的不同行为时,因此声明..
int ** arr ;

编译器对它们的处理方式不同,因为 Dynamic 2D Array 的每个索引由另一个地址组成 1D Array .它们可能会或可能不会出现在堆上的连续位置。它们的元素由它们各自的指针访问。上面我们静态数组的动态对应物看起来有点像这样。
1000  //2D Pointer
^
^
2000       2001     2002
^          ^        ^
^          ^        ^
0          4        8
1          5        9
2          6        10
3          7        11

1st ptr  2nd ptr   3rd ptr

假设情况是这样。这里2D Pointer或位置上的数组 1000 .它持有地址到 2000它本身持有内存位置的地址。这里的指针运算是由编译器完成的,它凭借它判断元素的正确位置。

2D Pointer 分配内存,我们这样做..
arr = new int *[3] ;

并以这种方式为每个索引指针分配内存..
for (auto i = 0 ; i < 3 ; ++i)
  arr[i] = new int [4] ;

最后,每个ptr2D Array本身就是一个数组。要访问您所做的元素...
arr[i][j] ;

编译器这样做...
*( *(arr + i) + j ) ;
   |---------|
     1st step
|------------------|
      2nd step

第一步,2D Array被取消引用到其适当的 1D Array在第二步中,1D Array被取消引用以到达适当的索引。
这就是为什么Dynamic 2D Arrays被发送到函数而不提及它们的行或列。

笔记:
很多细节都被忽略了,描述中假设了很多东西,特别是内存映射只是为了给你一个想法。

关于c++ - 二维数组作为函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12652598/

有关c++ - 二维数组作为函数的参数的更多相关文章

  1. ruby-on-rails - 在 Ruby 中循环遍历多个数组 - 2

    我有多个ActiveRecord子类Item的实例数组,我需要根据最早的事件循环打印。在这种情况下,我需要打印付款和维护日期,如下所示:ItemAmaintenancerequiredin5daysItemBpaymentrequiredin6daysItemApaymentrequiredin7daysItemBmaintenancerequiredin8days我目前有两个查询,用于查找maintenance和payment项目(非排他性查询),并输出如下内容:paymentrequiredin...maintenancerequiredin...有什么方法可以改善上述(丑陋的)代

  2. ruby - 多次弹出/移动 ruby​​ 数组 - 2

    我的代码目前看起来像这样numbers=[1,2,3,4,5]defpop_threepop=[]3.times{pop有没有办法在一行中完成pop_three方法中的内容?我基本上想做类似numbers.slice(0,3)的事情,但要删除切片中的数组项。嗯...嗯,我想我刚刚意识到我可以试试slice! 最佳答案 是numbers.pop(3)或者numbers.shift(3)如果你想要另一边。 关于ruby-多次弹出/移动ruby​​数组,我们在StackOverflow上找到一

  3. ruby - 将数组的内容转换为 int - 2

    我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]

  4. ruby-on-rails - 如何在 ruby​​ 中使用两个参数异步运行 exe? - 2

    exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby​​中使用两个参数异步运行exe吗?我已经尝试过ruby​​命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何ruby​​gems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 通过 erb 模板输出 ruby​​ 数组 - 2

    我正在使用puppet为ruby​​程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby​​不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这

  7. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  8. ruby - 检查数组是否在增加 - 2

    这个问题在这里已经有了答案:Checktoseeifanarrayisalreadysorted?(8个答案)关闭9年前。我只是想知道是否有办法检查数组是否在增加?这是我的解决方案,但我正在寻找更漂亮的方法:n=-1@arr.flatten.each{|e|returnfalseife

  9. ruby - 如何在 Ruby 中拆分参数字符串 Bash 样式? - 2

    我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"

  10. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

随机推荐