为什么需要一个指针数组作为参数传递与数组类型参数的函数之前定投? [英] Why does a pointer to array need to be cast before being passed as parameter to a function with array type argument?

查看:127
本文介绍了为什么需要一个指针数组作为参数传递与数组类型参数的函数之前定投?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在C99,那为什么声明一个变量 P 为指针数组需要之前它是作为一个参数与数组类型参数的函数传递给定投,但声明一个变量 p 为空指针然后转换为一个指针数组可以作为指针传递给数组相同的功能?

 的#include<&stdio.h中GT;INT arreglo(INT locArr [])
{
    locArr [0] = 1;
    的printf(厄尔尼诺arreglo ES:%I \\ N,locArr [0]);
    返回0;
}诠释的main()
{
    / *声明一个指针p为数组* /
    INT(* P)[];    INT manArr [10];    P =&放大器; manArr; / *分配manArr的ADRESS如下情况下* /    / *这里传递指针p是不允许的预期,
       因为我们的函数为int *作为参数* /    / *所以我需要做一个铸造* /
    arreglo(为(int *)p);
}/ * **但是在这个其他主要功能** * /诠释的main()
{
    / *声明一个空指针* /
    无效* p = NULL;    / *从对做一个铸件作废,p来数组* /
    P =(INT(*)[])P;    INT manArr [10];    P =&放大器; manArr; / * assing阵列manArr的ADRESS如在上述情况下* /    / *现在给出的指针数组作为参数的功能WORKS¡¡,
       为什么?。由于之前该函数需要为int *作为参数不
       一个指针阵列* /    arreglo(P);}


解决方案

下面是你的code的一个直接的适应性,结合的两个变种的main()成一个使用变量 p

 的#include<&stdio.h中GT;静态INT计数= 0;
静态INT arreglo(INT locArr [])
{
    locArr [0] = ++计数器;
    的printf(厄尔尼诺arreglo ES:%I \\ N,locArr [0]);
    返回0;
}INT主要(无效)
{
    INT manArr [10];
    INT(* P)[] =&放大器; manArr;    / *这里传递指针p是不允许的预期,因为
    **功能为int *作为参数,所以我需要投它...
    * /
    arreglo(为(int *)p);
    的printf(manArr [0] =%d个\\ N,manArr [0]);    / *或者,由于p是一个指针数组,* p是数组,
    **可以直接通过没有投。
    * /
    arreglo(* P);
    的printf(manArr [0] =%d个\\ N,manArr [0]);    无效* Q = NULL;    / *这是一个无操作* /
    Q =(INT(*)[])问; / *得自q转换为void为q数组* /    Q =&放大器; manArr; / *分配阵列manArr的地址如上* /    / *现在给出的指针数组作为参数传递给函数WORKS¡¡
    **为什么?由于之前该函数需要为int *作为参数不
    **一个指针数组
    * /
    arreglo(Q);
    的printf(manArr [0] =%d个\\ N,manArr [0]);    / *转换虚空*返回一个指针数组,然后取消对它的引用* /
    arreglo(*(INT(*)[])Q);
    的printf(manArr [0] =%d个\\ N,manArr [0]);    返回0;
}

您不能错过的原因 P arreglo()没有一个塑像是该类型'指针 INT 阵'是不一样的指针 INT ',参数的功能相当于一个指针 INT 。你投重挫编译器与你同意,你过关了,因为即使 P 的类型不正确,它的值(字节地址)是一样的该函数需要数组的起始单元的地址。正如在评论中指出,因为你有一个指向数组的指针和函数需要一个数组,你可以通过 * P 没有任何投是必要的。

无效* 版本(AB)使用了一个事实,即无效* 可以转换为任何其他指针没有在C强制转换为对象类型(C ++将需要转换)。因为你使用无效* 编译器不能发出警告。同样,你过关了,因为字节地址&放大器; manArr 相同的字节地址&放大器; manArr [0] ,即使类型是不同的。请注意,显式类型转换(回指针数组),然后提领的作品。

要与无效* 谨慎;它失去类型信息。它可以是一个福音;它还可以隐藏大问题。

