函数内部的C指针赋值

时间:2018-03-02 17:22:00

标签: c pointers

我正在尝试在函数get_by_id内分配一个指向数组元素的指针。

函数get_by_id正确地找到元素并将元素分配给lp,但是当它返回到调用者(set_attr)时,它将恢复为NULL

我不明白为什么它会在调用者中恢复为NULL,更不用说如何修复它了。

#include <stdio.h>
#include <stdlib.h>


typedef struct
{
    int id;
    char name[128];
    int attr;
} Lookup;


static int num_sources = 0;

Lookup ltable[128];


void add(int id, const char *name)
{
    sprintf(ltable[num_sources].name, name);
    ltable[num_sources].id = id;
    ltable[num_sources].attr = 999;  // example default attr 999
    num_sources++; // increment the number of sources
}


int get_by_id(int id, Lookup *lp)
{
    int status = 1;
    for (int i = 0; i < 128; i++)
    {
        lp = &ltable[i];
        if (id == lp->id)
        {
            status = 0;
            break;
        }
    }
    return status;
}


int set_attr(const int id, const int attr)
{
    Lookup *lp = NULL;
    int status = get_by_id(id, lp);
    if (status == 0)
    {
        lp->attr = attr;
    }
    return status;
}

int main(void) {
    add(88, "main"); // example id 88
    set_attr(88, 9); // example attr 9
    return EXIT_SUCCESS;
}

2 个答案:

答案 0 :(得分:3)

要更改lp的值,您必须使用双指针:

int get_by_id(int id, Lookup **lp)
{
    int status = 1;
    for (int i = 0; i < 128; i++)
    {
        *lp = &ltable[i];
        if (id == (*lp)->id)
        {
            status = 0;
            break;
        }
    }
    return status;
}

并打电话:

    int status = get_by_id(id, &lp);

因为C是“按值传递”,所以会生成lp的副本并传递给该函数。调用者无法看到对该副本的任何更改。要允许被调用函数更改调用者的变量,可以传递调用者变量的地址,以便被调用函数可以更改它。在您的情况下,您传递lp的{​​em>地址,写为&lp

<小时/> 可以使用以下版本:

#define T_SIZE (sizeof(ltable)/sizeof(ltable[0]))

Lookup *get_by_id(int id)
{
    for (int i = 0; i < T_SIZE; i++)
        if (id == ltable[i].id)
            return &ltable[i];

    return 0;
}

请注意,它返回指向表条目的指针,如果未找到则返回零。

答案 1 :(得分:0)

您需要通过引用而不是值传递Lookup参数。 这是因为只有在parameter通过引用传递时才能修改int get_by_id(int id, Lookup *lp) { int status = 1; for (int i = 0; i < 128; i++) { *lp = ltable[i]; if (id == lp->id) { status = 0; printf("lp=%X\n", lp); break; } } return status; } int set_attr(const int id, const int attr) { Lookup lp = {0}; int status = get_by_id(id, &lp); if (status == 0) { printf("lp = %X\n", &lp); lp.attr = attr; } return status; }

#Summarize grouped dataframe by World Region and Case Status Coded (by number 
of records and proportion)

summ_worldreg <- df_nona_worldreg %>% group_by(World.Region, 
CaseStatusCodedFactor) %>% summarise(n=n()) %>% mutate(proportion = n/sum(n))

Output of summ_worlreg: 

   World.Region              CaseStatusCodedFactor     n proportion
   <fct>                     <fct>                 <int>      <dbl>
 1 Australia and New Zealand Denied                  125     0.0628
 2 Australia and New Zealand Certified              1865     0.937 
 3 Carribbean                Denied                  337     0.187 
 4 Carribbean                Certified              1467     0.813 
 5 Central America           Denied                 2423     0.238 
 6 Central America           Certified              7762     0.762 
 7 Central Asia              Denied                   31     0.0861
 8 Central Asia              Certified               329     0.914 


#Plot 100% Stacked Bar Graph showing distribution of Case Status by World 
Region

worldreg_case_bar <- ggplot(summ_worldreg, aes(x = summ_worldreg$World.Region, 
y = summ_worldreg$proportion, fill = summ_worldreg$CaseStatusCodedFactor)) + 
geom_bar(stat = 'identity') 

这应该有用。