【问题标题】:passing a 2d-array to a function in c language, what is the difference between int* b[4] and int b[][4]?将二维数组传递给c语言中的函数,int * b [4]和int b [] [4]有什么区别?
【发布时间】:2021-06-18 10:09:30
【问题描述】:

我正在尝试移动二维数组的行:

#include <stdio.h>
#include <string.h>

void shift_to_left(int* b[4], int* new_col){
  for(size_t i=0; i<1; i++)
    memcpy(*(b+i+1), *(b+i), sizeof(int)*4);
  memcpy(*(b+1), new_col, sizeof(int)*4);
}

int main(){
  int a[4] = {1, 2, 3, 4};
  int b[2][4] = {{7, 8, 4, 5}, {8, 9, 5, 1}};

  printf("Before: \n");
  for(int i=0; i<2; i++){
    for(int j=0; j<4; j++)
      printf("%d ", b[i][j]);
    printf("\n");
  }

  shift_to_left(b, a);

  printf("After: \n");
  for(int i=0; i<2; i++){
    for(int j=0; j<4; j++)
      printf("%d ", b[i][j]);
    printf("\n");
  }
}

我收到一条警告,告诉我函数 shift_to_left() 需要一个双指针,但得到了一个数组:

array_to_pointer.c: In function ‘main’:
array_to_pointer.c:38:17: warning: passing argument 1 of ‘shift_to_left’ from incompatible pointer type [-Wincompatible-pointer-types]
   shift_to_left(b, a);
                 ^
array_to_pointer.c:20:6: note: expected ‘int **’ but argument is of type ‘int (*)[4]’
 void shift_to_left(int* b[4], int* new_col)

当我忽略警告并运行代码时,出现分段错误:

Before: 
7 8 4 5 
8 9 5 1 
Segmentation fault (core dumped)

当我将函数的原型从 void shift_to_left(int* b[4], int* new_col) 更改为 void shift_to_left(int b[][4], int* new_col) 时,分段错误消失了:

Before: 
7 8 4 5 
8 9 5 1 
After: 
7 8 4 5 
1 2 3 4

但是在这两种情况下,memcpy(*(b+i+1), *(b+i), sizeof(int)*4); 都不起作用(数组 b 的第一行保持不变)。

将数组传递为int* b[4] 和将其传递为int b[][4] 有什么区别?

在这种情况下 memcpy 有什么问题?

【问题讨论】:

  • 'int b[][4]' 在此上下文中与 'int (*b)[4]' 相同
  • 您刚刚发现了为什么使用 1D 数组和模拟 2D 几乎总是比实际使用 2D 数组或数组数组更好。您可以一次性复制一维数组,非常简单。不需要循环。
  • 提示:不要使用*(x+n),而是使用x[n]。语法更加整洁,对于熟悉 C 指针以及它们如何像数组一样工作的人来说更有意义。
  • @tstanisl 将括号放在 b 周围解决了这个问题! int b[4] 是一回事, int (*b)[4] 是另一回事。 memcpy 是怎么回事?

标签: arrays c pointers memory


【解决方案1】:

int* b[4] 是一个由 4 个 int 指针组成的数组。 int (*b)[4] 是一个指向一组 4 个整数的数组的指针,int b[][4] 也是如此。

实际上,相同的记忆被解释为以下两种方式之一:

// int* b[4] (4x 64-bit pointers)
[aaaaaaaabbbbbbbbccccccccdddddddd]
 ^ int* |^ int* |^ int* |^ int*

// int (*b)[4] (Nx 4x int)
[1111222233334444111122223333444411112222333344441111222233334444...]
 ^ int[4]       |^ int[4]       |^ int[4]       |^ int[4]

int[4] 视为指针会在取消引用时立即导致分段错误。这不是一个有效的指针。

如果您打开警告(在许多编译器上为-Wall),您将收到类似这样的消息,提醒您注意问题:

24d.c:21:17: warning: incompatible pointer types passing 'int [2][4]' to parameter of type 'int **' [-Wincompatible-pointer-types]
  shift_to_left(b, a);

如果您对 C 尽力做到的事情感到困惑,请使用像 cdecl 这样的解码器。

【讨论】:

    猜你喜欢
    • 2023-01-24
    • 2014-10-19
    • 2010-10-11
    • 1970-01-01
    • 2022-11-27
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2021-07-02
    相关资源
    最近更新 更多