【问题标题】:how to use malloc () in Double Pointer in Structure in C如何在C结构中的双指针中使用malloc()
【发布时间】:2015-05-15 00:36:32
【问题描述】:

我有结构:

    typedef struct accont
{
    char **tel;//list of tel
    char **email;//list of emails
}acc;

typedef struct _strcol
{
    int count;      //total of accounts
    acc **list;
} strcol ;

我用指针访问结构:

strcol index;
contato *p;
p = (index.list + index.count);

问题,我如何在这个函数中使用 malloc()?

我试试:

(*p)->tel = (char **) malloc(i * sizeof (char*))

p.tel = (char **) malloc(i * sizeof (char*))

&(*p)->tel = (char **) malloc(i * sizeof (char*))

然后像我做第二个 malloc 来保存数据电子邮件或电话

第一次发帖,请见谅

【问题讨论】:

  • 这个&(*p) 什么都不做,和p 一样。
  • 具体的问题是什么?编译错误?段错误?
  • 抱歉,您是否要对“列表”最后一个链接中的元素进行 malloc?或者试图动态地增加你的“列表”?我对您的确切目标和确切问题感到非常困惑。我们能得到更多信息吗? \n :-)
  • @JohnBollinger:与protato相反?

标签: c pointers data-structures struct


【解决方案1】:

所以这个:

(*p)->tel = (char **) malloc(i * sizeof (char*))

分配空间来存储 i 指向 char 的指针 - 这样您就可以拥有 i 电话号码字符串。但是您实际上还没有分配任何空间来存储这些电话号码字符串本身。为此,您需要(对于第一个电话号码):

(*p)->tel[0] = malloc(j);

如果对malloc() 的调用成功,您现在可以将长度为j-1 的以nul 结尾的字符串存储在(*p)->tel[0] 指向的空间中。然后,您可以对 (*p)->tel(*p)->tel[i-1] 中的其他指针执行相同操作。

【讨论】:

  • 嗯...除非他已经拥有包含电话号码的字符串和所有字符串(我猜在解析时已经分配了这些字符串或者是硬编码的字符串。)如此现实,除非他打算填写他的@ 987654330@一个字一个字,他就可以(*p)->tel[X] = str;
  • @Khaldor:可能是这样,但我的猜测是字符串将从某个临时位置复制。问题中没有足够的信息可以说明。
【解决方案2】:

如果代码如下,使用malloc() 很简单:

some_type *p;
p = malloc(number_of_elements * sizeof *p);
if (p == NULL) Handle_OutOfMemory();

所以p.tel

// p.tel = (char **) malloc(i * sizeof (char*));
p.tel = malloc(i * sizeof *(p.tel));
if (p.tel == NULL) exit(EXIT_FAILURE);

