【问题标题】:How do pointers in the structure work in the following code?结构中的指针如何在以下代码中工作?
【发布时间】:2020-10-25 17:11:40
【问题描述】:

我想在结构中使用指针来存储 2 个名称,代码可以正常存储并显示我想要的名称,但我对 & 运算符在 scanf 和 @ 中的作用感到困惑当我从printf 中删除& 运算符时,987654324@ 语句不会显示名称。我不知道它是如何工作的。

#include <stdio.h>
int main()
{
    struct name
    {
        char *p;
    }n1,n2; 
    
    printf("ENTER NAME1\n");
    scanf("%s",&n1.p);
    printf("\nENTER NAME2\n");
    scanf("%s",&n2.p);
    
    printf("ENTERED NAMES ARE %s , %s",&n1.p,&n2.p);
    return 0;
}

【问题讨论】:

  • 指针在任何地方都像指针一样工作,无论您将它作为单独的局部变量、参数还是作为结构的一部分。
  • 对于具有%s 格式的scanf,它需要一个指向char * 类型的字符数组的第一个元素的指针。当你使用地址操作符时,你会得到一个指向指针的指针,它的类型是char **。与printf%s 格式相同,它需要一个指向字符数组第一个元素的指针。
  • 老实说,您似乎跳过了大部分教科书,阅读了非常糟糕的教程,或者跳过了许多课程。重新开始,如果你没有书,买一本,你不能通过猜测来学习一门语言(编程或口语)。

标签: c string pointers struct


【解决方案1】:

代码运行良好

代码具有未定义的行为,因为在这些调用中

scanf("%s",&n1.p);
scanf("%s",&n2.p);

表达式 &n1.p 和 &n2.p 的类型不正确 char ** 并被覆盖。

您需要在要读取字符串的地方分配内存。

【讨论】:

    【解决方案2】:
    printf("ENTER NAME1\n");
    scanf("%s",&n1.p);
    printf("\nENTER NAME2\n");
    scanf("%s",&n2.p);
    

    您要将带有名称的字符串存储到哪里?

    进入各自结构本身内部的指针p的对象?

    这是无效和非法的。指针可以指向任何地方,而不是被赋予它们指向自己的对象的值。

    因此回答你的问题:

    "结构中的指针在下面的代码中是如何工作的?"

    它们根本不起作用。你的代码是一团乱七八糟的undefined behavior


    你需要先分配内存,p 指向的地方,f.e.通过使用malloc():

    n1.p = malloc(sizeof(char) * 20);   // Allocates memory for a string up to 19 characters.
    if (!n1.p)
    {
        fputs("Error at allocation!", stderr);
        return EXIT_FAILURE;
    }
    
    n2.p = malloc(sizeof(char) * 20);   // Allocates memory for a string up to 19 characters.
    if (!n2.p)
    {
        fputs("Error at allocation!", stderr);
        return EXIT_FAILURE;
    }
    

    然后将参数正确地传递给scanf()

    printf("ENTER NAME1\n");
    scanf("%s", n1.p);
    
    printf("\nENTER NAME2\n");
    scanf("%s", n2.p);
    

    (注意n1.p 而不是&amp;n1.pn2.p 也是如此)

    或者更好:

    printf("ENTER NAME1\n");
    if (scanf("%s", n1.p) != 1)
    {
        fputs("Error at input!", stderr);
        return EXIT_FAILURE;
    }    
    
    printf("\nENTER NAME2\n");
    if (scanf("%s", n2.p) != 1)
    {
        fputs("Error at input!", stderr);
        return EXIT_FAILURE;
    }   
    

    确保输入错误时的安全。


    此外,%s 转换说明符需要 char * 类型的参数,而不是像 &amp;n1.p&amp;n2.p 那样指向 char * (char **) 的指针。

    提供错误类型的参数也会调用undefined behavior

    只需使用n1.pn2.p


    这个printf() 调用也是错误的:

    printf("ENTERED NAMES ARE %s , %s", &n1.p,&n2.p);
    

    您也需要省略&amp;

    printf("ENTERED NAMES ARE %s , %s", n1.p, n2.p);
    

    一体化:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main (void)
    {
        struct name
        {
            char *p;
        } n1, n2; 
    
        n1.p = malloc(sizeof(char) * 20);   // Allocates memory for a string up to 19 characters.
        if (!n1.p)
        {
            fputs("Error at allocation!", stderr);
            return EXIT_FAILURE;
        }
    
        n2.p = malloc(sizeof(char) * 20);   // Allocates memory for a string up to 19 characters.
        if (!n2.p)
        {
            fputs("Error at allocation!", stderr);
            return EXIT_FAILURE;
        }
    
        
        printf("ENTER NAME1\n");
        if (scanf("%s", n1.p) != 1)
        {
            fputs("Error at input!", stderr);
            return EXIT_FAILUE;
        }    
    
        printf("ENTER NAME2\n");
        if (scanf("%s", n2.p) != 1)
        {
            fputs("Error at input!", stderr);
            return EXIT_FAILURE;
        } 
        
        printf("ENTERED NAMES ARE %s , %s", n1.p, n2.p);
    
        free(n1.p):
        free(n2.p);
    
        return 0;
    }
    

    执行:

    ENTER NAME1
    Peter
    ENTER NAME2
    Maria
    ENTERED NAMES ARE Peter , Maria
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-10-19
      • 1970-01-01
      • 1970-01-01
      • 2021-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多