通过C中的引用返回并传递文件描述符

我正在C中从头开始在Raspberry Pi上构建气象站。我有一个包含用于获取温度的代码的文件,并且我还有另一个文件来调用这些功能。 我之前已经写过代码,但是代码的质量很差,我想重新编写更好的代码。

我认为我的问题是了解如何传递对指向传感器的文件描述符的引用。

请考虑我的软件中的此代码段。 (我确信此部分中存在错误。)

#include "readTemp.h"
#include <stdio.h>

int main() {
    int fd;
    fd = initGPIO(0,0x76);
    getTemp(fd);
    return(0);
}

和文件readTemp.C

int * initGPIO(int i2cBus,int i2cAddr){
    int *addr = malloc(sizeof(int));
    int fd;
    //Initialise GPIO
    if(gpioInitialise() < 0) {
        perror("Initialisation failed\n");
        exit(EXIT_FAILURE);
    }
    //Open the I2C bus
    fd = i2cOpen(i2cBus,i2cAddr,0);
    if(fd < 0) {
        perror("Device failed to  open\n");
        exit(EXIT_FAILURE);
    }
    //Send Reset
    if(i2cWriteByte(fd,CMD_RESET) != 0){
        perror("Error sending reset---\n");
    }
    addr = &fd;
    printf("3-%d\n",&addr);
    return(addr);
}

/*
 * Reads the calibration data from the PROMs on the sensor
 * Parameters - fd - File Descriptor of the i2c device
 *              *proms - Pointer to an array of 8 unsigned 16-bit integers
 */
static int getcalibdata(int *fd,u_int16_t *proms) {
    const int bytesToRead = 2;
    char buf[2] = {0};
    printf("2-%d\n",&fd);
    // Populate for each prom (7)
    for(int i = PROM_START; i < PROM_STOP; i = i + 2){
        // Write PROM read commands
        if(i2cWriteByte(*fd,i) != 0) {
            perror("Error writing PROM command!!\n");
            exit(EXIT_FAILURE);
        }
        // Read result from PROM
        if(i2cReadDevice(*fd,buf,bytesToRead) <= 0) {
            perror("Error reading from PROM\n");
            exit(EXIT_FAILURE);
        }
        // Store result in array
        proms[(i - PROM_START) / 2] = (buf[0] << 8) | (buf[1]);
    }
    return(0);
}

int getTemp(int *fd){
    u_int16_t proms[8];
    u_int32_t rawTemp = getRawTemp(fd);
    printf("%d\n",rawTemp);
    getcalibdata(fd,proms);
    for(int i = 0; i < 8; i++){
        printf("%d-%d\n",i,proms[i]);
    }
    int temp = calcTemp(rawTemp,proms);
    printf("---%d\n",temp);
    return 0;
}

代码可以编译,但是在运行时出现"Error writing PROM Command"错误。

我认为我的错误可能出在代码的一小部分,其中我将initGPIO()的结果分配给int,而该结果应该是指针。但是,当我这样做时,我的代码段就会出错。

jahy988 回答:通过C中的引用返回并传递文件描述符

您应该在此行收到编译器警告

    fd = initGPIO(0,0x76);

因为fd的类型为int,并且initGPIO返回并返回int*

如下更改initGPIO

int initGPIO(int i2cBus,int i2cAddr){
    int fd;
    //Initialise GPIO
    if(gpioInitialise() < 0) {
        perror("Initialisation failed\n");
        exit(EXIT_FAILURE);
    }
    //Open the I2C bus
    fd = i2cOpen(i2cBus,i2cAddr,0);
    if(fd < 0) {
        perror("Device failed to  open\n");
        exit(EXIT_FAILURE);
    }
    //Send Reset
    if(i2cWriteByte(fd,CMD_RESET) != 0){
        perror("Error sending reset---\n");
    }
    return fd;
}

说明:

文件描述符是标识打开文件的数字。由于initGPIO将返回文件描述符,而您在main中分配了文件描述符,则只需返回数字即可。您不需要指针。

如果要将fdmain传递到预期会修改fd的函数,则需要传递一个指针。

您在initGPIO中还有两个错误:

    int *addr = malloc(sizeof(int)); /* Now addr points to the allocated memory for an int. */
    int fd;
/* ... */
    addr = &fd; /* Now you overwrite addr with the address of the local variable fd.
                   This creates a memory leak. Using the address in main() would be
                   undefined behavior because the address of the local variable fd will
                   become invalid when the function returns.
                   To put the fd value into the allocated memory you would have to use
                   *addr = fd,but this is not necessary here as explained above. */
,

在C语言中没有引用机制。通过使用指针和间接寻址,它在某种程度上被模仿。

在上面的代码中,您返回的是保存fd值的变量的地址。由于fd是局部变量,因此在声明的函数外部通过其地址取消引用将导致SEGFAULT。现在还没有发生,但最终肯定会发生。相反,只需返回fd本身即可。

本文链接:https://www.f2er.com/3167429.html

大家都在问