通过uint32_t数组指针

时间:2015-05-08 03:12:21

标签: c malloc uint32-t

我在一个函数中使用malloc时遇到困难,我在这个函数中读取了一个带有4字节无符号整数的二进制文件,释放了传递的数组引用,将其重新映射到新的大小,然后尝试访问该数组的成员。我认为问题是由于uint32_t类型,因为数组似乎被视为一个8字节整数而不是4字节整数的数组。不完全确定我出错的地方,可能是使用malloc,IE可能我需要指示它以与我正在做的不同的方式创建uint32_t类型,或者可能是其他东西。代码:

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <string.h>
#include <stdint.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <malloc.h>

int filecheck (uint32_t **sched, int * count) {
    int v, size = 0;
    FILE *f = fopen("/home/pi/schedule/default", "rb");
    if (f == NULL) { 
        return 0; 
    } 
    fseek(f, 0, SEEK_END);
    size = ftell(f);
    fseek(f, 0, SEEK_SET);
    int schedsize = sizeof(uint32_t);
    int elementcount = size / schedsize;
    free(*sched);
    *sched = malloc(size);
    if (elementcount != fread(sched, schedsize, elementcount, f)) { 
        free(*sched);
        return 0;
    } 
    fclose(f);
// This works correctly and prints data as expected
    for (v=0;v<elementcount;v++) { 
        printf("Method 1 %02d %u \n", v, ((uint32_t*)sched)[v]);
    }

// This skips every other byte byt does not print any numbers > 32 bit unsigned
    for (v=0;v<elementcount;v++) { 
        printf("Method 2 %02d %u \n", v, sched[v]);
    }
// This treats the binary file as if it was 64 bit uints, printing 64 bit numbers
    for (v=0;v<elementcount;v++) { 
        printf("Method 3 %02d %lu \n", v, sched[v]);
    }
    *count = elementcount;
    return 1;
}

int main (){
    uint32_t *sched = NULL;
    int i, count = 0;
    if (filecheck(&sched, &count)) {
        for (i=0;i<count;i++) { // At the next line I get a segmentation fault
            printf("Method 4 %02d %u\n", i, sched[i]);
        }
    } else {
        printf("Error\n");
    }
    return 0;
}

我按要求添加了文件读取代码。尝试以我正在做的方式访问main()中的数组sched将打印我正在读取的数据,就像它是8字节整数一样。所以我猜sched被看作是64位整数的数组而不是32位,因为我已经将其定义为。我想这是因为我释放它并再次使用malloc。但我相信我已经指示malloc它应该创建的类型是uint32_t所以我很困惑为什么数据没有被这样处理。

编辑:找到一种让它工作的方法,但不确定它是否正确(方法1)。这是将此数组视为uint32_t类型的唯一且最干净的方法吗?当然,编译器应该知道我正在处理什么类型,而不必每次使用它时都要使用它。

编辑:实际上当我尝试在main中访问它时,我得到一个seg错误。我在代码中添加了一条注释来反映这一点。之前我没有注意到这一点,因为我在几个地方使用for print循环来跟踪编译器如何查看数据。

编辑:不确定是否有办法添加二进制数据文件。我是在十六进制编辑器中手工制作它的确切内容并不重要。在bin文件中,FF FF FF FF FF FF FF FF应读取为2 uint32_t类型,而不是1 64位整数。 Fread AFAIK并不关心这一点,它只是填充缓冲区,但如果错误则需要纠正。

TIA,Pete

1 个答案:

答案 0 :(得分:1)

// This works correctly and prints data as expected
    for (v=0;v<elementcount;v++) { 
        printf("Method 1 %02d %u \n", v, ((uint32_t*)sched)[v]);
    }

这不太对,因为scheduint32_t**,而您已分配到*sched。还因为%u不是您应该如何打印uint32_t。 首先取消引用sched,然后应用数组索引访问。

您想要printf("%02d %"PRIu32"\n", v, (*sched)[v]));

// This skips every other byte byt does not print any numbers > 32 bit unsigned
    for (v=0;v<elementcount;v++) { 
        printf("Method 2 %02d %u \n", v, sched[v]);
    }

是的,那是因为sched[v]uint32_t*,因为它是指针类型而你可能在64位机器上运行,所以#&} 39;可能是64位...所以你以8字节为增量而不是4字节增量进行迭代,并尝试将指针打印为%u。它也超出范围,因为8 * 10大于4 * 10,这可能会导致分段错误。

// This treats the binary file as if it was 64 bit uints, printing 64 bit numbers
    for (v=0;v<elementcount;v++) { 
        printf("Method 2 %02d %lu \n", v, sched[v]);
    }

这就像第二个例子,只有您使用稍微合适但仍然不正确%lu进行打印。

您需要fread()进入*sched而不是sched,否则您将导致UB,这很可能会在您尝试阅读时导致分段错误数组

另外,你的for循环中的for循环应该永远不会运行,因为你没有将count设置为filecheck中的任何内容所以它应该仍然为零(至少在没有UB的情况下)

其他评论:

  • 正如您刚刚学到的那样,请不要将malloc()的结果投射到C中。
  • main()应该返回一个值。 0如果一切顺利的话。{/ li>
  • 当然,您可以使用uint32_t将一些fwrite()作为字节写入文件。
  • 检查malloc()的结果,看看是否成功。
  • 使用size_t代替size_t值代替int,并相应地打印(%zu)。