我刚学会了X-Macros.您看过X-Macros的实际用途?他们什么时候成为工作的合适工具?
这个问题的目的是提供一个关于如何在C中动态正确分配多维数组的参考.这是一个经常被误解的主题,即使在一些C编程书籍中也很难解释.因此,即使是经验丰富的C程序员也很难做到正确.
我从编程教师/书籍/教程中了解到,动态分配多维数组的正确方法是使用指针指针.
然而,SO上的几个高代表用户现在告诉我这是错误和不好的做法.他们说指针到指针不是数组,我实际上并没有分配数组,而且我的代码不必要地慢.
这就是我教我分配多维数组的方法:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int** arr_alloc (size_t x, size_t y)
{
int** pp = malloc(sizeof(*pp) * x);
assert(pp != NULL);
for(size_t i=0; i<x; i++)
{
pp[i] = malloc(sizeof(**pp) * y);
assert(pp[i] != NULL);
}
return pp;
}
int** arr_fill (int** pp, size_t x, size_t y)
{
for(size_t i=0; i<x; i++)
{
for(size_t j=0; j<y; j++)
{
pp[i][j] = (int)j + 1;
}
}
return pp;
}
void arr_print (int** pp, size_t x, size_t y) …Run Code Online (Sandbox Code Playgroud) c arrays dynamic-arrays dynamic-allocation variable-length-array
我的主要编程语言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定义中使用的语法.
我想知道是否有可能在宏参数上编写宏foreach.这是想做的事情:
#define PRINT(a) printf(#a": %d", a)
#define PRINT_ALL(...) ? ? ? THE PROBLEM ? ? ?
Run Code Online (Sandbox Code Playgroud)
可能的用法:
int a = 1, b = 3, d = 0;
PRINT_ALL(a,b,d);
Run Code Online (Sandbox Code Playgroud)
这是我到目前为止所取得的成就
#define FIRST_ARG(arg,...) arg
#define AFTER_FIRST_ARG(arg,...) , ##__VA_ARGS__
#define PRINT(a) printf(#a": %d", a)
#define PRINT_ALL PRINT(FIRST_ARG(__VA_ARGS__)); PRINT_ALL(AFTER_FIRST_ARG(__VA_ARGS__))
Run Code Online (Sandbox Code Playgroud)
这是一个递归宏,这是非法的.另一个问题是stop condition递归.
我正在C语言程序中为多精度整数编写一些数学例程,我希望能够轻松编写表达式,但用我自己的函数处理数学运算.所以我想要一些让我这样做的方法:
MPI x=mpi(5),y=mpi(6),z;
z=mpimath(x,+,y);
Run Code Online (Sandbox Code Playgroud)
通过以某种方式对角色进行编码,这在C中是否可行?我知道没有运算符重载所以它必须是函数调用,+-sign不能是函数名的一部分.
典型的1-D数组可以在声明中静态或自动分配.
enum { n=100 };
int arr1[n];
Run Code Online (Sandbox Code Playgroud)
或者通过指针动态分配和访问.
int *arr1m=malloc(n*sizeof*arr1m);
int *arr1c=calloc(n, sizeof*arr1c);
Run Code Online (Sandbox Code Playgroud)
这两种样式都使用相同的语法访问元素.
int i = n/2;
arr1[i] = arr1c[i] = arr1m[i] = 42;
Run Code Online (Sandbox Code Playgroud)
但是当你添加第二个维度时,需要花费一些力气来实现相同的语法.
int arr2[n][n];
int *arr2c=calloc(n*n,sizeof*arr2c);
arr2[5][5] = arr2c[5*n+5] = 23;
Run Code Online (Sandbox Code Playgroud)
如果您将其构造为Iliffe向量,则只能获得双重括号.
int **arr2l=calloc(n,sizeof*arr2l);
for (int j=0; j<n; j++)
arr2l[j]=calloc(n,sizeof**arr2l);
arr2[6][6] = arr2l[6][6] = 72;
Run Code Online (Sandbox Code Playgroud)
但随着尺寸的增加,这变得越来越麻烦.
另一个困难是在访问元素之前检查动态数组的边界(这样您就不会触及未正确分配的内存).在真正的阵列可以使用sizeof运营商确定的界限,但这些动态数组携带它们的大小与他们.
如何定义具有快速,连续布局的结构,如数组,但具有一致的语法,用于访问具有索引列表的元素,这些索引对于2D阵列和3D阵列的工作方式相同; 并且所有动态,动态大小可以传递给函数并从函数返回?
我有一个简单的问题,但答案似乎很难找到:
如何在C(不是C++)中创建一个真正的2D数组,动态调整大小(编译时未知的大小),而不是堆上的指针数组,以便我可以将该分配放入单独的函数中并返回分配数组,没有收到任何警告gcc -Wall?
我在SO和其他论坛上发现了很多其他问题,但答案都有一些缺陷:
a[y][x].我希望我的数组也有一个真正的2D数组的内存布局.实现这种真正2D阵列分配的正确方法是什么?
编辑#1: 分配方法的返回类型可以是指向已分配数组的指针.