【问题标题】:Passing Values from One Function to Another in C by reference [duplicate]通过引用在C中将值从一个函数传递给另一个函数[重复]
【发布时间】:2015-01-06 16:31:11
【问题描述】:

我需要一个从文件中读取数据块的程序。该块有一个dwDatadwLength 字段。 dwLength 字段是 sizeof dwData,就像 strlen 用于字符串一样。

这个程序的问题是readChunk0 无法获得从readChunk 初始化的dwLength 值。 dwLength 值在 readChunk 中是可以的,因为 cvar.mbsz 消息正确显示它(字符串的消息框)。

为什么我无法在测试功能中读取dwLength?为什么dwData可以通过,dwLength不行。

//////////////////////////////////////////////////////////////
//  read contents of a chunk in dwData
//  and dwLength value in a hex file
//
//////////////////////////////////////////////////////////////
DWORD readChunk(DWORD dwData, DWORD dwLength, TCHAR ccSymbol[6]){
    HWND hWnd=cvar.get_hwnd();
    STRCK strform;//readChunk
    strform.cksize=sizeof(STRCK);
    //  strform.ccSymbol=
    //  strform.ckmaxsize=200;
    //  strform.nextck=0x4;

    //open file in HMMIO mode
    //filename is a common one
    cchmmio=mmioOpen("vocer.hex", NULL, MMIO_READ|MMIO_DENYNONE);
    if (cchmmio==NULL){
        MessageBox(hWnd, "eroare 1 mmioOpen", "titlu", 0);
        return 1;
    };

    MMCKINFO lpckParent={0,0,mmioFOURCC('W','A','V','E'),0,0};
    lpckParent.fccType=mmioFOURCC('W','A','V','E');
    lpckParent.cksize=sizeof(MMCKINFO)+sizeof(STRCK);
    HRESULT hr=mmioDescend(cchmmio, (LPMMCKINFO)&lpckParent, NULL, MMIO_FINDCHUNK);
    if ((hr!=MMSYSERR_NOERROR)&(hr!=MMIOERR_CHUNKNOTFOUND)){//&(hr!=MMIOERR_CHUNKNOTFOUND)){
        MessageBox(hWnd, "eroare 2", "titlu", 0);
        return 2;
    };
    if (hr==MMIOERR_CHUNKNOTFOUND){
        MessageBox(hWnd, "eroare 3 WAVE CHUNKNOTFOUND", "titlu", 0);
        return 3;
    };

    MMCKINFO mmckinfo;
    mmckinfo.ckid=mmioStringToFOURCC(ccSymbol, 0);
    //if you find the symbol, read dwData chunk;
    hr=mmioDescend(cchmmio, &mmckinfo, &lpckParent, MMIO_FINDCHUNK);
    if (hr==MMIOERR_CHUNKNOTFOUND){
        MessageBox(hWnd, "4) eroare fatala. ccSymbol not found", "titlu", 0);
        return 4;
    };

    if ((hr!=MMSYSERR_NOERROR)&(hr!=MMIOERR_CHUNKNOTFOUND)){
        MessageBox(hWnd, "eroare 5", "titlu", 0);
        return 5;
    }

    dwLength=(DWORD*)mmckinfo.cksize;
//  memcpy(&dwLength, &mmckinfo.cksize, 2);

    hr=mmioRead(cchmmio, (LPSTR)&dwData, (LONG)dwLength);
    if (hr!=(LONG)dwLength){
        MessageBox(hWnd, "eroare 6 mmioRead ccSymbol", "titlu", 0);
        return 6;
    };

    hr=mmioClose(cchmmio, 0);
    if (hr!=MMSYSERR_NOERROR){
        MessageBox(hWnd, "eroare 9 mmioClose", "titlu", 0);
        return 9;
    };

    //ok
    //  cvar.mbsz((LPSTR)dwData, "titlu", 0);//display dwData contents
    //  cvar.mbsz("strlen(szData):", "titlu", strlen((LPSTR)dwData));//display szData value
    cvar.mbsz("(DWORD)dwLength:", "titlu", (DWORD)dwLength);//display length read

    return 0;
}

// Test Function///////////////////////////////////////
//    open vocer.hex file
//    read a ccSymbol chunk and return the
//    dwData and dwLength values
//
void readChunk0(void){
    HWND hWnd=cvar.get_hwnd();
    DWORD dwData=(DWORD)calloc(200, sizeof(DWORD));
    DWORD dwLength=2;
    TCHAR cc[6]="x002";

    HRESULT    hr=readChunk((DWORD*)&dwData, (DWORD*)&dwLength, cc);
    if (hr){
        cvar.mbsz("eroare la revenirea din readChunk:", "titlu", hr);
        return;
    };
    //result is read in dwData
    //and has dwLength length

    //display the length of the message: dwLength (2 methods)
    //and contents of the dwData buffer
    TCHAR sztemp[256];
    sprintf(sztemp, "%d", dwLength);
    MessageBox(hWnd, sztemp, "titlu", 0);
    cvar.mbsz("(DWORD)dwlength:", "titlu", (DWORD)dwLength);
    MessageBox(hWnd, (LPSTR)dwData, "titlu:", 0);
}

