c - 如何将指针传递给数组而不衰减,并在野蛮人的函数中使用 'reference'?

标签 c pebble-watch pebble-sdk

我读过很多关于将数组传递给函数的讨论。它们似乎是为精通 C 的人编写的。我是一个尚未精通 C 的野蛮人。

根据我在其他讨论中读到的内容应该可以在没有指针衰减的情况下传递数组。然而,我需要帮助来实现这一点。

请给我一个简洁的示例,说明如何将数组作为指针的指针传递,并确定其在传递到的函数中的大小。

如果在函数中更改数组,我希望更改数组的源。我想尽量减少额外的内存分配。 而且,如果可能的话,我想调整函数内数组的大小。

此代码无需通过即可运行。

// this works
j = sizeof(hourLongs)/sizeof(hourLongs[0]);
i = 0; while (now > hourLongs[i] && i < j){i++;}  
hour = --i; 

这可以工作,但无法调整函数内数组的大小。

hour = compareToLongs(&now, hourLongs, (int)(sizeof(hourLongs)/sizeof(hourLongs[0])) ); 

// long *, long * , int -> int 
// compare time to array of times.
static int compareToLongs(long * time, long * timeList_pointer, int size){
  i = 0; while (*time> (timeList_pointer)[i] && i < size){i++;}  
  return --i;
}

我想以一种允许我在函数中找到它的大小的方式传递数组。类似于以下内容,减去我的错误。

hour = compareToLongs(&now, &hourLongs); 

// long *, (long (*) [])*  -> int 
// compare time to array of times.
static int compareToLongs(long * time, long ** timeList_pointer){
  int size = (int)(sizeof(*timeList_pointer)/sizeof(*timeList_pointer[0]));
  i = 0; while (*time> (i < size && *timeList_pointer)[i]){i++;}
  free(size);  
  return --i;
}

编辑:hourLongs 是一个长整数数组。

编辑:关于标题,我在白话中使用了“引用”一词,以便其他像我这样的野蛮人可以找到问题。

编辑:我真的在寻找一种方法来调整函数内整数数组的大小。

sizeof(array)

给 sizeof() 一个允许确定大小的地址。这就是我想传递给我的函数的地址。

是否有原因导致我无法将传递给 sizeof() 的内容传递给我的函数?

编辑:由于 sizeof() 的操作表明可以在没有“指针衰减”的情况下传递数组。 user529758 在 this discussion 中给出了三个示例

in C99 there are three fundamental cases, namely:
1. when it's the argument of the & (address-of) operator.
2. when it's the argument of the sizeof operator.
3. When it's a string literal of type char [N + 1] or a wide string literal of type wchar_t [N + 1] (N is the length of the string) which is used to initialize an array, as in char str[] = "foo"; or wchar_t wstr[] = L"foo";.

我想要做的事情应该可以使用&array来实现。

最佳答案

C中,您无法在被调用函数中找到数组的大小。调用函数必须再传递一个参数来说明数组的大小。


让我们看一些例子来看看为什么这是不可能的。

首先在调用函数时,您将尝试将数组作为参数传递。但是,请注意,当您将数组作为参数传递时,它会自动变为指向其元素数据类型的指针。这将阻止被调用的函数使用sizeof运算符计算数组的大小。

例如,

int main(void)
{
    int arr_a[2] = {22, 33};
    int arr_b[5] = {6, 7, 8, 9, 10};

    foo(arr_a); // Here arr_a decays to an `int *`
    foo(arr_b); // Here arr_b decays to an `int *` too

    return 0;
}

void foo(int *arr)
{
    sizeof(arr); 
    /* Here sizeof(arr) will always give the size of 
     * an `int *` which maybe 4 or 8 bytes depending
     * on platform. It does not matter weather arr_a
     * or arr_b was passed from main.   
     * And because sizeof(arr) always gives the sameresult, 
     * we cannot use sizeof(arr)/sizeof(arr[0]) to calculate 
     * the size of array that was passed.
     */

     /* This value will always be the same, 
      * regardless of what was passed */
     sizeof(arr)/sizeof(arr[0]); 

}

另外,请注意:

void foo(int arr[]) { ... }

相当于:

void foo(int *arr) { ... }

编译器会默默地将 int arr[] 更改为 int *arr。因此,将 int arr[] 作为参数不会有任何区别。

