我是C的新手。我以这种方式设置了这两个文件。 我不完全理解如何在不动态分配内存的情况下在Item数组中分配值。 线集合c;将所有字段放在堆栈上,这就是我可以直接设置数组成员的原因吗?
//collection.c
typedef struct {
uint32 price;
uint32 itemId;
} Item;
typedef struct {
Item item[MAX_SIZE];
uint32 name;
} Collection;
void function(Collection * ptr)
{
int i;
uint32 id = 0;
for(i = 0; i < MAX_SIZE; i++)
{
ptr->item[i].price = 10;
ptr->item[i].itemId = id;
id++;
}
}
//collection_main.c
Collection c; //global struct variable
//calls function in collection.c
function(&c);
答案 0 :(得分:2)
我不完全理解如何在不动态分配内存的情况下在Item数组中分配值。
首先,因为您是C的新手,请注意传递C函数指针的潜在问题(这是非常合理的,BTW)。除非您保证您的调用代码将始终传递有效指针,否则您需要尽可能地检查函数中的指针值。这通常相当于检查这样的非空指针:
if ( ptr == NULL )
return <whatever to signal an error> ;
在这种情况下,您确实分配了内存,因为您创建了一个Collection
变量并且包含所需字段的已分配空间。
第
Collection c;
行将所有字段放在堆栈上,
如果它在一个函数中,它(通常)将在该函数的stack frame上分配空间,您应该在逻辑上将其视为调用代码无法访问的单独区域。不要假设堆栈的布局。一个非常典型的错误是尝试返回一个指向函数内声明的项的指针,甚至据说有经验的程序员也知道这样做。
将指针传递给函数的另一个潜在错误是尝试超出分配和指向的空间限制。这可以做一些事情,比如破坏其他变量甚至崩溃代码。你自己的代码是正确使用声明的数组常量大小,所以没问题。
如果在函数之外(可能)执行此操作,则将使用OS保留的空间用于这些类型的变量。这可能不是在堆栈上,而是在其他地方。操作系统从编译的代码文件中获取该信息。
那么为什么我可以直接设置数组成员呢?
C代码(以及编译器生成的可执行二进制文件)不关心或检查您传递的指针是否有效。因此,可以将错误的指针传递给C函数并导致混乱。
在这种情况下,当您声明变量并且传递了指向该变量的指针时,您确实分配了所有必需的有效内存。没问题。
动态内存分配
通常使用malloc()
函数系列作为动态分配来考虑显式分配。局部变量和全局变量的分配可能是动态的,因为它们可以在运行时发生,但分配和释放不是程序员明确控制的责任,因此您通常不需要将这些视为动态内存分配的一部分。
要关闭的小问题:
uint32 name ;
我认为这是字段名称的错误选择。使用“name”表示一个字符串,而你可能意味着一个字符串id来自例如数组。所以尝试类似的事情:
uint32 nameid ;
代替。
您会惊讶于生产环境中出现多少编码问题,原因很简单,因为变量名称选择不当。如果可能和实际的话,让它们提供信息。
这只是一个很好的编码习惯,IMO。