编辑

感谢 Diegos,您的建议既快速又好。我把它放在一起告诉你。

让我把我目前所了解的写下来。

//////////////////////////////////////////////////////////////
//  read contents of a iData chunk and iLength value
//  in vocer.hex RIFF file
//
//////////////////////////////////////////////////////////////
DWORD readChunk(int* iData, int* iLength, LPSTR ccSymbol){
HWND hWnd=cvar.get_hwnd();

    if (!PathFileExists(szName0))
        strcpy(szName0, "vocer.hex");

    cchmmio=mmioOpen(szName0, NULL, MMIO_READ|MMIO_DENYNONE);

MMCKINFO lpckParent={0};
lpckParent.fccType=mmioFOURCC('W','A','V','E');
HRESULT hr=mmioDescend(cchmmio, (LPMMCKINFO)&lpckParent, NULL, MMIO_FINDCHUNK);
    if ((hr!=MMSYSERR_NOERROR)&(hr!=MMIOERR_CHUNKNOTFOUND)){
        MessageBox(hWnd, "eroare 2", "titlu", 0);
        return 2;
    };
    if (hr==MMIOERR_CHUNKNOTFOUND){
        MessageBox(hWnd, "eroare 3 WAVE CHUNKNOTFOUND", "titlu", 0);
        return 3;
    };

MMCKINFO mmckinfo={0};
    mmckinfo.ckid=mmioStringToFOURCC(ccSymbol, 0);
//daca ai gasit symbolul, citeste chunkul dwData;
    hr=mmioDescend(cchmmio, &mmckinfo, &lpckParent, MMIO_FINDCHUNK);
    if (hr==MMIOERR_CHUNKNOTFOUND){
        MessageBox(hWnd, "eroare 4. ccSymbol not found", "titlu", 0);
        return 4;
    };

    if ((hr!=MMSYSERR_NOERROR)&(hr!=MMIOERR_CHUNKNOTFOUND)){
        MessageBox(hWnd, "eroare 5", "titlu", 0);
        return 5;
    };

//  memcpy((int*)iLength, (long*)mmckinfo.cksize, 2);
    iLength[0]=mmckinfo.cksize;

TCHAR sztemp2[256];
TCHAR* sztemp=(TCHAR*)calloc(iLength[0]+1, sizeof(TCHAR));
    hr=mmioRead(cchmmio, (LPSTR)sztemp, (long)iLength[0]);
    sprintf(sztemp2, "iData:%s\nmmioRead:%d", (LPSTR)sztemp, hr);
    MessageBox(hWnd, (LPSTR)sztemp2, "titlu", 0);
    if (hr!=iLength[0]){
        cvar.mbsz("valoare dwLength:", "titlu", (long)iLength[0]);
        MessageBox(hWnd, "eroare 6 mmioRead ccSymbol", "titlu", 0);
        return 6;
    };

    for(int i=0; i<iLength[0]; i++)
        iData[i]=sztemp[i];
//      memcpy(&iData[i], &sztemp[i], 1);

    hr=mmioClose(cchmmio, 0);

    return 0;
}


//Functie Test//////////////////////////////////////////
//  open vocer.hex file
//  read ccSymbol chunk and return
//  dwData of dwLength
//
//////////////////////////////////////////////////////////////
void readChunk00(void){
HWND hWnd=cvar.get_hwnd();
int* iLength=(int*)calloc(1, sizeof(int));
int* iData=(int*)calloc(200, sizeof(int));
TCHAR ccSymbol[6]="0x02";
TCHAR sztemp[200];//=(TCHAR*)calloc(iLength[0]+2, sizeof(TCHAR));

HRESULT hr=readChunk((int*)iData, (int*)iLength, ccSymbol);

    wsprintf(sztemp, "dwLength:%d\niData:%s", iLength[0], (LPSTR)&iData[0]);
    MessageBox(hWnd, (LPSTR)sztemp, "titlu", 0);

    strcpy(sztemp, "");
    MessageBox(hWnd, "inainte de for", "titlu", 0);
    for(int i=0; i<iLength[0]; i++){
//      strcat(sztemp,(LPSTR)&iData[i]);
        sztemp[i]=(TCHAR)&iData[i];
    };

TCHAR* sztemp2=(TCHAR*)calloc(iLength[0]+2, sizeof(TCHAR));
    sprintf(sztemp2, "dwLength:%d\niData:%s", iLength[0], (LPSTR)sztemp);
//  sprintf(sztemp, "dwLength:%d\niData[1]:%d", iLength[0], iData[1]);
    MessageBox(hWnd, (LPSTR)sztemp2, "titlu", 0);
}


