当前位置: 首页 > article >正文

C 学习笔记 —— 结构(二)

文章目录

    • 结构和指针
      • 传递结构地址进入函数
        • 传递结构
        • 结构和结构指针选择
      • 结构体中的指针
    • 把结构写入文件
    • 结构体内存对齐

结构和指针

注意结构体还不是数组,所以他的变量名和数组不一样,并不表示首元素地址。而是单独一个类型,所以使用结构体指针要注意。

struct guy {
    char favfood[LEN];
    char job[LEN];
    float income;
};

int main(void)
{
    struct guy *him = {
            "grilled salmon",
            "personality coach",
            68112.00
    };
    him->income = 53.4;

    struct guy him2 = {
            "grilled salmon",
            "personality coach",
            68112.00
    };
    him2.income = 433.5;
    struct guy *him3 = &him2;
    him3->income = 43.5;
   
   	// 使用malloc给某个结构体分配内存
	struct guy *stu
	    = (struct guy *)malloc(sizeof(struct guy));
}

注意结构体一般比较大,所以对于大的结构体一般不采用在栈上分配内存,空间可能不够,而在堆上分配内存。

传递结构地址进入函数

传递结构

struct funds {
    char   bank[FUNDLEN];
    double bankfund;
    char   save[FUNDLEN];
    double savefund;
};

double sum(struct funds moolah)
{
    return(moolah.bankfund + moolah.savefund);
}
double sum2(const struct funds * money)
{
    return(money->bankfund + money->savefund);
}

int main(void)
{
    struct funds stan = {
        "Garlic-Melon Bank",
        4032.27,
        "Lucky's Savings and Loan",
        8543.94
    };
    sum(stan); //传递结构
    sum2(&stan) //传递结构的地址
}

因为sum函数接收一个结构体指针,但是用const修饰表示不能修改指针指向值的内容。
传递结构和传递结构地址进入函数顾名思义,就是传递结构的时候实际上传递的是结构的副本,程序使用和修改的都是副本。
而传递结构地址则使用的是原来的结构。

结构和结构指针选择

传递结构:优点,操作的是副本对原数据进行保护,缺点是传递结构浪费时间和存储空间。所以小型结构可以使用直接传结构。
传递地址:优点:操作快,且不需要占用额外空间。缺点:会误操作而修改原结构变量。所以对于大型结构使用地址传递,当然如果想防止误操作可以加const修饰。

结构体中的指针

我们将结构体中的字符数组改成字符指针

struct funds1 {
    char   bank[20];
    char   save[20];
    }
struct funds2 {
    char   *bank;
    char   *save;
    }

对于funds1,结构体在创建对象的时候要分配40字节,
而对于funds2只需要16字节,因为每个指针占8字节。funds2不用为字符串分配空间,因为他存储的是地址,而字符串实际占用的空间是存储在别处的。所以这点在使用的时候就要注意。
看如下程序,就是malloc内存来存储字符串,然后用字符指针来指向这块内存。

struct namect {
    char * fname;  // using pointers
    char * lname;
    int letters;
};

void getinfo(struct namect *);        // allocates memory

int main(void)
{
    struct namect person;
    
    getinfo(&person);
}

void getinfo (struct namect * pst)
{
    char temp[SLEN];
    printf("Please enter your first name.\n");
    s_gets(temp, SLEN);
    // allocate memory to hold name
    pst->fname = (char *) malloc(strlen(temp) + 1);
    // copy name to allocated memory
    strcpy(pst->fname, temp);
}

把结构写入文件

/* booksave.c -- saves structure contents in a file */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXTITL  40
#define MAXAUTL  40
#define MAXBKS   10             /* maximum number of books */
#define BOOKNAME "book.txt"
char * s_gets(char * st, int n);
struct book {                   /* set up book template    */
    char title[MAXTITL];
    char author[MAXAUTL];
    float value;
};

