将C套接字数据接收到分配的2D数组

时间:2018-08-13 12:04:59

标签: c arrays sockets pointers calloc

我试图用从套接字接收的数据填充分配给我的数组,但是无法使其正常工作。当我定义并通过以下方式获取数据时:

uint16_t data[2048];
recv(network_socket, &data, sizeof(data), 0);

可以正确接收数据,但是当我尝试通过分配的数组进行操作时:

int i;
int N = 3;
int M = 2048;
int **matrix; 

matrix = (int **)calloc(N, sizeof(int *));

for (i=0; i<N; i++) {
    matrix[i] = (int *)calloc(M, sizeof(uint16_t));
}

for (i=0; i<N; i++) {
    recv(network_socket, matrix[i], sizeof(data), 0);
}

我感觉到最后出现了问题。据我了解,matrix[i]的末尾获得指向行i开头的指针,并且应该为recv()工作,但这可能是我在这里出错的地方。

编辑:当我尝试printf("Number: %" PRIu16 "\n", matrix[a][b]);时,在第二部分中会得到一些大字号,printf("Number: %" PRIu16 "\n", data[a]);首先效果很好。

3 个答案:

答案 0 :(得分:3)

您在第一个代码中告诉您要一个16位无符号整数数组并接收它们。一切都很好。

在第二个代码中,您需要一个int数组,它们可能不是您平台上的16位。然后,根据它们的16位值为它们分配一定数量的内存,并读取未公开的数据量。

然后,您尝试以int的形式访问它们,这显然会导致将两个uint16_t值合并为一个int(如果您的系统是32位,甚至在64位系统上为四个)。

修复代码,使其像第一个一样使用uint16_t,它实际上会知道如何处理16位数据。由于您尝试访问分配的范围之外的内存,因此您当前的代码甚至将具有未定义的行为。

答案 1 :(得分:2)

评论和其他答案指出了与type一致性(建议使用intuint16_t而不建议混合使用)和分配内存有关的一些潜在问题。

关于内存创建的建议
为了简化和提高可读性,尤其是在希望模拟数组的多个维度时,请考虑将内存创建封装到一个函数中。例如:

uint16_t ** Create2D(int c, int r)
{   
    uint16_t **arr;
    int    y;

    arr   = calloc(c, sizeof(uint16_t *));
    for(y=0;y<c;y++)
    {
        arr[y] = calloc(r, sizeof(uint16_t));   
    }
    return arr;
}

这样调用函数:

uint16_t ** matrix = Create2D(N, M);
if(matrix)//always good to check return of [c][m]alloc before using
{
    // Use allocated memory
    ...

注意:

  • 此示例不会创建2D矩阵,而是模拟 一。 (如 HERE 所述)。实际上,它只是一个指向指针集合的指针,每个指针都指向分配的内存,这样它们的内容就可以使用行列表示法访问,就像创建时一样:

uint16_t array[N][M];

释放此内存也可以以封装形式实现。例如:

void free2D(uint16_t **arr, int c)
{
    int i;
    for(i=0;i<c;i++)
    {
        free(arr[i]);
    }
    free(arr);
}  

答案 2 :(得分:1)

int **matrix; 

matrix = (int **)calloc(N, sizeof(int *));
...

由于上面的代码不是2D数组,而是分段的,基于指针的查找表,因此代码不起作用。因此,它与数组一点也不兼容。

没有理由在这里需要这样的查找表。问题可能源于对如何Correctly allocating multi-dimensional arrays的困惑。