- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
这是一种定义矩阵类型的方法
typedef struct {
int nr, nc;
double *elem;
} Matrix;
我想定义这个
typedef struct {
int nr, nc;
double elem[nr][nc];
} Matrix;
这很好,因为我不必担心索引。这就是 VLA 最初有用的原因,因为它们只透明地执行索引算法可以轻松完成的操作。
当然,上述情况是不可能的,因为结构的大小无法很好地定义。然后,我仍然会很高兴:
typedef struct {
int nr, nc;
double (*elem)[nc];
} Matrix;
现在,矩阵数据存储为指针,就像在非 VLA 情况下一样。但是运算仍然可以由编译器完成。该定义仅说明它是某种指向 double
数据的指针,double 排列在宽度为 nc
的数组中。
似乎标准也不允许这样做,我想知道为什么,因为通过转换很容易做到这一点。例如,使用第一个定义(使用 double *
),我可以做到
double get(Matrix *a, int i, int j) {
int nc = a->nc;
double (*p)[nc] = (double (*)[nc])a->elem;
return p[i][j];
}
当然,这里不是很有趣,因为只有一个对 elem 的访问,但如果有很多,也可能是这样。
那么,我的问题,希望它切题:禁止第三个定义的真正原因是什么?
我可以想象这很危险,因为它不能保证 nc
处理正确的值,但无论如何这对于指针来说都是危险的,所以这看起来不是一个好的理由。
最佳答案
这是否符合您的要求?它在结构中存储一个 void *
,访问函数将其转换为指向 2D VLA 的指针并使用它。 Mac OS X 10.10.5 上的 GCC 5.2.0 可以干净地编译它,valgrind
(2014 年 11 月左右的 3.11.0-SVN)给它一个干净的健康证明。
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int nr, nc;
void *data; // Actually double a[nr][nc]
} Matrix;
static double get(Matrix *a, int i, int j)
{
double (*array)[a->nr][a->nc] = a->data;
return (*array)[i][j];
}
static void set(Matrix *a, int i, int j, double v)
{
double (*array)[a->nr][a->nc] = a->data;
(*array)[i][j] = v;
}
static Matrix *mat_alloc(int nr, int nc)
{
Matrix *m = malloc(sizeof(*m));
if (m != 0)
{
m->nr = nr;
m->nc = nc;
m->data = malloc(nr * nc * sizeof(double));
if (m->data == 0)
{
free(m);
m = 0;
}
}
return m;
}
static void mat_free(Matrix *m)
{
free(m->data);
free(m);
}
int main(void)
{
int nr = 3;
int nc = 5;
Matrix *m = mat_alloc(nr, nc);
if (m == 0)
{
fprintf(stderr, "Matrix allocation for %dx%d matrix failed\n", nr, nc);
exit(1);
}
for (int i = 0; i < nr; i++)
{
for (int j = 0; j < nc; j++)
{
double v = (i * (nc + 1)) + j + 1;
set(m, i, j, v);
printf("Set: [%d,%d] = %4.1f\n", i, j, v);
}
}
for (int j = 0; j < nc; j++)
{
for (int i = 0; i < nr; i++)
printf("Get: [%d,%d] = %4.1f\n", i, j, get(m, i, j));
}
mat_free(m);
return 0;
}
我不确定是否有一种巧妙的方法来丢失访问函数中符号的 (*array)
部分。如果有的话我会更喜欢它(而不是使用 array[0][i][j]
,也就是说)。
Set: [0,0] = 1.0
Set: [0,1] = 2.0
Set: [0,2] = 3.0
Set: [0,3] = 4.0
Set: [0,4] = 5.0
Set: [1,0] = 7.0
Set: [1,1] = 8.0
Set: [1,2] = 9.0
Set: [1,3] = 10.0
Set: [1,4] = 11.0
Set: [2,0] = 13.0
Set: [2,1] = 14.0
Set: [2,2] = 15.0
Set: [2,3] = 16.0
Set: [2,4] = 17.0
Get: [0,0] = 1.0
Get: [1,0] = 7.0
Get: [2,0] = 13.0
Get: [0,1] = 2.0
Get: [1,1] = 8.0
Get: [2,1] = 14.0
Get: [0,2] = 3.0
Get: [1,2] = 9.0
Get: [2,2] = 15.0
Get: [0,3] = 4.0
Get: [1,3] = 10.0
Get: [2,3] = 16.0
Get: [0,4] = 5.0
Get: [1,4] = 11.0
Get: [2,4] = 17.0
关于c - 结构中的指针中不允许使用 VLA 有充分的理由吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32565694/
在this post ,OP 包含有很多错误的代码,但是 1 行让我特别好奇,因为我无法查找任何东西,不允许它。这是具体的行: int n = 100000, arr[n]; 是否保证了声明和初始化的
我需要定义一个结构体,其中包含两个信号量和三个(至少)或更多数组作为大小为变量的结构体成员。指示性示例(不是正确的语法,而是给出上下文含义;lr 是 double 的 typedef): int
函数的参数可以在后面的参数中使用吗?这是不好的形式吗? void print(int n, int m, int matrix[n][m]) { for (int i=0; i
C11 允许像这样使用 VLA 数组(和矩阵) int row = 10; int col = 10; double matrix[row][col]; 但是如果我只想将矩阵的一行传递给一个函数,我可
我写了最简单的矩阵乘法代码来完成我对 C99 VLA 的理解。让我有点困惑的是,当我在函数定义的参数列表中声明一个指向 VLA 的指针时。 例如,在 fill_matrix_randomly 中,声明
这样的函数原型(prototype)在 C 中有效吗? int (*func())[*]; 如果是,我该如何定义这样的函数? 最佳答案 您应该返回一个指向不完整数组类型的指针,因为可变长度数组的 *
在 C 中,我相信以下程序是有效的:将指向已分配内存缓冲区的指针转换为数组,如下所示: #include #include #define ARRSIZE 4 int *getPointer(in
您可能知道,VLA's haves pros and cons 和它们在 C11 中是可选的。 我想使 VLA 成为可选项的主要原因是:“堆栈可能会爆炸”: int arr[n]; /* where
我了解什么是可变长度数组以及它们是如何实现的。这个问题是关于它们为什么存在。 我们知道 VLA 只允许在功能块(或原型(prototype))中使用,并且它们基本上不能在堆栈上的任何地方(假设正常实现
这是允许的吗? goto inside; { inside: int a[n]; } A goto statement shall not jump from outside the scope of
我注意到 C 编译器(gcc、clang、tinycc)允许我在没有警告的情况下将指向较大数组的指针分配给指向较小 VLA 的指针: #include #if !__TINYC__ void tak
我使用以下结构来使用隐写术对带有消息的 PPM 文件进行编码: typedef struct{ char code[CODE_LENGTH]; COMMENT *commentPPM;
进一步开发昨天的代码( seg fault caused by malloc and sscanf in a function ),我尝试在网上找到的一些教程的帮助下生成一个 2-dim vla。但我
我有以下无法编译的代码。 using namespace std; void f(int); template void array_ini_1d(T1 (&x)[N]) { for (int i
我在 SO 上阅读了有关 VLA 的不同答案,但找不到答案。就我而言,我有一个分配内存的函数: template void allocMemory(T *&data, const size_t num
这是一种定义矩阵类型的方法 typedef struct { int nr, nc; double *elem; } Matrix; 我想定义这个 typedef struct {
我试图了解 sizeof 运算符的工作原理,我遇到了 this问题。以下是该问题的代码 #include int main() { int i = 0; int a[i];
CERT's Secure Coding Standard包括一项 ( API05-C ),它鼓励使用一致的数组参数,这是我在很多代码中实现的建议(对于不支持它们的编译器,隐藏在 a macro 后面
(这是后续 to this question 。) 我试图了解将多维数组传递给 C 中的函数的“最佳实践”(或任何实际实践)是什么。当然这取决于应用程序,所以让我们考虑编写一个函数来打印二维数组可变大
我们已经知道,VLA (在 C99 中标准化)不是 C++ 标准的一部分。 所以下面的代码在 C++ 中是“非法的”: void foo(int n) { int vla[n]; for (i
我是一名优秀的程序员,十分优秀!