2

我有以下代码,它只是打印出一个人名的介绍。

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

typedef struct {
    char* firstname;
    char* lastname;
}Person;

void intro(void *person){
    printf("The person you are looking for is %s %s\n", ((Person *)person)->firstname, ((Person *)person)->lastname);
}

int main()
{
    Person *a = NULL;
    a = (Person *)malloc(sizeof(Person));

    char *first = NULL, *last = NULL;
    first = (char *)malloc(sizeof(char)*20);
    strncpy(first,"Bob", 20);
    last = (char *)malloc(sizeof(char)*20);
    strncpy(last,"Newmonson", 20)
    a->firstname = first;
    a->lastname = last;

    intro(a);

    return 0;
}

产生输出

The person you are looking for is Bob Newmonson

然而改变intro(a)intro(&a)产生

The person you are looking for is �@ Newmonson

当我在 GDB 中打开第一次尝试并在第 10 行中断时,我找到了person=0x601010. 名字和姓氏都存储在我期望的位置,0x04006b9因为0x4006bd它们在堆栈中较早声明。

当我运行 GDB 并对intro(&a). 的地址person现在是0x7fffffffffdd38,名字指向 ,0x601010姓氏指向0x4006db

任何人都可以帮助解释发生了什么以及为什么我仍然可以在第二次测试中访问姓氏的正确地址。

编辑 :

正如每个人似乎一直在问这个问题void *,这是我没有包含的这段代码的线程部分。

4

4 回答 4

4

这是因为is 已经是一个结构的a指针;Person因此intro(&a)传递一个指向该指针的指针,但intro()将其参数视为指向Person.

此外,如果intro()打算在 Person 上工作,它应该声明一个Person *参数,而不是void *.

于 2012-12-05T03:11:50.723 回答
3

指针变量a中保存的地址与被占用的实际内存位置的地址不同a

address like0x601010是一个“低”内存地址,通常位于堆上的某个位置。类似的地址0x7fffffffffdd38是一个非常“高”的地址,通常会在堆栈上。因此&a,给您堆栈上变量的实际地址,a并将该值传递给函数,而不是0x601010存储在指针变量中的值a,并表示从返回的已分配内存缓冲区的第一个地址malloc

于 2012-12-05T03:13:12.363 回答
0

首先:

/* allocate space for 20 characters and make 'first' point to that space. */
first = (char *)malloc(sizeof(char)*20);
/* now make 'first' point to the string Bob. Leak the memory that was allocated before. */
first = "Bob";
/* Rinse, lather, repeat. */
last = (char *)malloc(sizeof(char)*20);
last = "Newmonson";

现在解释为什么 usingintro(&a)会给你意想不到的结果:

intro需要一个指针,它假定它指向一个类型的结构Person。您创建一个指向 a 的指针Person,然后为它分配空间。

调用intro(a)导致指针Person作为指向voidintro 的指针传递,然后将其视为指向的指针Person,一切都很好。

intro(&a)但是,调用会获取of的地址a并将其传入。再次intro尝试将其视为指向的指针,Person但这不起作用,因为您传递的是指向 a 的指针的指针Person。您正在将西红柿传递给一个认为它正在获取橙子的函数。两者都是水果,你会得到果汁,虽然当你的早餐是美味的番茄汁而不是美味的橙汁时,你可能不会很高兴。

如果你问为什么调用intro(&a)会导致名字被破坏而姓氏被打印出来,答案是纯粹的运气:带有姓氏的字符串恰好在内存中的正确位置。

于 2012-12-05T03:22:49.000 回答
0

尝试这个:

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

typedef struct {
    char* firstname;
    char* lastname;
}Person;

void intro(Person *person){
    printf("The person you are looking for is %s %s\n", (person)->firstname,   (person)->lastname);
}

int main()
{
    Person *a = NULL;
    char *first = NULL, *last = NULL;
    a = (Person *)malloc(sizeof(Person));


    first = (char *)malloc(sizeof(char)*20);
    first = "Bob";
    last = (char *)malloc(sizeof(char)*20);
    last = "Newmonson";
    a->firstname = first;
    a->lastname = last;

    intro(a);

    return 0;
}

希望能帮助到你...

于 2012-12-05T03:23:45.210 回答