通常情况下,不使用指针在所有阵列 - 他们的类型的C万神殿的深奥部分存在。你通常会写code,如:

 的#include<&stdio.h中GT;静态INT计数= 0;静态INT arreglo(INT locArr [])
{
    locArr [0] = ++计数器;
    的printf(厄尔尼诺arreglo ES:%I \\ N,locArr [0]);
    返回0;
}INT主要(无效)
{
    INT manArr [10];
    为int * p = manArr;    arreglo(P);
    的printf(manArr [0] =%d个\\ N,manArr [0]);
    返回0;
}

这是更容易理解。

In C99, why is it that declaring a variable p as pointer to array needs to be cast before it is passed as a parameter to a function with array type argument, but declaring a variable p as void pointer then casting it to a pointer to array can be passed as pointer to array to the same function?

#include <stdio.h>

int arreglo(int locArr[])
{
    locArr[0]=1;
    printf("el arreglo es : %i\n",locArr[0]);
    return 0;
}

int main()
{
    /* Declare a pointer p to array */
    int (*p)[];

    int manArr[10];

    p=&manArr;   /* assign the adress of manArr as case below */

    /* Here passing pointer p is not allowed as expected,
       since our function has int* as argument */         

    /* so I need to do a casting */
    arreglo((int*)p);   
}

/* **But in this other main function**: */

int main()
{
    /* Declare a void pointer  */
    void *p=NULL;

    /* Do a casting from p to void to p to array */
    p=(int (*)[])p;

    int manArr[10];

    p=&manArr;  /* assing the adress of the array manArr as in above case */

    /* Now given the pointer to array as parameter to function WORKS¡¡,
       why?. As before the function expects int* as argument not
       a pointer to an array */  

    arreglo(p);

}

解决方案

Here is a straight-forward adaptation of your code, combining the two variants of main() into one by using variables p and q:

#include <stdio.h>

static int counter = 0;
static int arreglo(int locArr[])
{
    locArr[0] = ++counter;
    printf("el arreglo es: %i\n", locArr[0]);
    return 0;
}

int main(void)
{
    int manArr[10];
    int (*p)[] = &manArr;

    /* Here passing pointer p is not allowed as expected, since
    ** the function has int* as argument so I need to cast it...
    */
    arreglo((int*)p);
    printf("manArr[0] = %d\n", manArr[0]);

    /* Or, since p is a pointer to an array, *p is the array,
    ** which can be passed directly without a cast.
    */
    arreglo(*p);
    printf("manArr[0] = %d\n", manArr[0]);

    void *q = NULL;

    /* This is a no-op */
    q = (int (*)[])q;   /* Cast from q to void to q to array */

    q = &manArr;  /* assign the address of the array manArr as above */

    /* Now given the pointer to array as parameter to function WORKS¡¡
    ** Why?. As before the function expects int* as argument not
    ** a pointer to an array
    */
    arreglo(q);
    printf("manArr[0] = %d\n", manArr[0]);

    /* Convert the void * back to a pointer to array, then dereference it */
    arreglo(*(int (*)[])q);
    printf("manArr[0] = %d\n", manArr[0]);

    return 0;
}

The reason you could not pass p to arreglo() without a cast was that the type 'pointer to array of int' is not the same as 'pointer to int', and the parameter to the function is equivalent to a 'pointer to int'. Your cast bludgeoned the compiler into agreeing with you, and you get away with it because even though the type of p is incorrect, its value (byte address) is the same as the address of the start element of the array which the function expects. As noted in the comments, since you have a pointer to an array and the function expects an array, you can pass *p without any cast being necessary.

The void * version (ab)uses the fact that a void * can be converted to any other pointer to object type without a cast in C (C++ would require a cast). The compiler is not able to warn you because you're using void *. Again, you get away with it because the byte address of &manArr is the same as the byte address of &manArr[0], even though the type is different. Note that the explicit cast (back to pointer to array) and then dereferencing works.

Be cautious with void *; it loses type information. It can be a boon; it can also hide major problems.

Normally, you don't use pointers to arrays at all — they exist in the 'esoterica' section of the C pantheon of types. You'd normally write code such as:

#include <stdio.h>

static int counter = 0;

static int arreglo(int locArr[])
{
    locArr[0] = ++counter;
    printf("el arreglo es: %i\n", locArr[0]);
    return 0;
}

int main(void)
{
    int manArr[10];
    int *p = manArr;

    arreglo(p);
    printf("manArr[0] = %d\n", manArr[0]);
    return 0;
}

Which is much simpler to understand.

这篇关于为什么需要一个指针数组作为参数传递与数组类型参数的函数之前定投?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