9

我是 C 编程新手,这是我的问题:

我想将每个数组的第一个值存储在一个新数组中,然后将每个数组的第二个值存储在一个新数组中,依此类推。

我可以声明指针数组,但我不知道如何使用它!

请我需要帮助。

int main()
{
    int t1[4]={0,1,2,3};
    int t2[4]={4,5,6,7};
    int t3[4]={8,9,10,11};
    int t4[4]={12,13,14,15};
    int *tab[4]={t1,t2,t3,t4};
    int i,j,k,l;
    for (i=0; i<4;i++)
    {
        printf("%d\t", *tab[i]);
    }

    return 0;
}

当我这样做时,我只存储每个数组的第一个值。

4

4 回答 4

13

您的术语到处都是。我认为回答您的问题的最简单方法是逐行浏览您的代码。

int main()
{
int t1[4]={0,1,2,3};      //Declares a 4 integer array "0,1,2,3"
int t2[4]={4,5,6,7};      //Declares a 4 integer array "4,5,6,7"
int t3[4]={8,9,10,11};    //Declares a 4 integer array "8,9,10,11"
int t4[4]={12,13,14,15};  //Declares a 4 integer array "12,13,14,15"
int *tab[4]={t1,t2,t3,t4};//Declares a 4 pointer of integers array "address of the first element of t1, address of the first element of t2, ..."
int i,j,k,l;              //Declares 4 integer variables: i,j,k,l
for (i=0; i<4;i++)
 {
  printf("%d\t", *tab[i]); //print out the integer that is pointed to by the i-th pointer in the tab array (i.e. t1[0], t2[0], t3[0], t4[0])
 }

 return 0;
 }

在你循环之前,你所做的一切似乎都很好。您只显示每个数组的第一个整数,因为您没有通过它们。要遍历它们,您的代码应如下所示:

for (i=0; i<4;i++)
{
   for (j=0; j<4; j++)
   {
      printf("%d\t", *(tab[j] + i));
   }
}

上面的代码使用了两个循环计数器,一个 (the i) 遍历数组中的位置(数组中的第一个值,数组中的第二个值等);另一个通过不同的数组(j)。它通过检索存储在其中的指针tab[j]并创建一个具有正确偏移量的新指针来显示i第 th 列的值。这称为指针算术(这里有关于指针算术的附加信息

大多数人发现语法*(tab[j] + i)很笨拙,但它更能描述实际发生的事情。在 C 中,您可以将其重写为tab[j][i],这更常见。

于 2012-07-06T14:01:17.297 回答
3

您已按预期存储数据,您只需要正确访问它

for (i=0; i<4;i++)
{
  for (j = 0; j < 4; j++) {
    int* temp = tab[i];    
    printf("%d\t", temp[j]);      // or try the next line...
    printf("%d\t", *(temp + j));  // prints same value as above line
    printf("%d\t", tab[i][j];     // the same value printed again
  }
}   

以上所有内容都打印相同的值,只是使用指针算法访问该值的不同方式。的每个元素tab都是一个int*值,每个元素的值都是您int[]在开始时定义的其他数组的地址

编辑:响应 Jerome 的评论,您可以通过声明 4 个数组来实现

int tab1[4]={*t1,*t2,*t3,*t4};
int tab2[4]={*(t1+1),*(t2+1),*(t3+1),*(t4+1)};
int tab3[4]={*(t1+2),*(t2+2),*(t3+2),*(t4+2)};
int tab4[4]={*(t1+3),*(t2+3),*(t3+3),*(t4+3)};

现在tab1包含每个数组的第一个元素,tab2第二个元素,依此类推。然后你可以使用

 int *tttt[4]={tab1,tab2,tab3,tab4};
 for (i=0; i<4;i++) {
   for (j = 0; j < 4; j++) {
     printf("%d\t", tttt[i][j]);   
   }
 } 

打印你想要的。如果您像开始时那样声明另一个指针数组

  int* tab[4] = {t1,t2,t3,t4};

那么本质上在矩阵术语中,tttttab

于 2012-07-06T13:47:42.953 回答
1

你存储一切,但你只是不显示它。尝试

for (i=0; i<4;i++)
 {
  for (j=0; j<4; j++)
  printf("%d\t", *(tab[i]+j));
 }
于 2012-07-06T13:38:33.977 回答
1

int* (*a[5])[5][5][5]声明一个包含 5 个指针的数组,指向一个 3d 指针数组

int* (*(*a[5])[5])[5][5][5]声明一个由 5 个指针组成的数组,指向一个由 5 个指针组成的数组,指向一个指向 int 的 3d 指针数组。

#include <stdio.h>

int main()
{
    int t1[4]={0,1,2,3};
    int t2[4]={4,5,6,7};
    int t3[4]={8,9,10,11};
    int t4[4]={12,13,14,15};
    int (*tab[4])[4]={&t1,&t2,&t3,&t4};
    int i,j,k,l;
    for (i=0; i<4;i++)
    {
        printf("%d\t", (*tab[i])[1]);
    }

    return 0;
}

t2和之间有区别&t2。尽管它们具有相同的值,但它们的类型不同。int [4]int (*)[4]。编译器将抛出警告(clang)或错误(gcc)。

int a[4]从概念上讲,在编译器级别是指向 4 数组的指针以及数组本身 ( &a == a)。

int (*a)[4]从概念上讲,在编译器级别是指向 4 数组的指针以及指向数组本身的指针 ( a == *a),因为它指向上述情况成立的数组类型。

在运行时,如果一个int *int (*a)[4]指向同一个地址,它们在物理上是相同的——它只是一个地址,同一个地址。类型仅在编译器如何解释和生成具有该地址的算术运算以及它基于类型实际输出的程序集方面很重要。您可以将地址转换为您想要的任何类型,以实现所需的代码输出以在其保存的地址处操作数据。然而,int a[4]类型实际上是数组本身,但您使用它就像a在内存中有一个指向它的指针,该指针被赋予与数组本身相同的地址。指向的指针int a[4]意味着'指向地址范围的指针a编译器将其视为具有 int 元素宽度的数组,其中编译器将数组的开头视为指向数组的指针',并且对该类型的任何操作都将在解引用链中保持一致,即您必须如果类型是指向数组的指针,则在编译器级别使用 (*a)[0] 访问第一个元素,但是如果将相同的地址转换为,int *则需要使用 a[0] 访问该成员。

于 2020-06-08T00:07:37.333 回答