[英]How do I return a struct from a function to a struct pointer?
我正在为代码创建一个函数,该代码使用输出到文件指针的函数,例如,
number *base6 = intToNumber(50, 6);
这是我到目前为止的代码:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int iNum;
int base;
char* sNum;
} number;
number * intToNumber(int nnum, int nbase) {
number * theNumbers;
//theNumbers= (number*)malloc(10*sizeof(number));
if (theNumbers = NULL) {
printf("\n\nNo\n\n");
exit(1);
}
theNumbers->iNum = nnum;
theNumbers->base = nbase;
}
您开始按照正确的theNumbers
思考,但是您对theNumbers
分配的处理(您已发表评论)只是第一步。 当您分配theNumbers
,会创建指针theNumbers->sNum
- 但它是一个未初始化的指针,它持有一个不确定的地址作为其值。 (例如,它无处指向您有任何能力利用)。 想想你的结构( typedef
)
typedef struct {
int iNum; /* automatic storage types */
int base;
char *sNum; /* a pointer - hold address to something else */
} number; /* must point to valid memory addr */
当您为其中之一分配时,您将分配 2 个整数值和 1 个具有自动存储类型且可以赋值的字符指针。 虽然iNum
和base
是整数值并且可以分配立即值,例如50
和6
,但sNum
相比之下是一个指针,只能分配一个有效的内存地址来存储其他内容。
通常,要使用指针,您需要分配一个新的内存块,用该类型所需的任何内容填充该内存,然后将该新内存块的起始地址分配给您的指针(此处为sNum
)。 所以现在您的指针将保存(例如指向)包含该对象类型可用值的有效内存块的地址。 ( char*
,指向char*
的指针,此处)
你的intToNumber
函数只接受int nnum
和int nbase
作为参数,所以在为你的struct
分配之后,你只能初始化theNumbers->iNum = nnum;
和theNumbers->base = nbase;
,但没有任何大小或初始化sNum
(因此应设置为NULL
)。
所以你接近你的intToNumber
,你需要做的就是在你为它分配存储后返回指针intToNumber
(因为在分配之后它分配了在程序生命周期中存活的存储类型- 或者直到它被释放),例如
number *intToNumber (int nnum, int nbase) {
number *theNumbers;
theNumbers= malloc (sizeof *theNumbers); /* allocate */
if (theNumbers == NULL) { /* validate */
perror ("malloc-theNumbers");
return NULL;
}
theNumbers->iNum = nnum; /* initialize values */
theNumbers->base = nbase;
theNumbers->sNum = NULL;
return theNumbers; /* return pointer */
}
现在如何处理sNum
? 好吧,这取决于您,但是例如,您可以创建一个单独的函数,将分配的struct
和字符串作为参数,分配length + 1
个字节来保存字符串(加上空终止字符)分配起始新块的地址到sNum
,然后将字符串复制到新的内存块,例如
/* allocate/set sNum member of n to s */
char *setsNum (number *n, const char *s)
{
if (!n) { /* validate n not NULL, return NULL on failure */
fputs ("error: struct parameter 'n' NULL.\n", stderr);
return NULL;
}
size_t len = strlen (s); /* get length */
n->sNum = malloc (len + 1); /* allocate storage (+1 byte) */
if (!n->sNum) { /* validate allocation */
perror ("malloc-sNum");
return NULL;
}
memcpy (n->sNum, s, len + 1); /* copy s to new block of memory */
return n->sNum; /* return pointer (convenience) */
}
(我怀疑你会用你的 base6 转换来填充它——但这留给你)
除了在完成后释放内存之外,剩下的就是一个简短的示例,展示如何完全放置它。 你可以做一些简单的事情,比如:
int main (void) {
number *mynum = intToNumber (50, 6); /* declare/initialize mynum */
if (!mynum) /* validate succeeded */
return 1;
/* allocate/validate mynum->sNum, copy string */
if (!setsNum (mynum, "created with intToNumber (50, 6)")) {
free (mynum);
return 1;
}
/* output values held in mynum */
printf ("succeeded:\n iNum: %d\n base: %d\n str : %s\n",
mynum->iNum, mynum->base, mynum->sNum);
free (mynum->sNum); /* free allocated string */
free (mynum); /* free struct */
}
示例使用/输出
如果你把这个例子放在一起,你会得到:
$ ./bin/struct_alloc_member
succeeded:
iNum: 50
base: 6
str : created with intToNumber (50, 6)
内存使用/错误检查
在你写的,可动态分配内存的任何代码,您有任何关于分配的内存任何块2个职责:(1)始终保持一个指针的起始地址的存储器中,以便块,(2),当它是没有它可以被释放不再需要。
您必须使用内存错误检查程序来确保您不会尝试访问内存或写入超出/超出分配块的边界,尝试读取或基于未初始化值的条件跳转,最后,确认你释放了你分配的所有内存。
对于 Linux valgrind
是正常的选择。 每个平台都有类似的内存检查器。 它们都易于使用,只需通过它运行您的程序即可。
$ valgrind ./bin/struct_alloc_member
==15553== Memcheck, a memory error detector
==15553== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==15553== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==15553== Command: ./bin/struct_alloc_member
==15553==
succeeded:
iNum: 50
base: 6
str : created with intToNumber (50, 6)
==15553==
==15553== HEAP SUMMARY:
==15553== in use at exit: 0 bytes in 0 blocks
==15553== total heap usage: 2 allocs, 2 frees, 49 bytes allocated
==15553==
==15553== All heap blocks were freed -- no leaks are possible
==15553==
==15553== For counts of detected and suppressed errors, rerun with: -v
==15553== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
始终确认您已释放所有分配的内存并且没有内存错误。
使用的完整示例是:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct {
int iNum; /* automatic storage types */
int base;
char *sNum; /* a pointer - hold address to something else */
} number; /* must point to valid memory addr */
number *intToNumber (int nnum, int nbase) {
number *theNumbers;
theNumbers= malloc (sizeof *theNumbers); /* allocate */
if (theNumbers == NULL) { /* validate */
perror ("malloc-theNumbers");
return NULL;
}
theNumbers->iNum = nnum; /* initialize values */
theNumbers->base = nbase;
theNumbers->sNum = NULL;
return theNumbers; /* return pointer */
}
/* allocate/set sNum member of n to s */
char *setsNum (number *n, const char *s)
{
if (!n) { /* validate n not NULL, return NULL on failure */
fputs ("error: struct parameter 'n' NULL.\n", stderr);
return NULL;
}
size_t len = strlen (s); /* get length */
n->sNum = malloc (len + 1); /* allocate storage (+1 byte) */
if (!n->sNum) { /* validate allocation */
perror ("malloc-sNum");
return NULL;
}
memcpy (n->sNum, s, len + 1); /* copy s to new block of memory */
return n->sNum; /* return pointer (convenience) */
}
int main (void) {
number *mynum = intToNumber (50, 6); /* declare/initialize mynum */
if (!mynum) /* validate succeeded */
return 1;
/* allocate/validate mynum->sNum, copy string */
if (!setsNum (mynum, "created with intToNumber (50, 6)")) {
free (mynum);
return 1;
}
/* output values held in mynum */
printf ("succeeded:\n iNum: %d\n base: %d\n str : %s\n",
mynum->iNum, mynum->base, mynum->sNum);
free (mynum->sNum); /* free allocated string */
free (mynum); /* free struct */
}
假设实际问题正是标题中提出的问题:
如何将结构从函数返回到结构指针?
答案是,虽然函数可以返回一个结构,它不能做这样一个struct指针。 在任何情况下都不能将结构分配给任何指针类型的对象。 您可以拥有指向结构的指针,也可以拥有包含指针的结构,但没有结构本身就是指针。
另一方面,如果问题是关于如何返回结构指针,那么答案将是“通过使用return
语句”,与返回任何其他类型的值的方式相同。 为了使之有用,您返回的指针应该是有效的,但这是一个单独的问题。
为什么不在函数中传递指向结构的指针,使签名看起来像void intToNumber(number *n)
? 然后你的实现看起来像
int main ()
{
number Numbers = {.sNum = malloc (25) };
// Do stuff here...
intToNumber(&Numbers);
// Do some more stuff...
}
由于您指向堆栈上的变量Numbers
,您可以在函数intToNumber
操作这些变量,并使它们在main
函数的其余部分(或您决定调用它的任何范围内)可用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.