2

我对 C 比较了解,我习惯于用 Java 编程,所以我发现 C 在涉及数组的方面有点困难。我仍然对这种情况感到困惑:

int a [];
int* a;
int *a;

在java中,我会做这样的事情来在函数中返回一个数组:

int [] returnArr(int [] a){
... modify a ...
return a;
}

int [] a = {...};
int [] b = returnArr(a); ##

我如何在 C 中做同样的事情,特别是带有## 的部分。

编辑:我有这个功能:

float *normalizeValues(float *v, float maxY){

    int size = sizeof(v) / sizeof(float);
    float max = findMax(v);
    float ratio = maxY / max;
    int i;
    for(i = 0; i < size ; ++i){
        v[i] = v[i] * ratio;
    }
    return v;
}

我正在做以下事情:

float vert [] = {306, 319, 360, 357, 375, 374, 387, 391, 391, 70, 82, 94, 91, 108, 114, 125, 127, 131};
int i = 0;
float *vert2;
vert2 = normalizeValues(vert, 0.7);

for(i = 0; i < sizeof(vert2) / sizeof(float); ++i){
    fprintf(stdout,": %f\n",vert2[i]);
}

并且输出只有 1 个元素。

4

5 回答 5

1

你不能。当函数返回时,堆栈帧将被清除(通常),并且您生成的数组将被破坏。但是,您可以编辑函数原型以接受指向要修改的数组的指针。这种函数参数称为“输出参数”。例子:

void function func(int a, int b, int[2] to_modify)
{
  to_modify[0] = a;
  to_modify[1] = b;
}
int main()
{
   int foo[2];
   func(1, 2, foo);
   printf("Result: foo[0] = %d, foo[1] = %d\n", foo[0], foo[1]);
   return 0; 
}

这将打印“结果:foo[0] = 1,foo[1] = 2”。

于 2013-04-22T03:51:58.800 回答
1

编辑:要直接回答您更新的问题:您必须传入数组的大小。C 没有像 Java 那样存储数组大小的机制。如果编译器知道数组的大小,因为数组是全局或局部变量,不是动态分配的,那么您可以使用 sizeof() 运算符。否则,您必须单独知道大小,或者在数组中使用标记值(例如末尾的 0.0 或 NULL)。

至于一般的数组、指针和参数,请参见下文:

您将返回一个指向数组的指针,该指针用 '*' 语法表示:

int *returnArr(int[] a) {
    // modify a...
    return a;
}

int a[] = { ... };
int *b;
b = returnArr(a);

需要注意的几点:

  • 您不能在涉及非常量表达式(例如,函数调用)的变量声明中进行赋值。不过,这可能在 C99 中有所改变。
  • 括号跟变量名之后,不像在 Java 中它们是类型的一部分。尽管 Java 的语法更加一致,但它在 C 中并不十分有意义,因为您经常在变量声明的括号中给出数组大小:

    int a[3] = { ... };

  • 没有办法指定一个函数返回一个数组而不是一个普通的指针。在 C 中,数组引用衰减为指针(尽管指针和数组不是一回事,正如通常所声称的那样)。这意味着每当您传递一个数组时,C 只提供一种方法来传递一个指向该数组的指针。整个数组实际上并没有被复制。碰巧,数组的名称也是指向数组第一个元素的指针。

另请注意 user268396 在他们的回答中所说的内容。如果您打算创建一个新数组并返回它,则需要动态分配数组,或者传入一个指向已分配数组的指针(无论如何,这似乎是您正在做的事情) .

于 2013-04-22T03:52:38.740 回答
1

希望这可以帮助

  #include<stdio.h>

    void change(int *c)/*Pointer c now has the first location of the array a[]*/
    {
      *(c+0) = 0;/*assign values to the array by adding step-size to the first array position*/
      *(c+1) = 1;
      *(c+2) = 2;
      *(c+3) = 3;
      *(c+4) = 4;
    }

    main()
    {
      int a[5]={10,20,30,40,50}; /* Declare and Assign an array a[] of size 5.*/
      int *b = a; /*Declare and assign a Pointer to the location of the array.*/
      change(b); /*pass the pointer(which is now pointing to first position of array) to the change() function.*/
      printf("%d,%d,%d,%d,%d,",a[0],a[1],a[2],a[3],a[4]);/*Print the changed value.*/
    }

输出:0,1,2,3,4,

从 Java 的角度来看,指针只是(不完全是)对象引用。

Object O;

O = New SomeClassName();

就像对象引用 O 指向 SomeClassName 类型的一些实际对象一样,C 中的指针也是如此:

int *b;
b = &a;

变量 b 只是指向 a 的地址位置。深入研究数组概念:

int a[5];
int *b = a;

这里我们只是说像Mr.*b指向组a的第一个位置,即a[0]

现在 C 中的 power 指针是从现在开始的,在此之后:

*b means a[0]
*(b+1) means a[1]
*(b+2) means a[2]
*(b+3) means a[3]
*(b+4) means a[4]

这意味着你改变了 *(b+4),你正在改变 a[4]。

于 2013-04-22T03:59:12.370 回答
0
int* returnArr(int a[]){
    //modify a
    return a;
}

需要提及的是,当您在函数的参数列表中使用数组时,它将被转换为指针。所以在 main(...) 的声明中,char *argv[]实际上char **argv是相同的。在这种情况下,int a[]int*a 是相同的。但是数组和指针不是一回事。

以下面的代码为例:

int a[10];
int main(){
    int *p = a;
    p[5] = 4;
    return p[5];
}

p是一个指针,当我们访问p[i]时,注意p的地址不是a的地址,p的内容是a的地址。然后代码将:

  1. 访问内存得到p的内容,即a的地址。
  2. 根据 i 和指针(int)的类型计算偏移量。
  3. 访问内存以获得结果。

a是一个int数组,如果我们访问a[i],a的地址就是a[0]的地址,代码会:

  1. 根据 i 和 int 类型计算偏移量。
  2. 访问内存。

指针和数组是不同的类型。因此,如果您在一个文件中声明 int *p 并在该文件中使用它,但将 p 定义为另一个文件中的数组,则会导致问题。

您可能还想知道 int *p = a,在 ANSI 中,如果您使用数组(其名称)作为表达式,编译器会将其转换为指针,指向数组的第一个元素。

根据 Jim Balter 的评论更新:

如果您使用数组(其名称)作为表达式,编译器不会总是将其转换为指针,指向数组的第一个元素。例如,在 sizeof(p->q->a) 中,p->q->a 是一个表达式,但如果 a 是一个数组,它不会转换为指针。

"除非它是 sizeof 运算符或一元 & 运算符的操作数,或者是用于初始化数组的字符串字面量,否则类型为 ''array of type'' 的表达式将转换为类型为 ''pointer 的表达式键入指向数组对象的初始元素的''。

于 2013-04-22T03:54:09.867 回答
0

在 C 中,您只能在函数中返回数组的指针。例如,如果您想在函数中返回一个字符串(char 数组),您可以返回一个指向以 null 结尾的字符串的指针。如果要返回其他类型的数组(int,用户定义的结构等),可以分配一些内存来存储数组,并返回数组的指针,在参数中返回数组的大小。例子:

int *function(int *size)
{
    *size = 10;
    int *intP = (int *)malloc((*size)*sizeof(int));

    return intP;
}
于 2013-04-22T03:59:07.713 回答