C语言需要初始化结构体的无法成功赋值


错误代码

#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));

这行代码执行了以下操作:

  1. 内存分配:使用malloc函数从堆(heap)中动态分配了足够存储一个IntArray类型对象所需的内存空间。sizeof(IntArray)计算了IntArray类型对象所需的字节数。
  2. 类型转换(IntArray*)是类型转换,将malloc返回的void*类型指针转换为IntArray*类型指针。在C语言中,malloc返回的是void*类型的指针,它可以被转换为任何其他类型的指针。
  3. 赋值:将分配好的内存地址赋值给IntArray*类型的指针变量intArray。这样,intArray就指向了一个动态分配的IntArray类型的对象。

第二行代码

IntArray intArray;

这行代码执行了以下操作:

  1. 自动变量声明:在栈(stack)上声明了一个IntArray类型的变量intArray。这意味着这个变量的生命周期是自动的,与包含它的函数或块的执行周期相同。一旦函数或块执行完毕,这个变量就会被自动销毁,并且其占用的栈内存也会被释放。

两者之间的区别

  • 内存位置:第一个例子中的IntArray对象是在堆上分配的,而第二个例子中的IntArray对象是在栈上分配的。
  • 生命周期:堆上分配的对象需要程序员手动管理其生命周期(通过free函数释放内存),而栈上分配的对象的生命周期是自动管理的,随着函数或块的结束而自动销毁。
  • 初始化:第一个例子中的IntArray对象在分配内存后,其内容是未初始化的(即包含垃圾值),除非之后对其进行初始化。而第二个例子中的IntArray对象,如果IntArray是聚合类型(如结构体),且包含有自动初始化的成员(如全局或静态变量,或者包含基本数据类型的成员且未显式初始化),则其成员可能会被自动初始化为零或特定值。
  • 使用场景:堆上分配的内存适用于需要长期存在或大小在编译时不确定的情况。栈上分配的内存适用于生命周期短且大小确定的情况。
    总的来说,选择哪种方式取决于具体的应用场景和性能考虑。

声明:一代明君的小屋|版权所有,违者必究|如未注明,均为原创|本网站采用BY-NC-SA协议进行授权

转载:转载请注明原文链接 - C语言需要初始化结构体的无法成功赋值


欢迎来到我的小屋