错误代码
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int capacity;
} IntArray;
int main(){
printf("test.\n");
IntArray* intArray;
int t;
printf("test2.\n");
intArray->capacity = 0;
printf("test3.\n");
printf("%d\n",intArray->capacity);
return 0;
}原因
代码中的IntArray试图在未经初始化的指针上直接访问和修改内存。这会导致未定义行为,通常表现为程序崩溃或数据损坏。
具体来说,IntArray* intArray; 这行代码仅仅声明了一个指向 IntArray 类型的指针 intArray,但没有为其分配内存。因此,intArray 指向的是一个随机的内存地址,对这个地址的解引用(即使用 intArray->capacity)是未定义的行为。
为了修复这个问题,你需要在使用 intArray 指针之前,为其分配足够的内存来存储一个 IntArray 结构体。这可以通过 malloc 函数来实现.
解决示例:
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int capacity;
} IntArray;
int main() {
printf("test.\n");
IntArray* intArray = (IntArray*)malloc(sizeof(IntArray)); // 分配内存
if (intArray == NULL) { // 检查malloc是否成功
printf("Memory allocation failed!\n");
return 1;
}
int t;
printf("test2.\n");
intArray->capacity = 0; // 现在可以安全地赋值了
printf("test3.\n");
printf("%d\n", intArray->capacity); // 正确地打印出0
free(intArray); // 释放之前分配的内存
return 0;
}深入学习
场景
IntArray* intArray = (IntArray*)malloc(sizeof(IntArray));
IntArray intArray;在C语言中,这两句有什么区别。
第一行代码
IntArray* intArray = (IntArray*)malloc(sizeof(IntArray));这行代码执行了以下操作:
- 内存分配:使用
malloc函数从堆(heap)中动态分配了足够存储一个IntArray类型对象所需的内存空间。sizeof(IntArray)计算了IntArray类型对象所需的字节数。 - 类型转换:
(IntArray*)是类型转换,将malloc返回的void*类型指针转换为IntArray*类型指针。在C语言中,malloc返回的是void*类型的指针,它可以被转换为任何其他类型的指针。 - 赋值:将分配好的内存地址赋值给
IntArray*类型的指针变量intArray。这样,intArray就指向了一个动态分配的IntArray类型的对象。
第二行代码
IntArray intArray;这行代码执行了以下操作:
- 自动变量声明:在栈(stack)上声明了一个
IntArray类型的变量intArray。这意味着这个变量的生命周期是自动的,与包含它的函数或块的执行周期相同。一旦函数或块执行完毕,这个变量就会被自动销毁,并且其占用的栈内存也会被释放。
两者之间的区别
- 内存位置:第一个例子中的
IntArray对象是在堆上分配的,而第二个例子中的IntArray对象是在栈上分配的。 - 生命周期:堆上分配的对象需要程序员手动管理其生命周期(通过
free函数释放内存),而栈上分配的对象的生命周期是自动管理的,随着函数或块的结束而自动销毁。 - 初始化:第一个例子中的
IntArray对象在分配内存后,其内容是未初始化的(即包含垃圾值),除非之后对其进行初始化。而第二个例子中的IntArray对象,如果IntArray是聚合类型(如结构体),且包含有自动初始化的成员(如全局或静态变量,或者包含基本数据类型的成员且未显式初始化),则其成员可能会被自动初始化为零或特定值。 - 使用场景:堆上分配的内存适用于需要长期存在或大小在编译时不确定的情况。栈上分配的内存适用于生命周期短且大小确定的情况。
总的来说,选择哪种方式取决于具体的应用场景和性能考虑。


Comments | NOTHING