int main(void)
{
    struct book library[MAXBKS]; /* array of structures     */
    int count = 0; //记录输入的结构体数量
    int index, filecount; //filecount记录第几个结构体
    FILE * pbooks;
    int size = sizeof (struct book);
    
    //新建一个文件
    if ((pbooks = fopen(BOOKNAME, "a+b")) == NULL)
    {
        fputs("Can't open book.dat file\n",stderr);
        exit(1);
    }
    
    rewind(pbooks);            /* go to start of file     */
    //读文件内容
    while (count < MAXBKS &&  fread(&library[count], size,
                                    1, pbooks) == 1)
    {
        if (count == 0)
            puts("Current contents of book:");
        printf("%s by %s: $%.2f\n",library[count].title,
               library[count].author, library[count].value);
        count++;
    }
    filecount = count;
    if (count == MAXBKS)
    {
        fputs("The book.dat file is full.", stderr);
        exit(2);
    }
    
    puts("Please add new book titles.");
    puts("Press double [enter] to stop.");
    while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
           && library[count].title[0] != '\0')
    {
        puts("Now enter the author.");
        s_gets(library[count].author, MAXAUTL);
        puts("Now enter the value.");
        scanf("%f", &library[count++].value);
        while (getchar() != '\n')
            continue;                /* clear input line  */
        if (count < MAXBKS)
            puts("Enter the next title.");
    }
    
    if (count > 0)
    {
        puts("Here is the list of your books:");
        for (index = 0; index < count; index++)
            printf("%s by %s: $%.2f\n",library[index].title,
                   library[index].author, library[index].value);
        //将结构体写入文件:定位到结构变量开始的位置,并把结构中所有字节都写入到文件
        //数据被分为count-file块,每块大小是一个结构体,写入到文件中 
        fwrite(&library[filecount], size, count - filecount,
               pbooks);
    }
    else
    	puts("No books? Too bad.\n");
    
    puts("Bye.\n");
    fclose(pbooks);
    
    return 0;
}

char * s_gets(char * st, int n)
{
    char * ret_val;
    char * find;
    
    ret_val = fgets(st, n, stdin);
    if (ret_val)
    {
        find = strchr(st, '\n');   // look for newline
        if (find)                  // if the address is not NULL,
            *find = '\0';          // place a null character there
        else
            while (getchar() != '\n')
                continue;          // dispose of rest of line
    }
    return ret_val;
}

结构体内存对齐

https://blog.csdn.net/weixin_69939913/article/details/126958523?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_baidulandingword~default-4-126958523-blog-91926731.235^v27^pc_relevant_default&spm=1001.2101.3001.4242.4&utm_relevant_index=7


http://www.kler.cn/a/6464.html

相关文章:

  • Android学习(五)-Kotlin编程语言-面向对象中的 继承-构造函数-接口三模块学习
  • Redis 集群实操:强大的数据“分身术”
  • 代码随想录day23 | leetcode 39.组合总和 40.组合总和II 131.分割回文串
  • OpenResty、Lua介绍认识
  • 单片机上电后程序不运行怎么排查问题?
  • 【游戏设计原理】20 - 囚徒困境
  • 【面试】互联网相关面试题
  • 操作系统结构
  • 【C语言学习】预处理命令
  • 【从零开始学习 UVM】10.7、UVM TLM —— TLM Fifo [uvm_tlm_fifo]
  • [windows-rs]Rust 调用 Windows API
  • 2023-4-1刷提情况
  • C++内存模型
  • LeetCode-5. 最长回文子串
  • Docker基础操作
  • c++编写动态星空
  • 我在 bilibili 学代码审计
  • Haar特征
  • 【CSS】课程网站横版导航栏 ( 横版导航栏测量及样式 | 代码示例 )
  • Linux中vi编辑器使用及ps系统管理命令
  • 如何看待 Chat-GPT 的崛起
  • Hibernate多表关联——(一对多关系)
  • 设计模式之责任链模式
  • 【Ruby学习笔记】15.Ruby 异常
  • 如何切换node版本
  • 【从零开始学习 UVM】9.3、UVM Config DB —— uvm_config_db 示例【文章最后的表格对于理解路径索引很重要】