【讨论】:

    【解决方案3】:

    我将假设 'p' 是 acc *p; (我不知道'contato'是什么)。 无论如何...重点是展示如何分配内存和存储/访问电话/电子邮件数据...还复制了电话号码/电子邮件ID只是为了演示... 关于从 malloc 返回的强制转换 void 指针,我已经看到支持/反对 ... i cast 的参数(malloc 是我强制转换的唯一情况)。

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    typedef struct accont
    {
            char **tel;    //list of tel
            char **email;  //list of emails
    }acc;
    
    typedef struct _strcol
    {
            int count;      //total of accounts
            acc **list;
    }strcol;
    
    int main()
    {
            int iNumAccounts = 5;   // Assume there are 5 Accounts.
            int iNumTels = 2;       // Each Account has 2 Tel #s.
            int iNumEmails = 3;     // Each Account has 3 Email ids.
    
            strcol index;
            acc *p = NULL;
    
            index.list = (acc **)malloc(5 * sizeof(acc *)); // Master list  
                // of 'acc' pointers i.e. pointer to a set of pointers.
    
            int i, j;
            for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at 
                // a time ... and allocate & store tel #s/email ids.
            {
                    index.list[i] = (acc *)malloc(sizeof(acc));
    
                    p = index.list[i];
    
                    p->tel = (char **)malloc(iNumTels * sizeof(char*));
                    for(j=0; j<iNumTels; j++)
                    {
                            p->tel[iNumTels] = (char *)malloc(11 * sizeof (char)); // 10 digit tel # + 1 byte for '\0' ...
                            strcpy(p->tel[iNumTels], "1234567890");
                    }
    
                    p->email = (char **)malloc(iNumEmails * sizeof(char*));
                    for(j=0; j<iNumEmails; j++)
                    {
                            p->email[iNumEmails] = (char *)malloc(51 * sizeof(char)); // 50 char long email id + 1 byte for '\0' ...
                            strcpy(p->email[iNumEmails], "kingkong@ihop.yum");
                    }
            }
    
            for(i=0; i<iNumAccounts; i++) // Go through the 5 Accounts, one at a time ... and display.
            {
                    p = index.list[i];
    
                    for(j=0; j<iNumTels; j++)
                    {
                            printf("Tel # is: %d\n", p->tel[iNumTels]);
                    }
    
                    for(j=0; j<iNumEmails; j++)
                    {
                            printf("Email id is: %s\n", p->email[iNumEmails]);
                    }
    
                    printf("----------\n");
            }
    }
    

    【讨论】:

    • 没有必要强制转换malloc() 的返回值。乘以 .sizeof (char) 是不必要的,因为它总是 1. 最好乘以取消引用指针的大小。
    • 我使用 sizeof(char),而不仅仅是 '1',以保持一致性并且对我来说更清楚。关于不强制转换 malloc 的返回,我已经阅读过它......这是我的看法:即使我强制转换并通过错误的强制转换无意中引入了一个错误,编译器也会给我一个警告。其次,如果我不投......我会遇到以下情况: int * p; // 而不是 int ** p。 p = malloc(10 * sizeof(int * )); // 编译器不会给出警告......程序员永远不会知道他/她通过声明 int * p 而不是 int ** p 犯了错误/错字; ...这不是一个有效的问题吗?
    • index.list = malloc(5 * sizeof *(index.list));解决。
    【解决方案4】:

    如果我理解正确,stack 实现将最适合这种情况。您可以使用标准的stack 库头(gcc)或创建适合您自己需要的堆栈实现。

    示例可能类似于下面的代码,但您最好关注 Jerry Cain 的有关堆栈过程的视频(您可以在 youtube 上找到这些视频:Stanford - Programming Paradigms videos . 堆栈会话应在视频编号 6 到 8 之间)。 link from here

    注意:小心!杀死堆栈元素(通过 StackPop)不会杀死由strdup 创建的字符字符串。您需要单独释放它们。这些在视频中进行了解释,但我不完全记得如何(同样,您会在这些视频中找到一些适合您的案例的有价值的信息)。

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <string.h>
    
    typedef struct {
        char *tel;
        char *email;
    } account;
    
    typedef struct {
        int *ptrElement; // starting address of the stack
        int sizeAllocat; // total size allocated
        int sizeCurrent; // current size
        int sizeElement; // byte length of the stack element
    } Stack;
    
    // create a new stack pointer
    void StackNew (Stack *s, int sizeElement) {
        assert (s->ptrElement > 0);
        s->sizeElement = sizeElement;
        s->sizeCurrent = 0;
        s->sizeAllocat = 4;
        s->ptrElement = malloc (4 * sizeElement);
        assert (s->ptrElement != NULL);
    }
    
    // kills a stack pointer
    void StackDispose (Stack *s) {
        free (s->ptrElement);
    }
    
    // expands stack space
    static void StackGrow (Stack *s) {
        s->sizeAllocat *= 2;
        s->ptrElement = realloc (s->ptrElement, s->sizeAllocat * s->sizeElement);
    }
    
    // insert new stack pointer (of type account for example)
    void StackPush (Stack *s, void *ptrElement) {
        if (s->sizeCurrent == s->sizeAllocat) {
            StackGrow (s);
        }
        void *target = (char *) s->ptrElement + s->sizeCurrent * s->sizeElement;
        memcpy (target, ptrElement, s->sizeElement);
        s->sizeCurrent++;
    }
    
    // pops (deletes) an element from stack
    void StackPop (Stack *s, void *ptrElement) {
        void *source = (char *) s->ptrElement +
                       (s->sizeCurrent - 1) * s->sizeElement;
        memcpy (ptrElement, source, s->sizeElement);
        s->sizeCurrent--;
    }
    
    // relocate stack element
    void StackRotate (void *first, void *middle, void *after) {
        int foreSize = (char *) middle - (char *) first;
        int backSize = (char *) after - (char *) middle;
        char tmp [foreSize];
        memcpy (tmp, first, foreSize);
        memmove (first, middle, backSize);
        memcpy ((char *) after - foreSize, tmp, foreSize);
    }
    
    int main () {
        Stack s;
        account *acc;
        StackNew (&s, sizeof (acc));
    
        // your code here
        // example
        // acc->tel = strdup("some number");
        // acc->email = strdup("some text");
        // StackPush(&s, &acc);
        ...
        // StackPop(&s, &acc);
        ...
        ...
    
        StackDispose (&s);
        return 0;
    }
    

    【讨论】:

    • 建议StackDispose ()s-&gt;sizeCurrent = s-&gt;sizeAllocat = 0;
    猜你喜欢
    • 1970-01-01
    • 2013-01-23
    • 2020-11-03
    • 1970-01-01
    • 2018-12-03
    • 1970-01-01
    • 2013-05-09
    • 1970-01-01
    • 2021-11-22
    相关资源
    最近更新 更多