C指针参考

时间:2012-12-05 03:07:51

标签: c memory

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

#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的地址。名字和姓氏都存储在我期望的位置,0x04006b90x4006bd,因为它们在堆栈的前面声明了。

当我使用intro(&a)所做的更改运行GDB时,我得到的是什么。 person的地址现为0x7fffffffffdd38,第一个名称指向0x601010,姓氏指向0x4006db

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

编辑:

由于每个人似乎都在不断询问,void *是代码的线程部分,我没有提及。

4 个答案:

答案 0 :(得分:4)

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

此外,如果intro()旨在处理Person,则应声明Person *参数,而不是void *

答案 1 :(得分:3)

指针变量a内部的地址与a占用的实际内存位置的地址不同。

0x601010这样的地址是一个“低”的内存地址,通常会在堆上的某个地方。像0x7fffffffffdd38这样的地址是一个非常“高”的地址,通常会在堆栈上。所以&a给出了堆栈上变量a的实际地址,它将该值传递给函数,而不是存储在指针变量{{}中的值0x601010。 1}},表示从a返回的已分配内存缓冲区的第一个地址。

答案 2 :(得分: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";

现在解释为什么使用intro(&a)会给您带来意想不到的结果:

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

调用intro(a)会将指向Person的指针作为指向void的指针传递给intro,然后将其视为指向Person的指针,一切都很顺利

然后调用intro(&a)获取a地址并将其传入。再次,intro尝试将其视为指向{{1}的指针但这不起作用,因为你传递的是一个指向Person的指针。你把西红柿送到一个认为它变成橘子的功能。两者都是水果,你会得到果汁,但是当你的早餐搭配美味的番茄汁而不是美味的橙汁时,你可能不会很开心。

如果你问为什么调用Person导致第一个名字被破坏但是要打印的姓氏,答案是因为纯粹的运气:姓氏的字符串碰巧在右边在记忆中的位置。

答案 3 :(得分: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;
}
希望它有所帮助...