我的主要编程语言j最近是开源的.为了改进它,我正在研究用C语言编写的源代码.
但是,自从我读过或写过C以来,这已经是一段很长的时间了,而我当时并不擅长.编写这个特定代码库的方式是......特殊的(许多APL解释器,其中的J,其源代码以高级"APL样式"编写,即使用低级语言编写;非常简洁,冗余避免,重大的宏观用途等)
目前,我正在尝试理解它采用的基本数据结构.最基本的是typedefA("A"代表" 数组 "):
typedef struct {I k,flag,m,t,c,n,r,s[1];}* A;
Run Code Online (Sandbox Code Playgroud)
我明白很好.但我正在努力绕过AF两行之后:
typedef A (*AF)();
Run Code Online (Sandbox Code Playgroud)
这个语法是什么意思?特别是,当事情后来被宣布为"AF型"时,它意味着什么?一个是AF简单的指针A?
我的直接目标是解释包含类型V(对于" 动词 ")的内存转储,其前两个成员是AFs:
typedef struct {AF f1,f2;A f,g,h;I flag,mr,lr,rr,fdep;C id;} V;
Run Code Online (Sandbox Code Playgroud)
但是我的总体目标比这更大,所以请详细说明AF定义中使用的语法.
我有一个巨大的代码使用由指针管理的3D数组.就像是:
int *** tab;
tab = malloc(m*sizeof(int**));
for(i= 1..n) tab[i] = malloc(n*sizeof(int*));
... etc...
Run Code Online (Sandbox Code Playgroud)
然后使用以下方法访问元素:
tab[i][j][k] = ...
Run Code Online (Sandbox Code Playgroud)
但由于此结构的特定问题,我想将tab声明为连续数组,但仍然在代码中使用带有3个括号的语法.编译器将在内部替换它们,如下所示:
tab[i][j][k] = ... => tab[i*m*n+j*m+k] = ...
Run Code Online (Sandbox Code Playgroud)
因此只使用一个指针解引用访问该数组.我不想更改源代码(没有sed).
例如,我可以通过在堆栈中声明制表符来完成此操作:
int tab[n][m][l];
Run Code Online (Sandbox Code Playgroud)
但不幸的是,如果m并且n是运行时变量,这不起作用.
我正在构建一套函数来处理多维数组数据结构,我希望能够定义数组的任意切片,这样我就可以实现两个任意矩阵(又称Tensors或nd数组)的广义内积.
一个APL论文我看了(老实说,我无法找到它-我已经看了这么多)定义的矩阵产品上左矩阵X,其尺寸A;B;C;D;E;F和右矩阵Y,尺寸G;H;I;J;K,其中F==G作为
Z <- X +.× Y
Z[A;B;C;D;E;H;I;J;K] <- +/ X[A;B;C;D;E;*] × Y[*;H;I;J;K]
Run Code Online (Sandbox Code Playgroud)
其中+/是和的和,并且×将元素逐个元素应用于两个相同长度的向量.
所以我需要左边的"行"切片和右边的"列"切片.我当然可以使用转置,然后使用"行"切片来模拟"列"切片,但我宁愿更优雅地做.
维基百科关于切片的文章引出了关于涂料载体的存根,这似乎是我正在寻找的奇迹治疗,但是没有太多可以继续下去.
如何使用涂料矢量来实现任意切片?
(很久以后我注意到了一个有一些细节的数组的Stride.)
c transpose slice multidimensional-array matrix-multiplication
我有一个简单的问题,但答案似乎很难找到:
如何在C(不是C++)中创建一个真正的2D数组,动态调整大小(编译时未知的大小),而不是堆上的指针数组,以便我可以将该分配放入单独的函数中并返回分配数组,没有收到任何警告gcc -Wall?
我在SO和其他论坛上发现了很多其他问题,但答案都有一些缺陷:
a[y][x].我希望我的数组也有一个真正的2D数组的内存布局.实现这种真正2D阵列分配的正确方法是什么?
编辑#1: 分配方法的返回类型可以是指向已分配数组的指针.