【问题标题】:c incompatible types in assignment, problem with pointers?c 赋值中的类型不兼容,指针有问题吗?
【发布时间】:2011-02-04 07:38:39
【问题描述】:

您好,我正在使用 C,我有一个关于分配指针的问题。

struct foo
{
   int _bar;
   char * _car[SOME_NUMBER]; // this is meant to be an array of char * so that it can hold pointers to names of cars
}

int foofunc (void * arg)
{
   int bar;
   char * car[SOME_NUMBER];

   struct foo * thing = (struct foo *) arg;

   bar = thing->_bar; // this works fine
   car = thing->_car; // this gives compiler errors of incompatible types in assignment
}

car 和 _car 具有相同的声明,为什么我会收到有关不兼容类型的错误?我的猜测是它与它们是指针有关(因为它们是指向 char * 数组的指针,对吗?)但我不明白为什么这是一个问题。

当我声明 char * car; 而不是 char * car[MAXINT]; 时,它编译得很好。但是当我需要使用索引访问某些信息时,我看不出这对我有什么用处,以后访问该信息会很烦人。事实上,我什至不确定我的方法是否正确,也许有更好的方法来存储一堆字符串而不是使用 char * 数组?

编辑:我不是故意使用 INT_MAX(int 的最大值),它只是其他一些 int,大约是 20。

