问题
I am working through the Learn C the Hard Way and I am currently stuck on the extra credit exercise number 16.
I am currently trying to adapt their code and making the struct on the stack instead of the heap but my code is giving me segmentation fault and I am unsure why or how to proceed. Any advice is greatly appreciated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Person {
char *name;
int age;
int height;
int weight;
};
void Person_create(struct Person p,char *name,int age,int height,int weight)
{
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
}
void Person_print(struct Person who)
{
printf("Name: %s\n", who.name);
printf("\tAge: %d\n", who.age);
printf("\tHeight: %d\n", who.height);
printf("\tWeight: %d\n", who.weight);
}
int main(int argc, char *argv[])
{
// make two people structures
struct Person joe;
struct Person frank;
Person_create(
joe,"Joe Alex",32,64,140);
Person_create(
frank,"Frank Blank",20,72,180);
// print them out
Person_print(joe);
Person_print(frank);
// make everyone age 20 years and print them again
joe.age += 20;
joe.height -= 2;
joe.weight += 40;
Person_print(joe);
frank.age += 20;
frank.weight += 20;
Person_print(frank);
return 0;
}
回答1:
The reason your code produces errors at runtime is that C passes structs by value, meaning that the following assignments inside Person_create have no effect:
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
This makes no changes to joe and frank inside main(), leading to undefined behavior on printing, because name data member of the struct Person remains uninitialized.
In order to fix this problem, pass struct Person by pointer, and apply -> operator in place of . operator:
void Person_create(struct Person *p,char *name,int age,int height,int weight)
{
p->name = name;
p->age = age;
p->height = height;
p->weight = weight;
}
...
Person_create(&joe, "Joe Alex", 32, 64, 140);
// ^ Pass an address
It is asking for me to not use pointers or malloc, and says as advice to look into creating a struct on the stack
Your code already creates the structs on the stack. If you would like to get rid of pointers completely, change Person_create to *return` a new person, like this:
struct Person Person_create(char *name,int age,int height,int weight) {
struct Person p;
p.name = name;
p.age = age;
p.height = height;
p.weight = weight;
return p;
}
...
joe = Person_create("Joe Alex", 32, 64, 140);
回答2:
Define finction Person_create the following way
void Person_create(struct Person *p, char *name, int age, int height, int weight)
{
p->name = name;
p->age = age;
p->height = height;
p->weight = weight;
}
and call it like
Person_create( &joe, "Joe Alex", 32, 64, 140 );
A more sophisticated approach is the following
#include <string.h>
#include <stdlib.h>
//...
void Person_create(struct Person *p, const char *name, int age, int height, int weight)
{
size_t n = strlen( name );
p->name = malloc( ( n + 1 ) * sizeof( char ) );
strcpy( p->name, name );
p->age = age;
p->height = height;
p->weight = weight;
}
However in this case you should remember to free the allocated memory when the object of the structure leaves its scope.
回答3:
#include <stdio.h>
#include <stdlib.h>
typedef struct {
char *name;
int age;
int height;
int weight;
}Person;
void Person_print(Person who)
{
printf("Name: %s\n", who.name);
printf("\tAge: %d\n", who.age);
printf("\tHeight: %d\n", who.height);
printf("\tWeight: %d\n", who.weight);
}
int main(int argc, char *argv[])
{
Person joe= {"Joe Alex", 32, 64, 140};
Person frank={"Joe Alex", 32, 64, 140};
printf("Joe is at memory location: %p\n", &joe);
Person_print(joe);
printf("Frank is at memory location: %p\n", &frank);
Person_print(frank);
joe.age += 20;
joe.height -= 2;
joe.weight += 40;
Person_print(joe);
frank.age += 20;
frank.weight += 20;
Person_print(frank);
return 0;
}
Typedef the struct called 'Person', then you don't have to use 'Person create'.
来源:https://stackoverflow.com/questions/31568778/changing-a-struct-on-the-stack-inside-function