- android - 多次调用 OnPrimaryClipChangedListener
- android - 无法更新 RecyclerView 中的 TextView 字段
- android.database.CursorIndexOutOfBoundsException : Index 0 requested, 光标大小为 0
- android - 使用 AppCompat 时,我们是否需要明确指定其 UI 组件(Spinner、EditText)颜色
我是 C 的新手,在使用以下 C 函数时被一些魔法惊呆了。 此代码适用于我,并打印所有数据。
typedef struct string_t {
char *data;
size_t len;
} string_t;
string_t *generate_test_data(size_t size) {
string_t test_data[size];
for(size_t i = 0; i < size; ++i) {
string_t string;
string.data = "test";
string.len = 4;
test_data[i] = string;
}
return test_data;
}
int main() {
size_t test_data_size = 10;
string_t *test_data = generate_test_data(test_data_size);
for(size_t i = 0; i < test_data_size; ++i) {
printf("%zu: %s\n", test_data[i].len, test_data[i].data);
}
}
为什么函数 generate_test_data 仅在“test_data_size = 10”时有效,但在“test_data_size = 20”过程结束时退出代码为 11?怎么可能?
最佳答案
这段代码永远不会完美运行,它只是碰巧可以运行。在 C 中,您必须自己管理内存。如果您犯了一个错误,该程序可能会继续运行……或者某些东西可能会在您认为属于您的内存中乱涂乱画。这通常表现为您所遇到的奇怪错误:它在长度为 X 时有效,但在长度为 Y 时失败。
如果您打开 -Wall
,或者如果您使用 clang 甚至更好 -Weverything
,您将收到这样的警告。
test.c:18:12: warning: address of stack memory associated with local variable 'test_data' returned
[-Wreturn-stack-address]
return test_data;
^~~~~~~~~
C 中两种重要的内存类型是:栈和堆。基本上,堆栈内存仅在函数运行期间有用。当函数返回时,堆栈上声明的任何内容都会自动释放,有点像其他语言中的局部变量。经验法则是,如果您没有显式分配它,它就在堆栈上。 string_t test_data[size];
为栈内存。
您自己分配和释放的堆内存,通常使用 malloc
或 calloc
或 realloc
或其他为您执行此操作的函数,例如 strdup
。分配后,堆内存会一直存在,直到它被显式释放。
经验法则:堆内存可以从函数返回,栈内存不能……好吧,你可以但是那个内存槽可能会被其他东西使用。这就是发生在你身上的事情。
所以你需要分配内存,不只是一次,而是多次。
string_t
结构的指针数组分配内存。string_t
结构分配内存。char
字符串(实际上是一个数组)分配内存。然后你必须释放所有这些。听起来工作量很大?这是!欢迎来到 C。抱歉。您可能想编写函数来分配和释放 string_t
。
static string_t *string_t_new(size_t size) {
string_t *string = malloc(sizeof(string_t));
string->len = 0;
return string;
}
static void string_t_destroy(string_t *self) {
free(self);
}
现在您的测试数据函数如下所示。
static string_t **generate_test_data_v3(size_t size) {
/* Allocate memory for the array of pointers */
string_t **test_data = calloc(size, sizeof(string_t*));
for(size_t i = 0; i < size; ++i) {
/* Allocate for the string */
string_t *string = string_t_new(5);
string->data = "test";
string->len = 4;
test_data[i] = string;
}
/* Return a pointer to the array, which is also a pointer */
return test_data;
}
int main() {
size_t test_data_size = 20;
string_t **test_data = generate_test_data_v3(test_data_size);
for(size_t i = 0; i < test_data_size; ++i) {
printf("%zu: %s\n", test_data[i]->len, test_data[i]->data);
}
/* Free each string_t in the array */
for(size_t i = 0; i < test_data_size; i++) {
string_t_destroy(test_data[i]);
}
/* Free the array */
free(test_data);
}
您可以不使用指针而是复制您使用的所有内存,这与您之前所做的类似。这对程序员来说更容易,但对计算机来说效率低下。如果您使用 C 语言编写代码,那么一切都是为了提高计算机的效率。
关于c - 返回 C 数组时的财富?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34597526/
什么是命运 react ? Techempower.com 使用它们来对 Web 框架进行基准测试。我正在撰写有关 PHP 框架的文章,我想要一个易于理解的财富响应定义。 最佳答案 您可以在相关 te
我是一名优秀的程序员,十分优秀!