【问题讨论】:

    标签: c struct pointers void


    【解决方案1】:

    car_car 都是数组,您不能在 C 中分配数组(除非数组嵌入在结构(或联合)中并且您执行结构分配)。

    它们也是指向 char 的指针数组,而不是指向 char 数组的指针。您在代码中编写的内容可能就是您想要的 - 您可以在数组中存储指向最多 MAXINT 个名称的指针。但是,您应该正确地描述类型 - 作为指向 char 或 char 指针的指针数组。

    指向字符数组的指针如下所示:

    char (*car)[MAXINT];
    

    指向字符指针数组的点(谢谢,Brian)如下所示:

    char *(*car)[MAXINT];
    

    小心 MAXINT;这可能是一个非常大的数组(在 Linux 上,<values.h>MAXINT 定义为 INT_MAX,至少为 231-1)。


    代码如下:

    struct foo
    {
       int _bar;
       char * _car[MAXINT];
    }
    
    int foofunc (void * arg)
    {
       int bar;
       char * car[MAXINT];
       struct foo thing = (struct foo *) arg;
       bar = arg->_bar; // this works fine
       car = arg->_car; // this gives compiler errors of incompatible types in assignment
    }
    

    对 bar 和 car 的赋值都不应该编译 - argvoid *。您大概打算以某种形式或形式使用thing。正如 Brian 指出的那样,那里也存在问题:

    你要么想要:

    int foofunc(void *arg)
    {
        int bar;
        char *car[MAXINT];
        struct foo thing = *(struct foo *)arg;
        bar = thing._bar; // this works fine
        car = thing._car; // this is still an array assignment
        ...other code using bar and car...
    }
    

    或者你想要的:

    int foofunc(void *arg)
    {
        int bar;
        char *car[MAXINT];
        struct foo *thing = (struct foo *) arg;
        bar = thing->_bar; // this works fine
        car = thing->_car; // this is still an array assignment
        ...other code using bar and car...
    }
    

    或者,确实:

    int foofunc(void *arg)
    {
        struct foo *thing = (struct foo *) arg;
        int bar           = thing->_bar; // this works fine
        char *car[MAXINT] = thing->_car; // this is still an array assignment
        ...other code using bar and car...
    }
    

    最后,处理数组赋值,在C中你可以合理地使用memmove()来做到这一点:

    int foofunc(void *arg)
    {
        struct foo *thing = (struct foo *) arg;
        int bar           = thing->_bar; // this works fine
        char *car[MAXINT];
        memmove(car, thing->_car, sizeof(car));
        ...other code using bar and car...
    }
    

    如果要复制的区域重叠,类似的函数memcpy()没有可靠的语义,而memmove()有;始终使用memmove() 会更简单,因为它始终可以正常工作。在 C++ 中,您需要谨慎使用memmove()(或memcpy())。在这段代码中,它已经足够安全了,但理解其中的原因并非易事。

    您确实需要注意,您只是在此处复制指针 - 您不是在复制指针指向的字符串。如果有其他东西改变了这些字符串,它会影响通过car 看到的值和调用代码中的变量。

    最后一点 - 现在:您确定需要将函数的参数作为 void * 吗?如果将函数声明为采用“struct foo *”(甚至是“const struct foo *”),它会向各种滥用代码敞开大门。

    【讨论】:

    • 我认为他想要一个指向 char 的指针数组,因为每个指向 char 的指针似乎代表一个汽车名称。不过,Brian 有一个观点,他也许可以使用指向数组的指针,而不是复制它。
    • @Matthew:我同意他可能想要他在代码中编写的内容。然而,他对他拥有的东西的描述是错误的——这正是我想说的(但显然不够清楚)。
    • 指向字符数组的指针与指向字符指针数组的指针不同。
    【解决方案2】:

    您不能按照您的方式分配给数组。您可以按元素进行复制。

    for(int i = 0; i < MAXINT; i++)
    {
      car[i] = (arg->_car)[i]
    }
    

    请注意,如果字符串不是常量,您可能需要使用strcpy

    【讨论】:

    • 如果他使用strcpy(),他必须小心确保他的空间用于复制字符串。但是,如果字符串不是恒定的,那么在一个地方(通过一个变量)所做的更改可能会在另一个地方出乎意料地出现(另一个变量指向的字符串也会改变,因为两组指针都指向同一个空间)。
    【解决方案3】:

    您正在创建一个大小为 MAXINT 的新数组。我认为您想创建一个指向大小为 MAXINT 的数组的指针。

    创建一个指向 char* 数组的指针:

    以下是一个大小为 MAXINT 到 char* 元素的数组:

    char * car[MAXINT]; 
    

    下面是一个指针:一个大小为 MAXINT 的数组,指向 char* 元素:

    char* (*car)[MAXINT];
    

    以下是如何设置指针:一个大小为 MAXINT 的数组到 char* 元素:

    char* (*car)[MAXINT];
    car = &arg->_car;
    

    问题中的其他语法错误:

    • 您的结构定义后需要有一个分号。
    • 您应该使用foo* 而不是foo。所以应该是:
      struct foo* thing = (struct foo *) arg;
    • 您应该使用thing 而不是arg:
      bar = thing-&gt;_bar;
      car = thing-&gt;_car;

    【讨论】:

    • 谢谢,我需要的是指向 char * 数组的指针。我想这就是我需要的(交叉手指)
    • @Fantastic Fourier:同意您需要一个指向数组的指针,其元素是 char*。其他一些答案提到了指向不一样的 char* 数组的指针。
    【解决方案4】:

    C 中的数组表示法确实令人困惑;您的代码并不像您认为的那样。

    arg-&gt;_car 表示“数组地址_car”。类似地,car 表示“数组car 的地址”。如果您尝试将 _car 的内容复制到 car,则可以这样做:

    memcpy(car, _car, MAXINT);
    

    但我认为,您真正的问题是“存储字符串列表的最佳方式是什么?”这个答案是:一个动态列表(一个随着您添加项目而自动增长的列表)。

    你可以这样声明:

    #define CARSIZE 65
    int numCars = 0;
    char **car; /* a list of addresses, each one will point to a string */
    

    添加汽车:

    char *newCar = malloc(CARSIZE); /* make room */
    strncpy(newCar, "Mercedes", CARSIZE); /* newCar has the address of the string */
    car[numCars++] = newCar; /* store it */
    

    列出汽车:

    int n;
    for (n = 0; n < numCars; ++n)
        printf("%s\n", car[n]);
    

    要移除位置 n 的汽车:

    free(car[n]); /* release the memory */
    /* condense the list of pointers */
    for ( ; n < numCars - 1; ++n)
        car[n] = car[n+1];
    

    这在 C 语言中完全是例行公事。注意: 以上是我的想法,不是从工作程序中复制的,所以我不能保证所有 * 都在正确的位置.我怀疑这是一个家庭作业,所以我不想给你所有的东西...

    【讨论】:

    • 它适用于我的网络,其中该数组用于保存传入连接的名称(连接数在 SOME_NUMBER 处最大,即 20)。所以我认为我应该坚持静态,而不是动态。
    猜你喜欢
    • 2014-12-14
    • 2021-06-07
    • 2019-08-09
    • 1970-01-01
    • 2012-03-13
    • 2017-03-26
    • 2021-04-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多