动态内存分配,如何在处理结构时正确使用指针?

时间:2017-11-22 09:47:43

标签: c pointers

我现在正在学习动态内存分配,这很难理解,尤其是当讲师提到DMA和使用指针的结构时。

首先,在我的代码中的第1行,我对“& ptr-> eno”的含义感到困惑。我们启动ptr作为指针,这意味着ptr保持我们保留的内存的地址,让ptr保持地址2046,是“& ptr-> eno”意味着将值写入它指向的2046的地址?

第二,在第2行,如何打印出值,导致“ptr-> eno”包含值“2046”比我打印出来时,它会给我2046号,而不是值i尝试存储在内存位置2046.

我的代码是从讲义中复制过来的,我试图在Visual Studio上运行它,在输入值后它崩溃了。我对C这么新,我的假设可能看起来很愚蠢和痛苦。如果你无法理解我的解释,请告诉我如何使用指针与结构,可能是我可以弄清楚我的错误。谢谢

#include<stdio.h>
#include<stdlib.h>
struct emp
{
    int eno;
    char ename[20];
    float esal;
};
void main()
{
    struct emp* ptr;
    ptr = (struct emp*)malloc(sizeof(struct emp));
    if (ptr=NULL)
    {
        printf("out of memory error");
    }
    else
    {
        printf("enter the value of employee: \n");
        scanf_s("%d%s%f", &ptr->eno, ptr->ename, &ptr->esal); // line 1
    }
    printf("the name is: %s \t the number: %d \t the salary: %f", ptr->ename, ptr->eno, ptr->esal); //line2
}

3 个答案:

答案 0 :(得分:4)

此:

if (ptr=NULL)

没有做你想做的事。您需要比较运算符==,而不是赋值运算符=。这将始终将ptr设置为NULL,使得其余代码具有未定义的行为(这通常会导致实际崩溃)。启用和查看编译器警告是避免此问题的一种非常好的方法。

对于实际问题,&ptr->eno表示&{34; eno&#34;指向的结构中字段ptr的地址。在实践中,它将评估ptr的值,加上从结构开始到字段eno的偏移量,在这种情况下将为0,因为eno是第一个字段

此外,printf()当然应位于else内,因为只有在ptr不为NULL时才能运行{。}}。

而且,重要的是:您必须为字符串scanf_s()提供缓冲区大小。):

  

scanfwscanf不同,scanf_swscanf_s要求为c类型的所有输入参数指定缓冲区大小,{{1} },CsS中包含的字符串控件集。字符的缓冲区大小作为附加参数传递,紧跟在指向缓冲区或变量的指针之后。

所以,它应该是:

[]

你应该检查它的返回值,否则如果由于某种原因输入失败,你就有可能使用非初始化变量。

请注意,缓冲区的大小似乎指定为const int num = scanf_s("%d%s%f", &ptr->eno, ptr->ename, (unsigned int) sizeof ptr->ename, &ptr->esal); if (num == 3) // All conversions succeeded, we can rely on them { printf("the name is: %s \t the number: %d \t the salary: %f", ptr->ename, ptr->eno, ptr->esal); //line2 } ,而不是unsigned int,这在我的观点中不是最佳的,因此需要强制转换。

顺便说一下,&#34; DMA&#34;通常意味着&#34; direct memory access&#34;与此无关;那让我困惑了一段时间。

答案 1 :(得分:4)

假设

if (ptr=NULL)

是一个拼写错误(因为随后的&#34;它在我输入值后出现崩溃&#34;不可能发生),这里有一个错误:

scanf_s("%d%s%f", &ptr->eno, ptr->ename, &ptr->esal);

缺少%s

所需的大小参数
scanf_s("%d%s%f", &ptr->eno, ptr->ename, 20, &ptr->esal);

或者代替硬编码,也许

scanf_s("%d%s%f", &ptr->eno, ptr->ename, (unsigned)sizeof ptr->ename, &ptr->esal);

答案 2 :(得分:1)

投射malloc的输出(检查[ this ])不是一个好习惯,最简单的方法是

struct emp *ptr;
ptr = malloc(1 * sizeof *ptr);

然后,==用于等于逻辑比较,所以

if (NULL == ptr)
/* = changed to ==, also put the value first which will help you easily
* fix accidental omission of the second =
*/
{
    printf("out of memory error");
    exit(1); // Exiting with a non-zero status
} 

注意这应作为 [ this ]回答的补充