接下来,您可能会考虑传递数组的地址(通过执行&arr_name)。但是,请注意,&arr_name 是一个指向数组(具有一定大小)的指针,它与指向数组的指针不同指向基础数据类型的指针。这次你做了这样的事情。

void foo(void) {
    int arr_a[2] = {22, 33};
    int arr_b[3] = {7, 8, 9};
     bar(&arr_a); // Note here that type of `&arr_a`  is `int (*)[2]`,
                  // i.e. a `pointer to int array of 2 elements`, which is
                  // different from a `pionter to pointer to int`

     bar(&arr_b); // Note here that type of `&arr_b`  is `int (*)[3]`,
                  // i.e. a `pointer to int array of 3 elements`, which is
                  // different from a `int (*)[2]`, 
                  // i.e a `pointer to int array of 2 elements`
                  // Note that this will give ERROR. See comments in bar()
    return 0;
}

void bar(int (*arr)[2]) {
     /* 
      * The caller of this function can ONLY pass int arrays with
      * 2 elements. Caller CANNOT pass int array with 3 elemens, or
      * 1 element, or 5 element.
      * This means you ALWAYS KNOW the size of arrays being passed,
      * and although you can calculate the size by doing
      * sizeof(*arr)/sizeof(*arr[0]); 
      * There is no point in calculating it - you alreay know the size 
      */
}

所以,基本上你甚至不能通过传递&array_name来传递指向数组的指针来解决这个问题,因为你将需要不同的函数来接受不同大小的数组。例如,void bar_2(int (*arr)[2]) {...} 接受指向 2 个整数的数组的指针,以及 void bar_3(int (*arr)[3]) {...} 接受指向 3 个整数的数组的指针。此外,在这些函数中计算大小是没有意义的,正如您已经知道的那样。

最后,您将尝试传递一个指向底层数据类型的指针。所以你做类似的事情:

void foo() {
    int arr_a[2] = {22, 33};
    int arr_b[5] = {6, 7, 8, 9, 10};
    int *ptr;
    ptr = &arr_a[0];
    bar(&ptr); // Passing pointer to pointer to int (int **)
    ptr = &arr_b[0];
    bar(&ptr); // Passing pointer to pointer to int (int **)
}

void bar(int **pptr) {
    sizeof(*pptr);
    /* This will always be the same. 
     * i.e. the size of an integer pointer 
     * So here again you cannot use 
     * sizeof(*pptr)/sizeof((*pptr)[0]) to calculate the size
     * as it will always give the same result */

     sizeof(*pptr)/sizeof((*pptr)[0]) // Always same, no matter what was
                                      // passed by the caller
}

您会发现,传递指向基础数据类型的指针也不能解决此问题。

因此,您会看到,无论您做什么,都无法通过在被调用函数中使用 sizeof() 找到数组的大小。 仅当调用者传递此信息时,被调用函数才能知道数组的大小。


顺便说一句,您的代码存在问题。当你在做的时候

 i = 0; while (now > hourLongs[i] && i < j){i++;}  // AND
 i = 0; while (*time> (timeList_pointer)[i] && i < size){i++;} 

while 循环中的条件顺序应该相反。应该是

 i = 0; while ( i < j && now > hourLongs[i]){i++;}  // AND
 i = 0; while (i < size && *time> (timeList_pointer)[i]){i++;} 

这是因为,您必须首先检查 i 是否在数组范围内,然后仅计算 hourLongs[i](timeList_pointer) [i].

关于c - 如何将指针传递给数组而不衰减,并在野蛮人的函数中使用 'reference'?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38858594/

相关文章:

c - 从文件中读取数据到C中的结构

c - 如何在 Pebble watch 中创建表格

c - 卵石时间颜色配置

c - 如何在 C 中存储字节数组?

c - openmp 代码执行期间的 "cygwin_exception::open_stackdumpfile error"

python - 检查解释器是否嵌入

c - 如何在获取输入的同时在数字数组中创建实时动态内存分配?

c - 将取消引用的指针(即按值)传递给需要指针的函数

pebble-watch - 获取请勿打扰设置

JSON 不会编译,给出 : "Expecting ' STRING', 'NUMBER' , 'NULL' , 'TRUE' , 'FALSE' , '{' , 06791045 "错误