- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我正在尝试创建 3 个动态类型的矩阵(int、float、double)以用于矩阵乘法。我已经为主矩阵中的每个矩阵创建了一个 void**“类型化”容器,然后将它们(作为 void***)传递到一个 init 函数中,以便根据用户对类型的选择进行 malloc。下面的代码可以编译,但是在 j 循环的一次迭代后我遇到了段错误,我终究无法弄清楚为什么会发生这种情况。类似地,如果我要在一个单独的 2 层深度循环中进行初始化(从 malloc 循环中取出 j 循环),那么在 i 循环的一次迭代之后仍然会发生段错误。
这甚至是实现我的动态类型矩阵乘法目标的好方法吗?非常感谢您的帮助。
void initMat(int type, int matSize, void ***matA, void ***matB, void ***matC)
{
int i, j, k;
switch(type) {
case 0 :
*matA = malloc(matSize * sizeof(int*));
*matB = malloc(matSize * sizeof(int*));
*matC = malloc(matSize * sizeof(int*));
for (i = 0; i < matSize; i++) {
*matA[i] = malloc(matSize * sizeof(int));
*matB[i] = malloc(matSize * sizeof(int));
*matC[i] = malloc(matSize * sizeof(int));
for (j = 0; j < matSize; j++) {
*(int*)matA[i][j] = rand()/RAND_MAX * 10;
*(int*)matB[i][j] = rand()/RAND_MAX * 10;
*(int*)matC[i][j] = 0;
}
}
break;
case 1 :
// with float, double, etc.
break;
default :
printf("Invalid case.\n" );
}
}
int main()
{
int type = 0;
int size = 0;
void **matA, **matB, **matC;
int sizes[6] = {3, 4, 5};
int matSize = sizes[size];
printf("The selected matrix size is: %d. \n", matSize); //allows user to select matrix size
initMat(type, matSize, &matA, &matB, &matC);
// displayMat(matSize, matA);
}
最佳答案
要使用动态分配的二维数组,应使用正确的指针类型。 (int **)
是一个指向指针的指针,指向指针数组的第一个元素,这些指针本身指向不同的分配。这种代码的结果是一个锯齿状的数组,而不是一个二维数组。分配的内存不保证是连续的(因为数组分配必须是连续的):
size_t num_rows = 3;
size_t num_cols = 5;
int **jagged_arr = malloc(sizeof *jagged_arr * num_rows);
for (size_t i = 0; i < num_rows; i++) {
jagged_arr[i] = malloc(sizeof *jagged_arr[i] * num_cols);
}
一种可能性是简单地为一维数组分配存储空间,并根据二维数组索引计算该数组的偏移量。这工作正常,但结果不是二维数组:
size_t num_elems = num_rows * num_cols;
int *simulated_2d_arr = malloc(sizeof *simulated_2d_arr * num_elems);
这不能作为二维数组索引,但可以根据列数和二维数组索引计算一维索引:
for (size_t i = 0; i < num_rows; i++) {
for (size_t j = 0; j < num_cols; j++) {
simulated_2d_arr[i * num_cols + j] = i * num_cols + j;
}
}
这两种方法都有其用途,但它们都有一个缺点,即生成的数组无法传递给旨在使用二维数组的函数。也就是说,考虑一个打印二维数组的函数,例如:
void print_2d_arr(size_t rows, size_t cols, int arr[][cols])
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
printf("%5d", arr[i][j]);
}
putchar('\n');
}
}
这个函数适用于类似的东西:
int real_2d_arr[2][3] = { { 1, 2, 3 },
{ 4, 5, 6 } };
但它不适用于较早的jagged_arr
:
expected ‘int (*)[(sizetype)(cols)]’ but argument is of type ‘int **’
或对于 simulated_2d_arr
:
expected ‘int (*)[(sizetype)(cols)]’ but argument is of type ‘int *’
在上面的错误消息中可以看到动态分配二维数组时要使用的正确类型。对于 int
的二维数组,这将是 int (*)[]
。这是二维数组在大多数表达式(包括函数调用)中衰减的类型。因此,要动态分配 int
的二维数组,这会起作用:
size_t num_rows = 3;
size_t num_cols = 5;
int (*array_2d)[num_cols] = malloc(sizeof *array_2d * num_rows);
这为num_cols
int
的num_rows
数组分配了空间。请注意,这不会创建 VLA,但会使用 VLA type。当然,VLA 早在 C99 中就引入了,但在 C11 中成为可选的(尽管仍得到广泛支持)。
至于你问题的动态类型部分,一个选择是创建一个 enum
来保存类型标识符,并将这些枚举常量之一传递给任何需要它们的函数。这些函数将需要接受 (void *)
参数,这些参数将根据类型枚举常量进行适当转换。这有点复杂,但这是一个示例程序。请注意,print_array()
函数适用于动态分配的数组和静态大小的数组。另请注意,不需要三重甚至双重间接寻址!
#include <stdio.h>
#include <stdlib.h>
enum Type { CHAR,
INT,
FLOAT,
DOUBLE };
void * get_array(enum Type type, size_t rows, size_t cols);
void init_array(enum Type type, size_t rows, size_t cols, void *arr);
void print_array(enum Type type, size_t rows, size_t cols, void *arr);
int main(void)
{
char (*arr_char)[5] = get_array(CHAR, 4, 5);
int (*arr_int)[5] = get_array(INT, 4, 5);
double (*arr_double)[5] = get_array(DOUBLE, 4, 5);
int arr_static[][3] = { { 1, 2, 3 },
{ 4, 5, 6 },
{ 7, 8, 9 } };
if (arr_char) { // check for null pointer
init_array(CHAR, 4, 5, arr_char);
puts("4x5 array of char");
print_array(CHAR, 4, 5, arr_char);
putchar('\n');
}
if (arr_int) { // check for null pointer
init_array(INT, 4, 5, arr_int);
puts("4x5 array of int");
print_array(INT, 4, 5, arr_int);
putchar('\n');
}
if (arr_double) { // check for null pointer
init_array(DOUBLE, 4, 5, arr_double);
puts("4x5 array of double");
print_array(DOUBLE, 4, 5, arr_double);
putchar('\n');
}
puts("Statically sized 3x3 array of int");
print_array(INT, 3, 3, arr_static);
putchar('\n');
/* Cleanup */
free(arr_char);
free(arr_int);
free(arr_double);
return 0;
}
/* Returns null pointer on allocation failure */
void *get_array(enum Type type, size_t rows, size_t cols)
{
size_t array_sz = 0;
void *ret = NULL;
switch (type) {
case CHAR:
array_sz = sizeof (char) * rows * cols;
break;
case INT:
array_sz = sizeof (int) * rows * cols;
break;
case FLOAT:
array_sz = sizeof (float) * rows * cols;
break;
case DOUBLE:
array_sz = sizeof (double) * rows * cols;
break;
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
if (array_sz) {
ret = malloc(array_sz);
}
return ret;
}
void init_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
int offset = i * cols + j;
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
array_char[i][j] = 'a' + offset;
break;
}
case INT:
{
int (*array_int)[cols] = arr;
array_int[i][j] = 0 + offset;
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
array_float[i][j] = 0.0 + offset;
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
array_double[i][j] = 0.0 + offset;
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
}
}
void print_array(enum Type type, size_t rows, size_t cols, void *arr)
{
for (size_t i = 0; i < rows; i++) {
for (size_t j = 0; j < cols; j++) {
switch (type) {
case CHAR:
{
char (*array_char)[cols] = arr;
printf("%3c", array_char[i][j]);
break;
}
case INT:
{
int (*array_int)[cols] = arr;
printf("%5d", array_int[i][j]);
break;
}
case FLOAT:
{
float (*array_float)[cols] = arr;
printf("%8.2f", array_float[i][j]);
break;
}
case DOUBLE:
{
double (*array_double)[cols] = arr;
printf("%8.2f", array_double[i][j]);
break;
}
default:
fprintf(stderr, "Unrecognized type in get_array()");
}
}
putchar('\n');
}
}
程序输出:
4x5 array of char
a b c d e
f g h i j
k l m n o
p q r s t
4x5 array of int
0 1 2 3 4
5 6 7 8 9
10 11 12 13 14
15 16 17 18 19
4x5 array of double
0.00 1.00 2.00 3.00 4.00
5.00 6.00 7.00 8.00 9.00
10.00 11.00 12.00 13.00 14.00
15.00 16.00 17.00 18.00 19.00
Statically sized 3x3 array of int
1 2 3
4 5 6
7 8 9
关于C:在另一个函数中初始化动态类型的二维矩阵,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46355693/
在 JavaScript 中,我们可以动态创建 元素并附加到 部分,以便为大量元素应用 CSS 规则。 这种方法的优点或缺点是什么? 如果它确实提供了与元素上的 javascript 迭代相比的性
我有这个代码 import "./HTTPMethod.dart"; import '../../DataModel/DataModel.dart'; mixin RouterMixin { HT
哪些 OLAP 工具支持动态、动态地创建维度或层次结构? 例如,层次结构将成员定义为:“前 5 名”、“前 6-10 名”、“其他”... 计算成员是通常的答案,我正在寻找不同的东西。计算器的问题。成
我正在 CakePHP 中创建一个“表单编辑器”。 该界面允许用户选择要应用于字段的验证,例如数字、电子邮件等 因此,我需要根据用户输入为模型动态创建验证。为此,我可以使用验证对象:https://b
这是一个场景: 我有一个Web服务,我们将其称为部署在tomcat(轴)上的StockQuoteService。通过此 Web 服务公开了 getStockQuote() 方法。 现在,我想构建一个
我正在尝试从服务器获取 JSON 响应并将其输出到控制台。 Future login() async { var response = await http.get( Uri.
我从另一个问题中得到了这段代码(感谢 chunhunghan)。我需要创建一个登录屏幕,并尝试根据服务器发回给我的响应来验证用户凭据,但是每次我尝试运行代码时,它都会给我“未处理的异常:Interna
当我在“Dart”主程序中运行它时,一切正常,并且我得到了一个与会者列表。但是,当我在我的 Flutter 应用程序中调用它时,出现错误: flutter:“List”类型不是“List>”类型的子类
本文实例为大家分享了js实现验证码动态干扰的具体代码,供大家参考,具体内容如下 效果一 效果二 代码一 ?
目前我正在为我的网站使用 No-Ip,我想使用 cloudflare 来抵御 ddos 和机器人程序。我注意到您需要一个用于 cloudflare 的域。我还搜索了网络,发现了一个叫做 cloud
有没有办法在 Excel VBA 中构建动态 if 语句?基本上我正在尝试创建一个参数化计算,用户将能够输入不同的变量,即 变量 1 “变量 2” “变量 3” 在这种情况下 变量 1 是单元格引用
大家好, 请查看上面的图片,我有两张 table 。在下面代码的第一个表中,我得到了这种格式。 但我想像 Table2 那样格式化,每个合并单元格中的行数是动态的,而且不一样。 有没有办法像table
如何根据我添加的 View 修改标题部分的高度?heightForHeaderInSection在 viewForHeaderInSection 之前被调用我不知道 View 大小,直到我创建它。 最
是否存在在运行时生成 AST/解析树的解析器?有点像一个库,它会接受一串 EBNF 语法或类似的东西并吐出数据结构? 我知道 antlr、jlex 和他们的同类。他们生成可以做到这一点的源代码。 (喜
我在持有汽车制造商的表格上有一个 MultipleChoiceField。我想将我的汽车数据库过滤到已检查的品牌,但这会导致问题。如何动态获取所有 Q(make=...) 语句? 我如何开始:['va
$end = preg_replace($pattern, $replacement, $str); 如何使替换字符串 $replacement 随 $str 中的每次匹配而变化?例如,我想用关联的图
我正在编写一个 VBA 程序,用于过滤表中的值。我试图使其成为一个适用于您提供的所有表格的通用程序。在我的程序中,我必须设置它正在过滤的表的范围:Set rng = dataSheet.Range("
我正在循环一个元素数组,并且我想使用给定的模板递归地显示该元素 然后在该模板内使用带有切换功能的按钮来显示/隐藏给定元素的Child的更深级别模板(Child也是一个元素) 这是我的模板
从客户端(html)发送表单,服务器端通过选择选项之一决定运行哪个函数。 const decideWho = (form) => { const choice = form.choice; c
我有一个具有以下属性的按钮: circle_normal.xml(在 res/drawable 中) circle.xml(在 res/drawable 中)
我是一名优秀的程序员,十分优秀!