- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我写了最简单的矩阵乘法代码来完成我对 C99 VLA 的理解。让我有点困惑的是,当我在函数定义的参数列表中声明一个指向 VLA 的指针时。
例如,在 fill_matrix_randomly
中,声明为 double (*m)[n_cols]
的参数 m
可以正常编译。 double (*m)[*]
是一个编译错误,因为[*]
只能出现在声明中。 double (*m)[]
也是一个错误,因为我无法访问不完整类型的数组。到现在为止没有什么奇怪的,但是。 double (*m)[n_rows]
编译正常甚至运行正常? double (*m)[1]
或 double (*m)[2]
也可以,我在这里真的很困惑。帮助我减少困惑。
#include <stdio.h>
#include <stdlib.h>
static void fill_matrix_randomly(int, int, double (*)[*]);
static void print_matrix(int, int, double (*)[*]);
static void multiply_matrices(int, int, int, double (*restrict)[*],
double (*restrict)[*], double (*restrict)[*]);
int main(void) {
const int a = 1, b = 3, c = 5;
double m[a][c], m2[a][b], m3[b][c];
fill_matrix_randomly(a, b, m2);
fill_matrix_randomly(b, c, m3);
multiply_matrices(a, b, c, m, m2, m3);
print_matrix(a, b, m2);
print_matrix(b, c, m3);
print_matrix(a, c, m);
}
static void fill_matrix_randomly
(int n_rows, int n_cols, double (*m)[n_cols]) {
for (int i = 0; i < n_rows; ++i) {
for (int j = 0; j < n_cols; ++j) {
m[i][j] = (double)rand() / RAND_MAX + 1;
}
}
}
static void print_matrix(int n_rows, int n_cols, double (*m)[n_cols]) {
for (int i = 0; i < n_rows; ++i) {
printf("[ ");
for (int j = 0; j < n_cols; ++j) {
printf("%.3f", m[i][j]);
if (j != n_cols - 1) {
printf(", ");
} else {
printf(" ]\n");
}
}
}
putchar('\n');
}
static void multiply_matrices
(int n, int m, int p, double (*restrict r)[p],
double (*restrict a)[m], double (*restrict b)[p]) {
for (int i = 0; i < n; ++i) {
for (int j = 0; j < p; ++j) {
double sum = 0;
for (int k = 0; k < m; ++k) {
sum += a[i][k] * b[k][j];
}
r[i][j] = sum;
}
}
}
最佳答案
double (*m)[n_rows] compiles fine and even runs fine
如果您声明函数参数类型为double (*)[n_rows]
,但传递的参数类型为double (*)[n_columns]
,并且n_rows
不同于n_columns
,则行为未定义。
这同样适用于 double (*m)[1]
和 double (*m)[2]
变体。
参数传递要求参数类型与参数类型兼容。在指向数组的指针的情况下,指针必须指向兼容的数组类型。在您的情况下,以下情况适用
6.7.5.2 Array declarators
6 For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.
显然,没有人可以合理地期望在编译时捕获此类违规行为,因为编译器通常无法在编译时预测和执行运行时关系(VLA 大小)。
在提交此违规行为(这本身足以触发 UB)后,您可以通过对 fill_matrix_randomly
中的数组执行越界访问来继续提交另一个违规行为。
至于运行它...我不清楚您认为带有 double (*m)[n_rows]
的代码“运行良好”的想法。一个快速的实验表明,如果你幸运的话,像那样对编译器说谎会导致数组填充不正确
http://coliru.stacked-crooked.com/a/6032864f2baa2eae
如果你不那么幸运,或者崩溃
关于c - VLA 作为函数参数的语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31932730/
在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
我是一名优秀的程序员,十分优秀!