简体   繁体   English

为函数内部的结构分配指针

[英]Allocate memory for a pointer to a struct inside a function

I am trying to write a separate program that calls a function to dynamically allocate memory for a certain number of "student" structs. 我正在尝试编写一个单独的程序,该程序调用一个函数来为一定数量的“学生”结构动态分配内存。

My main program was too large to mess with so I created a smaller program to help me more easily figure out what I'm doing: 我的主程序太大而无法处理,因此我创建了一个较小的程序来帮助我更轻松地弄清楚自己在做什么:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "memtest.h"

void structMemInit(myName **);

int main(void){

    myName *myNameIs;

    structMemInit(&myNameIs);

    printf("%s\n", myNameIs[1].name);

    return 0;
}

void structMemInit(myName **myNameIs){
    *myNameIs = (myName *) calloc(5, sizeof(myName));
    if(myNameIs == NULL){
        printf("allocating memory didn't work!\n");
        exit(1);
    }
    else if(myNameIs != NULL)
        (*myNameIs)[1].name = "Zach";
}

the memtest.h file is: memtest.h文件为:

typedef struct{
    char *name;
}myName;

All the above program is trying to do is pass a pointer to a struct into the function "structMemInit" and allocate clean space for the struct. 上面所有程序试图做的就是将指向结构的指针传递到函数“ structMemInit”中,并为该结构分配干净的空间。 Then to see show that it worked, I am setting the variable char to a name. 然后要查看它是否有效,我将变量char设置为一个名称。 After all this happens, you leave the function and go back to main. 在发生所有这些情况之后,您将离开函数并返回至main。 Then I print the name in the struct to show it worked. 然后,我在结构中打印该名称以显示其有效。

When run, the program always gives a segfault. 运行时,程序始终给出段错误。

In case you are wondering why I have a separate .h file, my actual program is much larger and has several globally declared structs and I am required by my instructor to keep a separate .h for those structs. 如果您想知道为什么我有一个单独的.h文件,我的实际程序要大得多,并且有几个全局声明的结构,我的老师要求我为这些结构保留一个单独的.h。

Thanks! 谢谢! Zach 扎克

If you insist on passing the pointer, it should be by reference, so it's a pointer to a pointer, as the function itslef will modify the address in the pointer. 如果您坚持要传递指针,则应该通过引用进行传递,因此它是指向指针的指针,因为itslef函数将修改指针中的地址。

You're much better off if your function returns a pointer. 如果您的函数返回一个指针,您会更好。

//function for allocating the memory
myName *structMemInit(void)
{
    myName *myNameIs = (myName *)calloc(1, sizeof(myName));
    if (myNameIs == NULL) {
        printf("allocating memory didn't work!\n");
        exit(1);
    } else {                     // don't repeat the negation of the condition
        myNameIs->name = "Zach"; // No need for \0, it's automatic
        return myNameIs;
    }
}

//Usage
myName *myNameIs = structMemInit();

BTW it's int main(void) not int main() . 顺便说一句,它是int main(void)而不是int main()

Before I answer, I should state that I am not too well-versed in C, I am a C++ programmer so there may be a few grammatical errors in what follows. 在回答之前,我应该说我不太精通C语言,因为我是C ++程序员,所以接下来可能会有一些语法错误。 Hopefully though, my point will be made sufficiently for any errors to be of much importance. 希望我的观点足以使任何错误都非常重要。

The reason you're getting segfault is because of your misunderstanding of what's happening when you pass a pointer as an argument to a function. 出现段错误的原因是因为您对将指针作为函数的参数传递时发生的误解。

Imagine, for instance, your program was the following: 想象一下,例如,您的程序如下:

int main(void){
    int i;

    setInteger(i);

    printf("%d\n", i);

    return 0;
}

void setInteger(int n){
    n = 12;
}

In this case, you can clearly see that the output will be undefined because the variable i was not initialised, and was passed by-value to setInteger . 在这种情况下,您可以清楚地看到输出将是未定义的,因为变量i尚未初始化,并且已按值传递给setInteger Any changes to n are not transferred back to i when the function returns. 函数返回时,对n任何更改都不会传递回i

If the program were replaced with 如果程序被替换为

int main(void){
    int i;

    setInteger(&i);

    printf("%d\n", i);

    return 0;
}

void setInteger(int *n){
    *n = 12;
}

Then the value output by i will be 12 . 那么,由i输出的值将为12

The same thing is happening in your program, you're passing your pointer by value . 程序中发生了同样的事情,您正在通过value传递指针。

If you want to pass by reference, you need to do the following: 如果要通过引用传递,则需要执行以下操作:

int main(void){

    myName *myNameIs;

    structMemInit(&myNameIs); // pass the address of your pointer

    printf("%s\n", myNameIs->name);

    return 0;
}

//function for allocating the memory
void structMemInit(myName **myNameIs){ // argument is pointer-to-pointer 
    *myNameIs = (myName *) calloc(1, sizeof(myName)); // dereference pointer to get underlying pointer
    if(*myNameIs == NULL){
        printf("allocating memory didn't work!\n");
        exit(1);
    }
    else{
        *myNameIs->name = "Zach";
    }

}

That's, unfortunately, not the end of your problems. 不幸的是,那还不是问题的结局。 Although you've allocated memory to your myName object, you have not allocated memory to your character array. 尽管您已经为myName对象分配了内存,但是尚未为字符数组分配内存。

To return the string "Zach", you need to do the following: 要返回字符串“ Zach”,您需要执行以下操作:

*myNameIs->name = (char*)malloc(5*sizeof(char)); // need extra char for \0
strcpy(*myNameIs->name, "Zach");

Please note that: 请注意:

typedef struct{
    char name[20];
} myName;

is different from: 不同于:

typedef struct{
    char *name;
} myName;

In the second form, you are not allocating any space for the string. 在第二种形式中,您没有为字符串分配任何空间。 You are just allocating space for a pointer. 您只是在为指针分配空间。

Below is a running version of your program. 下面是程序的运行版本。 If you want to use strcpy(p->name, "Zach"); 如果要使用strcpy(p->name, "Zach"); you need to use char name[20]; 您需要使用char name[20]; in your struct. 在你的结构中。

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

typedef struct{
    // char name[20];
    char *name;
} myName;

myName *structMemInit();

int main(){
    myName *myNameIs;
    myNameIs = structMemInit();
    if (myNameIs)
        printf("%s\n", myNameIs->name);
    return 0;
}

//function for allocating the memory
myName *structMemInit(){
    myName * p = (myName *) malloc(sizeof(myName));
    if (p == NULL){
        fprintf(stderr, "allocating memory didn't work!\n");
    } else {
        fprintf(stderr, "allocating %d memory work!\n", sizeof(myName));
        // strcpy(p->name, "Zach");
        p->name = strdup("Zach");
    }
    return p;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM