【问题标题】:Read from the keyboard using pointer to a struct without using dereferencing operator使用指向结构的指针从键盘读取,而不使用解引用运算符
【发布时间】:2013-09-10 20:47:28
【问题描述】:

在下面的例子中,为什么我不能使用

scanf("%s%d%d", p.name, p.age, p.code);

如果变量p已经有了地址,那我为什么要放&p->age而不是p.age呢? 为什么我需要使用 'p->name' 从键盘读取字符串而不是 p.name 或 &p->name? 如果p->name 等于(*p).name,并且scanf("%s",&variable) 需要一个地址,那么如果(*p).name 将p 指向的值传递给函数scanf,它是如何工作的?

#include <stdio.h>
#include <stdlib.h>
struct person{
    char name[60];
    int age;
    int code;
};

void printdata(struct person *p){
   printf("%s, %d, %d",p->name, p->age, p->code);
}

int main(int argc, char *argv[]){
   struct person *p;
   p = (struct person*) malloc(sizeof(struct person));
   scanf("%s%d%d", p->name, &p->age, &p->code);
   printdata(p);
   free(p);
   return 0;
}

【问题讨论】:

    标签: c pointers struct dereference


    【解决方案1】:

    p 是一个指向结构体的指针; p-&gt;age 取消引用该指针并获取 age 成员,它是一个整数,而不是指针; &amp;p-&gt;age 采用p-&gt;age 的地址。所以p 没有age 成员,虽然*p 有,并且您传递*p 的年龄成员的地址进行扫描。

    至于(*p).name(即p-&gt;name),这是因为字符串无论如何都表示为指向字符数组的指针,因此您可以像以前一样将字符串传递给scanf,它只是覆盖其中的字符。这是危险的!因此,如果您输入的名称超过 60,您的代码可能会缓冲区溢出并崩溃。

    【讨论】:

    • 正确,但在 C 中,数组是连续内存的区域,与该数组关联的名称与指向数组第一个元素的指针相同。所以对于char x[];,x[2] == *(x+2) == 2[x]
    【解决方案2】:

    第一个问题:

    如果变量p已经有了地址,那我为什么要放&amp;p-&gt;age而不是p.age呢?

    您将p 声明为指针

    struct person *p;
    

    这意味着如果你想访问例如年龄成员,你必须首先取消引用指针:

    (*p).age
    

    正好等于符号

    p->age
    

    但是,scanf 函数,对于整数,takes a pointer to an int。因为p-&gt;age 指向一个int,所以你必须通过age 成员的地址来传递它。由于-&gt; 运算符的precedence 超过&amp;,因此您可以将其简单地写为

    &p->age
    

    与p的name成员的区别在于,因为它被声明为char的数组

     p->name
    

    其实已经是一个指针,指向name的第一个元素。因此,当您将 &amp; 传递给 scanf 时,您不需要在 p-&gt;name 前面添加 &amp; 运算符

    【讨论】:

      猜你喜欢
      • 2017-07-18
      • 2016-12-01
      • 2017-06-17
      • 2013-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-14
      相关资源
      最近更新 更多