我正在尝试创建一个程序,该程序包含一个名为“ myStruct”的结构,该结构包含一个字符串数组“ char * array”。然后是分配内存的函数,然后打印输出,然后是如下所示的主要函数:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct myStruct { char *array; } str1;
void display(str1 *p1) {
char *array;
array = (char *)malloc(10 * sizeof(char));
printf("%s", p1->array);
free(array);
}
int main(void) {
str1 s1;
strcpy(s1.array, "Damn");
return 0;
}
但是我希望输出“ Damn”,但是输出却什么也没有。 但是,在编译过程中,显示以下警告:
user@localhost: ~ $ clang struct.c -Weverything
struct.c:7:6: warning: no previous prototype for function 'display' [-Wmissing-prototypes]
void display(str1 *p1) {
^
1 warning generated.
这意味着未调用函数。在这种情况下,我在语法和语义上都需要一些帮助。我不确定如何调用函数display()。
答案 0 :(得分:2)
您没有在display
中呼叫main()
。要将内存分配给char *array
并复制字符串,可以设计如下函数:
#define DEFAULT_LEN 10
void allocate(str1 *p1, const char * str) {
char * array;
if(str) {
//(char *) is omittable in C (not C++)
array = malloc(strlen(str) + 1);
strcpy(array, str);
}
else {
array = malloc(DEFAULT_LEN);
array[0] = 0;
}
p1->array = array;
}
,您可以这样打印文本:
int main() {
str1 s1; allocate(&s1, "Damn");
puts(s1.array);
deallocate(&s1);
return 0;
}
您必须释放内存:
void deallocate(str1 *p1) {
free(p1->array);
p1->array = NULL;
}
答案 1 :(得分:1)
使用str1 s1
s1在堆栈上分配时,其中的数组只是一个指针,没有为其内容分配内存。
strcpy
然后尝试写入该指针指向的任何位置,该值可能为零,也可能是随机数,具体取决于您的编译器及其设置。
您需要先为字符串分配一个缓冲区,例如:
str1 s1;
size_t len = strlen("Damn");
s1.array = malloc((len+1) * sizeof(char)); // +1 for the null terminator
strcpy(s1.array, "Damn");
答案 2 :(得分:1)
让我们看看我们是否能为您提供一些基础。声明s1
时,将声明类型struct myStruct
的结构,该结构方便地具有typedef
到str1
;声明:
str1 s1;
为s1
创建存储,该存储具有自动存储持续时间,并且仅在s1
处于范围内时才有效。 s1
的自动存储包括一个指针 array
的存储,仅此而已。 (暂时忽略填充)。 一个指针 array
完全是未初始化的,它指向一些您无法写入的不确定地址。尝试写入未初始化的值将调用未定义行为,并且程序的有效操作将在此时停止。 (实际上,尝试对其进行写操作可能会导致分段错误)
如何为s1.array
创建存储?这是您需要分配的位置。 (之前,您尝试复制到s1.array
)存储字符串需要多少内存? strlen(string) + 1
(为 nul-终止字符提供存储的+1)
知道这一点,并按照我在评论中留下的链接,您可以使用以下方式为字符串分配存储空间:
s1.array = malloc (strlen ("Damn") + 1);
对于每个分配,您将验证分配成功,然后再尝试使用内存块。如果malloc
失败(并且确实如此),则您尝试使用无效块将使您回到原本无法分配的状态–逐步进入未定义行为 ...
现在您已经初始化s1.array
指向有效的内存块,并且验证分配成功,现在可以将字符串复制到s1.array
。
strcpy (s1.array, "Damn");
您的display
函数不需要进行任何分配(当然可以)。您的display
函数仅需要显示现在保存在s1.array
中的字符串。正如乔纳森·莱夫勒(Jonathan Leffler)所述,您只需将指针传递到display(str1 *s)
,然后从内部输出s->array
。没什么比:
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
您将通过main()
呼叫的方式为:
display (&s); /* pass the address of s (a pointer to s) */
在您编写的任何动态分配内存的代码中,对于任何分配的内存块,您都有2个职责:(1)始终保留指向起始地址的指针因此,(2)当不再需要它时可以释放。
从display()
返回时,s1.array
的使用已结束,可以释放它。立即养成释放分配的内存的习惯,不要仅仅依赖于程序结束时就释放它-随着代码变得更加复杂,这将带来很多好处。
free (s1.array); /* if you allocate it, you free it when done */
由于s1
具有自动存储功能,因此该结构本身没有任何可用空间。
让我们举两个例子。第一个将声明具有自动存储持续时间的结构,并且仅分配给s.array
(如上所述)。第二个将声明一个指向您的结构的指针,现在需要您为结构和数组分配。 (这又需要您释放数组和结构)
具有自动存储期限的结构
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR "Damn"
typedef struct mystruct {
char *array;
} mystruct_t;
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
int main (void) {
mystruct_t s; /* struct with automatic storage - for the pointer */
/* s is a struct, so you use the '.' operator access members */
s.array = malloc (strlen (STR) + 1); /* you must allocate for array */
if (s.array == NULL) { /* validate each allocation */
perror ("malloc-s.array");
return 1;
}
strcpy (s.array, STR); /* with valid memory pointed to, you can copy */
display (&s); /* pass the address of s (a pointer to s) */
free (s.array); /* if you allocate it, you free it when done */
return 0;
}
声明要构造的指针
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define STR "Damn"
typedef struct mystruct {
char *array;
} mystruct_t;
void display (mystruct_t *s)
{
printf ("%s\n", s->array);
}
int main (void) {
mystruct_t *s; /* declare a pointer to the struct itself */
s = malloc (sizeof *s); /* now you must allocate for the struct */
if (s == NULL) { /* and you validate every allocation */
perror ("malloc-s");
return 1;
}
/* s is a pointer to struct, so you use -> to reference member */
s->array = malloc (strlen (STR) + 1); /* you must allocate for array */
if (s->array == NULL) { /* validate each allocation */
perror ("malloc-s->array");
return 1;
}
strcpy (s->array, STR); /* with valid memory pointed to, you can copy */
display (s); /* s is a pointer, just pass it to display */
free (s->array); /* if you allocate it, you free it when done */
free (s); /* don't forget to free the struct */
return 0;
}
(在两种情况下,输出只是您的字符串)
请仔细检查两者,以注意使用'.'
或->
运算符来取消引用结构并访问array
。您需要了解何时以及在何处使用它们。
如果您还有其他问题,请告诉我。