[英]Vectors and matrices in C
I would like to perform vectorial operations in C but I don't know how to return a vector from a function. 我想在C中执行矢量运算,但我不知道如何从函数返回一个矢量。 I tried to generate a vector in this way:
我尝试以这种方式生成一个向量:
float *generate_vector()
{
static float vec[3];
return vec;
}
However, calling this function using 但是,使用调用此函数
int main (void)
{
float vec[3];
vec = generate_vector();
}
leads to an error (error: incompatible types when assigning to type 'float[3]' from type 'float *'). 导致错误(错误:从类型'float *'指定类型'float [3]'时不兼容的类型)。 Interestingly, this error doesn't occur when only a component of the vector is called using vec[1] = &generate_vector()[1].
有趣的是,当使用vec [1] =&generate_vector()[1]仅调用向量的一个组件时,不会发生此错误。
Could you help me with this problem? 你能帮我解决这个问题吗?
Thank you in advance. 先感谢您。
You have two problems here, the first is you can't assign an array like this: 你有两个问题,第一个是你不能分配这样的数组:
vec = generate_vector();
Arrays decay to pointers when they're passed, but in the function where it's declared it's an array, and you can't assign a pointer to it like this. 传递时,数组会衰减到指针,但是在声明它是数组的函数中,你不能像这样指定它。
You need to declare a pointer to get the returned array: 您需要声明一个指针来获取返回的数组:
float *vec = generate_vector();
Just FYI, a second option you might be interested in, if you want to generate a new array from this function you can do it dynamically. 只是FYI,你可能感兴趣的第二个选项,如果你想从这个函数生成一个新的数组,你可以动态地执行它。
float *vec = malloc(3 * sizeof(float));
then you need to free that later when you're done. 然后你需要在完成后释放它。
Here's a different approach if you like. 如果你愿意,这是一种不同的方法。 It's a little less efficient but might be easier to understand (and probably easier to handle in a complex program).
效率稍低但可能更容易理解(并且在复杂程序中可能更容易处理)。
In C, you can't return an array. 在C中,您无法返回数组。 You either need to
malloc()
a buffer (which you need to keep track of and later free()
it) or you need to declare a "return array" outside the function and pass an additional pointer to it into your functions. 你需要
malloc()
一个缓冲区(你需要跟踪它以及稍后free()
它)或者你需要在函数外部声明一个“返回数组”并将一个额外的指针传递给你的函数。
So there is the inability to return an array. 因此无法返回数组。 But hey, here is a nice workaround: you actually can return a
struct
that contains an array: 但是,嘿,这是一个很好的解决方法:你实际上可以返回一个包含数组的
struct
:
#include <stdio.h>
struct vec
{
double v[3];
};
struct vec multiply_scalar(struct vec v, double scalar)
{
int i;
struct vec ret;
for (i = 0; i < 3; i++)
{
ret.v[i] = v.v[i] * scalar;
}
return ret;
}
As was mentioned you are returning a pointer so you need to assign it to a pointer variable. 如前所述,您返回一个指针,因此需要将其指定给指针变量。 In addition, using a static array like this is a bad idea.
另外,使用像这样的静态数组是一个坏主意。 It would be better to take the vector in like this:
最好采用这样的向量:
void generate_vector(float * inVector)
This way the memory management is handled outside of the function and you won't accidentally use the same vector in multiple places. 这样,内存管理在函数外部处理,您不会在多个位置意外使用相同的向量。
With your setup a user of the function could write this code: 使用您的设置,该函数的用户可以编写此代码:
float * vectorA = generate_vector();
float * vectorB = generate_vector();
They may not expect that vectorA and vectorB are actually the same thing and this would lead to bugs. 他们可能不期望vectorA和vectorB实际上是同一个东西,这会导致错误。
When doing these things in C, I tend to reserve the return value of a function for an indicator that a function has succeded or failed. 在C中执行这些操作时,我倾向于为函数的成功或失败指示函数保留函数的返回值。 The input and output arrays I tend to pass as parameters.
我倾向于传递输入和输出数组作为参数。
Some years ago I wrote a Perl script to generate loop-unrolled matrix and vector code. 几年前,我编写了一个Perl脚本来生成循环展开的矩阵和向量代码。 (Like C++ templates, but for C) An example of the output is this function to transform a vector with a matrix.
(与C ++模板类似,但对于C)输出的一个示例是使用矩阵变换矢量的函数。
/* Multiplies a matrix with a vector */
extern void mat_xform3(double m[3][3], double v[3], double mv[3]);
Implementation: 执行:
#ifndef NULL
#define NULL (void*)0
#endif
/* If the product of the multiplication of two doubles is less than EPS,
* the value is set to 0. */
#define EPS 1e-8
void mat_mul3(double a[3][3], double b[3][3], double ab[3][3])
{
double res[3][3];
assert(a!=NULL); assert(b!=NULL); assert(ab!=NULL);
res[0][0] = a[0][0]*b[0][0];
res[0][0] += a[0][1]*b[1][0];
res[0][0] += a[0][2]*b[2][0];
if (res[0][0] < EPS && res[0][0] > -EPS) {res[0][0] = 0.0;}
res[0][1] = a[0][0]*b[0][1];
res[0][1] += a[0][1]*b[1][1];
res[0][1] += a[0][2]*b[2][1];
if (res[0][1] < EPS && res[0][1] > -EPS) {res[0][1] = 0.0;}
res[0][2] = a[0][0]*b[0][2];
res[0][2] += a[0][1]*b[1][2];
res[0][2] += a[0][2]*b[2][2];
if (res[0][2] < EPS && res[0][2] > -EPS) {res[0][2] = 0.0;}
res[1][0] = a[1][0]*b[0][0];
res[1][0] += a[1][1]*b[1][0];
res[1][0] += a[1][2]*b[2][0];
if (res[1][0] < EPS && res[1][0] > -EPS) {res[1][0] = 0.0;}
res[1][1] = a[1][0]*b[0][1];
res[1][1] += a[1][1]*b[1][1];
res[1][1] += a[1][2]*b[2][1];
if (res[1][1] < EPS && res[1][1] > -EPS) {res[1][1] = 0.0;}
res[1][2] = a[1][0]*b[0][2];
res[1][2] += a[1][1]*b[1][2];
res[1][2] += a[1][2]*b[2][2];
if (res[1][2] < EPS && res[1][2] > -EPS) {res[1][2] = 0.0;}
res[2][0] = a[2][0]*b[0][0];
res[2][0] += a[2][1]*b[1][0];
res[2][0] += a[2][2]*b[2][0];
if (res[2][0] < EPS && res[2][0] > -EPS) {res[2][0] = 0.0;}
res[2][1] = a[2][0]*b[0][1];
res[2][1] += a[2][1]*b[1][1];
res[2][1] += a[2][2]*b[2][1];
if (res[2][1] < EPS && res[2][1] > -EPS) {res[2][1] = 0.0;}
res[2][2] = a[2][0]*b[0][2];
res[2][2] += a[2][1]*b[1][2];
res[2][2] += a[2][2]*b[2][2];
if (res[2][2] < EPS && res[2][2] > -EPS) {res[2][2] = 0.0;}
memcpy(ab, res, 3*3*sizeof(double));
}
In this case, the function cannot fail, so it returns void
. 在这种情况下,函数不会失败,因此返回
void
。 But a function to eg invert a matrix can fail, so that returned a value indicating success or failure. 但是,例如反转矩阵的函数可能会失败,因此返回指示成功或失败的值。
The Perl script could generate code for matrices of arbitrary size. Perl脚本可以为任意大小的矩阵生成代码。 Leave a comment if you'd want it.
如果你需要,请发表评论。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.