简体   繁体   English

C中的向量和矩阵

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM