0

我知道这有点长,但这是一个棘手的问题。感谢您的关注!我在这方面工作太久了。我做了很多研究并尝试了很多东西,希望有人可以帮助解释。

大纲:

用 C 语言编写。我需要从仪器中获取一组数据。数组的大小将根据收集的数据量而有所不同。我可以查询数据点的数量。我编写了一个函数来收集数据(如下所示)。这在 main() 中直接调用函数时有效。我用来测试的。但是,此函数将是一个 dll,并从更高 dll 中的函数调用。这不起作用。我相信是因为大小可变。

我迷失在可变大小和指针的细节中。任何帮助表示赞赏。

功能代码,从 main() 调用

*注意 - ViInt16 以下是特定于 VISA(仪器通信协议)的有符号短类型。函数返回一个 int 作为状态/错误(在其他代码中设置)。

标题:

    int GetSamples (ViInt16 *DataArray, int DataSize);

功能:

    int GetSamples (ViInt16 *DataArray, int DataSize)
    {
        ViUInt16 N=0;
        ViInt16 Datatemp[DataSize];

        viMoveIn (Handle, N, 0, DataSize, Datatemp);
        memcpy (DataArray, Datatemp, sizeof(Datatemp);
    }

主要的:

    int totalsamples = (PreTrigPts() + AcqPts())
    ViInt16 Data [totalsamples];
    GetSamples (Data, totalsamples);             

这行得通!我想,只是因为我可以得到总大小,然后从 main() 分配 ViInt16 数组。说实话,不确定我在传递数组时用指针等做什么

问题是,当它是一个调用函数的函数时,我不确定该怎么做,因为我认为,在查询大小之前,需要在顶部分配数组。这是我正在尝试的方法(这不起作用)

问题代码

低级“驱动程序”(称为 dll):

    Header and function definition from above.

Functions_header:(将低级驱动程序称为 dll)

    void AutoSample(void);  //No returns. Writes to UI in Functions_list.c

函数列表.c:

    void AutoSample ()
    {
        int PreTriggerPts = 0;  //Declare all variables at top, or won't compile
        int Points = 0;
        int TotalSamples = 0
        ViInt16 MyData [5] = {0};  //arbitrary since don't know size yet

        TotalSamples = (PreTrigPts() + AcqPts());

        ViInt16 MyData[TotalSamples];  //Trying to size by reinitializing? 

        GetSamples (MyData, TotalSamples);

        //...calls another function to write MyData to UI...etc. etc.

主要.c:

    AutoSample();

错误

当我尝试不同的事情时,我遇到了很多错误。如果需要,我可以更具体,但是如果我在知道变量的大小之后尝试初始化变量(就像我在工作代码中所做的那样),它会告诉我这是非法的。将声明放在首位可以解决此问题。现在我不知道要初始化的大小。从这里我一直在破解,没有更具体的。我需要对指针和内存做一些事情,但我不知道是什么。请,任何帮助表示赞赏!

4

4 回答 4

0

有几件事。

在 AutoSample 中试试这个(就像在 main 中一样):

void AutoSample ()
{
    int PreTriggerPts = 0;  //Declare all variables at top, or won't compile
    int Points = 0;
    int TotalSamples = (PreTrigPts() + AcqPts());
    ViInt16 MyData[TotalSamples];  //Trying to size by reinitializing? 

    GetSamples (MyData, TotalSamples);

    //...calls another function to write MyData to UI...etc. etc.

此外,在 GetSamples() 中,您可以避免使用 memcpy():

int GetSamples (ViInt16 *DataArray, int DataSize)
{
    ViUInt16 N=0;

    viMoveIn (Handle, N, 0, DataSize, DataArray);
}
于 2013-05-31T19:15:19.273 回答
0

应该能够推迟 VLA 的声明,直到您知道需要的元素数量1

void AutoSample ()
{
    int PreTriggerPts = 0;  
    int Points = 0;
    int TotalSamples = 0

    TotalSamples = (PreTrigPts() + AcqPts());

    ViInt16 MyData[TotalSamples];     // initializer not allowed for VLAs
                                      // If you *really* need to initialize a VLA,
                                      // use memset or memcpy

    GetSamples (MyData, TotalSamples);

    //...calls another function to write MyData to UI...etc. etc.

如果没有,您可能需要在编译器上设置一个标志以允许混合声明和代码。

关于指针和数组...

在大多数情况下,“N-element array of T”类型的表达式将被转换为“pointer to T”类型的表达式,表达式的值将是数组2的第一个元素的地址。当表达式是一元运算符sizeof或一元运算符的操作数&,或者是用于初始化另一个数组的字符串文字时,会出现此规则的例外情况。

所以在函数调用中

GetSamples (MyData, TotalSamples);

表达式 MyData从“ TotalSamples-element array of ”类型转换为ViInt16“pointer to ViInt16”类型,接收到的值GetSamples是指向第一个元素的指针MyData。这就是为什么你的函数声明写成

int GetSamples (ViInt16 *DataArray, int DataSize);

因为GetSamples实际接收的是指针值,而不是数组。你也可以把它写成

int GetSamples (ViInt16 DataArray[], int DataSize);

在函数参数声明的上下文中,T a[]T a[N]等价于T *a. 请注意,这适用于函数参数声明。

VLA 很有用,但也有局限性:

  • 它们不能在文件范围内使用(在任何函数之外),也不能被声明static
  • 它们不能用通常的数组初始化语法进行初始化;
  • 尽管有这个名字,但它们不能即时调整大小;
  • 它们不能任意大;
  • 它们没有得到普遍支持,并且在 C2011 标准中它们是可选的;

根据您返回的样本数量,您可能希望放弃 VLA 并使用malloc或从堆中分配内存realloc


1 - C99 允许您混合声明和代码,如果您成功使用 VLA,那么您很可能使用 C99 或更高版本的编译器。
2 - 信不信由你,这种行为有一个合理的解释——向下滚动到标题为“胚胎 C”的部分。

于 2013-05-31T20:52:28.277 回答
0

您可能需要启用 C99 模式 ( gcc --std=c99) 才能使用可变长度数组。另一种选择是使用malloc. “重新初始化”永远不会起作用。C 不能像那样调整数组的大小。

于 2013-05-31T18:50:54.323 回答
0

我认为您将不得不将 ViInt16 MyData 变成指针而不是数组,如下所示:

 ViInt16 *MyData;

然后在知道数据长度后动态分配一个缓冲区来保存数据,如下所示:

 MyData = (ViInt16*)malloc((sizeof ViInt16) *  TotalSamples); 

请注意,稍后您必须通过调用 free 来释放此缓冲区。

于 2013-05-31T18:56:07.643 回答