//Functie Test///////////////////////////////////////
//  deschide fisierul voce.hex
//  citeste un chunk ccSymbol si returneaza
//  dwData de dimensiune dwLength
//  metoda cu pointer
void readChunk0(void){
HWND hWnd=cvar.get_hwnd();
LPSTR ccSymbol="0x02";
int* dwLength=(int*)calloc(1, sizeof(int));

HGLOBAL hData=GlobalAlloc(GHND, (int)dwLength);
    if (hData==0){
        cvar.mbsz("eroare la GlobalAlloc:", "titlu", GetLastError());
        return;
    };

int* iData=(int*)GlobalLock(hData);
    if (iData==0){
        cvar.mbsz("eroare la GlobalLock:", "titlu", GetLastError());
        return;
    };

HRESULT hr=readChunk((int*)iData, (int*)dwLength, ccSymbol);
    if (hr){
        cvar.mbsz("eroare la revenirea din readChunk:", "titlu", hr);
        return;
    };

    hr=GlobalUnlock(hData);
    if (hr!=0){
        cvar.mbsz("eroare la GlobalUnlock:", "titlu", GetLastError());
        return;
    };

TCHAR* sztemp=(TCHAR*)calloc(dwLength[0]+2, sizeof(TCHAR));
    for(int i=0; i<dwLength[0]; i++)
        sztemp[i]=iData[i];

    strcat(sztemp, "\0");
    MessageBox(hWnd, (LPSTR)sztemp, "titlu", 0);
    cvar.mbsz("(DWORD)dwLength:", "titlu", dwLength[0]);

}

我最终设法让它运行起来。下次请指导,因为 calloc 函数的实现方式与操作系统(WINDOWS XP)的 GlobalAlloc 不同。我写了两个结果相同的函数,如果我错了,请纠正我。函数测试 readChunk00 使用 calloc 完成,它无法读取 readChunk 中的主函数对第一个参数 dwLength[0] 所做的修改。

函数 readChunk0 是为与 readChunk00 相同目的而构建的测试函数,但现在它使用 GlobalAlloc 和系列函数,在我看来,操作系统更好地解释了这些函数。

在您看来,calloc 的第一个参数 (dwLength[0]) 是否没有通过调用 hr=readChunk 函数很好地初始化?这个话题不是重复的。感谢您的宝贵时间:)

【问题讨论】:

  • 您的标题、您的问题、您的代码和您的标签似乎彼此无关。请编辑您的问题 (?) 并进行清理。
  • 要读取一大块数据,请使用std::istream::read()
  • 请将您的问题标记为[c][c++],但不能同时标记。它们不是同一件事。标签[voice-recording] 与读取文件有什么关系?
  • 这里不需要投:(long*)&amp;dwLength&amp;dwLength 可以,因为 dwLength 被定义为 long

标签: c pass-by-reference


【解决方案1】:

如果您希望修改调用者看到的值,您需要将指向dwLength 的指针传递给readChunk 并在函数内取消引用它。

另外,给定dwData的初始化,它的数据类型应该是DWORD*


编辑以了解新信息。

您的新方法仍然存在一些问题。下面是一些代码片段,希望大家可以整理一下。

这就是你应该如何声明你的 readChunk 函数:

DWORD readChunk(DWORD* dwData, DWORD* dwLength, TCHAR ccSymbol[6])

在函数内部,这是设置dwLength指向的值的方式:

*dwLength = mmckinfo.cksize;

在你的测试函数中,这是你声明dwData的方式:

DWORD* dwData = calloc(200, sizeof(DWORD));

这就是你声明dwLength的方式:

DWORD dwLength;

最后这就是你将所有数据传递给readChunk的方式:

HRESULT hr = readChunk(dwData, &dwLength, cc);

您确实需要熟悉指针的工作原理以及参数如何按值传递或通过 C 中的指针间接传递。

【讨论】:

  • 抱歉粗鲁,但它适用于 dwData 就好了;尝试过 DWORD* 但效果相同。 int* 等于 INT 是真的吗?
  • 它适用于dwData,因为转换(LPSTR)dwData 使值成为指针。在 DWORD 的大小与指针相同的体系结构中,它可以工作,但通常情况并非如此。 (即 64 位)
  • @paul80 很抱歉粗鲁,但如果它有效,那只是因为您正在编译 32 位代码,而不是因为它应该有效。你违反了严格的别名。而这个答案是正确的。要么通过引用传递dwLength,要么通过地址传递,具体取决于您用于实际语言的轮盘赌,因为这个问题同时被标记为 C 和 C++。
  • @Diego Nieto Cid \n传递 dwData 的值是可以的
  • 说得清楚一点,c 确实 支持通过引用传递。一切都是价值。 stackoverflow.com/questions/2229498/passing-by-reference-in-c
猜你喜欢
  • 1970-01-01
  • 2020-10-21
  • 1970-01-01
  • 2011-11-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-12
  • 1970-01-01
相关资源
最近更新 更多