在使用指针之前,务必要将其初始化。这个是我们最早学习 C 语言的时候,书上经常说的一个问题。在工作中,我们反而会经常忘记这条金科玉律。

结构体成员指针的初始化

结构体成员指针的初始化,指的是初始化结构体中指针变量的成员。

我们举个例子,下面是 Animal 的结构体,定义在animal.h头文件中:

struct Animal {
    char *name; //指针成员
    int age;
    char info[200]; //字符数组
    struct Animal *nextAnimal; //指针成员
};

结构体 Animal 含有4个成员变量,其中 nameinfonextAnimal 是指针变量。

测试函数都是在main函数中执行,省略了main函数;

写一段测试代码,如下:

void test01(){
    struct Animal animal;
    printf("name:%s, age:%i, info:%s\n", animal.name, animal.age, animal.info);
}

运行结果正常,终端输出如下:

name:(null), age:0, info:

来验证一下 Animal *nextAnimal 在没有初始化的情况下,会不会有什么问题:

void test02(){
    struct Animal animal;
    printf("animal.nextAnimal:%p\n", animal.nextAnimal);
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
            animal.nextAnimal->age, animal.nextAnimal->info);
}

程序编译没有问题,运行报错:

animal.nextAnimal:0x400a4d
Signal: SIGSEGV (Segmentation fault)

修改一下代码,初始化一下 animal.nextAnimal 这个指针,如下:

void test03(){
    struct Animal animal;
    printf("animal.nextAnimal:%p\n", animal.nextAnimal);

    animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
    animal.nextAnimal->name = "cat";
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
           animal.nextAnimal->age, animal.nextAnimal->info);
}

再次编译,重新运行正常:

animal.nextAnimal:0x400a4d
animal.nextAnimal->name:cat,age:0,info:

还需要初始化 animal.nextAnimal->name 这个变量:

void test04(){
    struct Animal animal;
    animal.name = "cat";
    strcpy(animal.info, "This is a cat!");
    printf("name:%s, age:%i, info:%s\n", animal.name, animal.age, animal.info);
    //name:cat, age:1467878128, info:This is a cat!

    printf("animal.nextAnimal:%p\n", animal.nextAnimal);
    //初始化结构体指针
    animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));

    animal.nextAnimal->name = "dog";
    strcpy(animal.nextAnimal->info, "This is a dog!");
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
           animal.nextAnimal->age, animal.nextAnimal->info);
    //animal.nextAnimal->name:dog,age:0,info:This is a dog!
}

编译运行,一切正常:

name:cat, age:0, info:This is a cat!
animal.nextAnimal:0x400a4d
animal.nextAnimal->name:dog,age:0,info:This is a dog!

通过上面的例子,结构体指针变量有些会给默认值,有些又不会给,所以都要初始化指针变量。

结构体指针的初始化

指的是初始化结构体指针变量。

void test05(){
    struct Animal *pAnimal;
    printf("name:%s, age:%i, info:%s\n", pAnimal->name, pAnimal->age, pAnimal->info);
}

编译运行报错:

Signal: SIGSEGV (Segmentation fault)

同样的道理,需要初始化指针变量。完成后的示例代码如下:

void test06(){
    struct Animal *pAnimal;
    //初始化结构体指针
    pAnimal = (struct Animal*)malloc(sizeof(struct Animal));
    pAnimal->name = "dog";
    strcpy(pAnimal->info, "This is a dog!!!");
    printf("name:%s, age:%i, info:%s\n", pAnimal->name, pAnimal->age, pAnimal->info);

    pAnimal->nextAnimal = (struct Animal*)malloc(sizeof(struct Animal));
    pAnimal->nextAnimal->name = "puppy";
    strcpy(pAnimal->nextAnimal->info, "This is a puppy.");
    printf("pAnimal->nextAnimal->name:%s,age:%i,info:%s\n",pAnimal->nextAnimal->name,
           pAnimal->nextAnimal->age, pAnimal->nextAnimal->info);
}

完整示例

animal.h 头文件

#ifndef LINUX_C_ANIMAL_H
#define LINUX_C_ANIMAL_H

#endif //LINUX_C_ANIMAL_H

struct Animal{
    char *name;
    int age;
    char info[200];
    struct Animal *nextAnimal;
};

animal.c文件

#include <stdio.h>
#include <malloc.h>
#include <string.h>
#include "animal.h"

void test01(){
    struct Animal animal;
    printf("name:%s, age:%i, info:%s\n", animal.name, animal.age, animal.info);
}

/**
 * 指针未初始化使用,程序编译没有问题,运行会报错
 */
void test02(){
    struct Animal animal;
    printf("animal.nextAnimal:%p\n", animal.nextAnimal);
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
            animal.nextAnimal->age, animal.nextAnimal->info);
}

/**
 * 动态分配内存空间后运行正确
 */
void test03(){
    struct Animal animal;
    printf("animal.nextAnimal:%p\n", animal.nextAnimal);

    animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));
    animal.nextAnimal->name = "cat";
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
           animal.nextAnimal->age, animal.nextAnimal->info);
}

/**
 * 结构体指针变量有些会给默认值,有些又不会给,所以都要初始化指针变量
 * animal.age如果不赋值,则默认值可能是1467878128,不一定是0
 */
void test04(){
    struct Animal animal;
    animal.name = "cat";
    strcpy(animal.info, "This is a cat!");
    printf("name:%s, age:%i, info:%s\n", animal.name, animal.age, animal.info);
    //name:cat, age:1467878128, info:This is a cat!

    printf("animal.nextAnimal:%p\n", animal.nextAnimal);
    //初始化结构体指针
    animal.nextAnimal = (struct Animal *)malloc(sizeof(struct Animal));

    animal.nextAnimal->name = "dog";
    strcpy(animal.nextAnimal->info, "This is a dog!");
    printf("animal.nextAnimal->name:%s,age:%i,info:%s\n",animal.nextAnimal->name,
           animal.nextAnimal->age, animal.nextAnimal->info);
    //animal.nextAnimal->name:dog,age:0,info:This is a dog!
}

/**
 * 编译报错
 */
void test05(){
    struct Animal *pAnimal;
    printf("name:%s, age:%i, info:%s\n", pAnimal->name, pAnimal->age, pAnimal->info);
}

/**
 * 使用结构体前都必须先初始化
 */
void test06(){
    struct Animal *pAnimal;
    //初始化结构体指针
    pAnimal = (struct Animal*)malloc(sizeof(struct Animal));
    pAnimal->name = "dog";
    strcpy(pAnimal->info, "This is a dog!!!");
    printf("name:%s, age:%i, info:%s\n", pAnimal->name, pAnimal->age, pAnimal->info);

    pAnimal->nextAnimal = (struct Animal*)malloc(sizeof(struct Animal));
    pAnimal->nextAnimal->name = "puppy";
    strcpy(pAnimal->nextAnimal->info, "This is a puppy.");
    printf("pAnimal->nextAnimal->name:%s,age:%i,info:%s\n",pAnimal->nextAnimal->name,
           pAnimal->nextAnimal->age, pAnimal->nextAnimal->info);
}

int main(int argc, char *argv[]){

//    test01();
//    test02();
//    test03();
//    test04();
//    test05();
    test06();
    return 0;
}

发表评论