C语言学习 — 自定义数据类型

举报
矜辰所致 发表于 2022/09/28 17:41:06 2022/09/28
【摘要】 C语言学习 — 自定义数据类型
最近重新学习了一下C语言教学视频看了看,把一些知识点细节记录一下。

一、自定义数据类型

typedef关键字

typedef 关键字,常用做法 typedef unsigned int uint,所以以前我还认为使用起来就是 typedef 旧名字 新名字,实际上是错误的。

语法是: typedef Type NewTypeName

使用的步骤是 : 在传统的变量声明表达式里,用 新的 类型名替换变量名 ,然后把关键字 typedef 加在该语句的开头。

下面的例子演示 typedef 的用法步骤,便于记忆 typedef 的用法(其实还是有点不太明白):

1、int a; //第一步,正常的定义某类型的变量
2、int my_int; //第二步,用新的类型名字 my_int 替换 变量名a;
3、 typedef int my_int;//第三步,在第二步的前面加上 typedef ;//实际上使用只有第三步
上面这个例子很常用,但是用于函数指针
1、void (*p)(int a); //第一步,定义一个函数指针变量 p
2、void (*PF)(int a); //第二步,用新的类型名字 *PF 变量名p;
3、 typedef void (*PF)(int a);//第三步,在第二步的前面加上 typedef ;//

typedef 的用途:

  1. 使用 typedef 为现有的类型创建别名。常用的:typedef unsigned long int uint32;
  2. 定义机器无关的类型。 typedef float REAL; /typedef double REAL; 我的理解这里怎么和第一点一样,不是太明白??????
  3. 简化一些比较复杂的声明, 用的相对不多这点有点不是太明白??下面的例子
/*不使用typedef 简化复杂的声明,Callback函数声明如下*/
Callback(u8 *begin, void (*pFunCallback)(u8* pchar, u8 Len), bool state); 
/*使用typedef ,Callback函数声明如下*/
typedef void (*PFunCallBack)(u8* pchar, u8 Len);

Callback(u8 *begin,PFunCallBack pFun, bool state);//等价于上面

示例

#include "stdio.h"

typedef float(FArr5)[5]; // 为 float[5] 数组类型取新名字  FArr5代表 float[5]
typedef int(IFuncII)(int, int); //  为 int (int, int) 函数类型取新名字 IFunII 表示函数类型

typedef FArr5* PFarr;     //为FArr5 (float[5])这个数组类型的指针取新名字
typedef IFuncII* PIFuncII;  // 为 指向这个类型的函数 的 指针 取新名字

float g_arr[5] = {0.1, 0.2 ,0.3}; //这个数组类型就是  FArr5 类型

int add(int a, int b)  // add 函数类型就是  IFunII
{
	return a + b;
}
int main()
{
	FArr5* pa = &g_arr; // pa是指针,指针指向 FArr5 这个类型的东西,这个类型是float[5]数组类型
	IFuncII* pf = add;  // pf是指针,指针指向 IFuncII 这个类型的东西,是int (int, int) 类型的函数

    PFarr  npa = pa;
	PIFuncII npf =pf;

	int i =0;

	for(i=0; i<5; i++){
		printf("%0.2f\n",(*pa)[i]);  //小数点保留2位,对其后的数据进行四舍五入
		printf("%f\n",(*pa)[i]);      //默认输出,小数点保留6位
		printf("%10.2f\n",(*pa)[i]); //输出宽度为10个字符,右对齐,前补空格,小数点保留2位
		
	}
	printf("%d\n",pf(2, 3));
	printf("%d\n",npf(2, 3));

	return 0;
}

在这里插入图片描述

typedef 和 #define

典型案例分析

    typedef char* pStr1;
    #define pStr2 char* 
    pStr1 s1, s2;
    pStr2 s3, s4;  //char *s3,s4;

通过上面的定义, s1,s2,为char* 类型,s3 为char* 类型, 但是s4 为char 类型, 因为#define 只是进行了字符串的替换,在定义 s3 s4 的时候,看注释,会变成s3 是指针,s4 是char

结构体和联合体

结构体使用我就直接贴图了,我看的视频教程是 唐佐林老师的C语言基础视频教程,因为是免费的,所以想看原视频的网上就能直接找到

struct:
在这里插入图片描述
union:
在这里插入图片描述
在这里插入图片描述
union demo:

  #include <stdio.h>
    union data{
        int n;
        char ch;
        short m;
    };
    int main(){
        union data a;
        printf("%d, %d\n", sizeof(a), sizeof(union data) );
        a.n = 0x40;
        printf("%X, %c, %hX\n", a.n, a.ch, a.m);
        a.ch = 'd';
        printf("%X, %c, %hX\n", a.n, a.ch, a.m);
        a.m = 0x2059;
        printf("%X, %c, %hX\n", a.n, a.ch, a.m);
        a.n = 0x3E25AD54;
        printf("%X, %c, %hX\n", a.n, a.ch, a.m);
       
        return 0;
    }

在这里插入图片描述
union的典型应用 – 判断系统大小端

    #include <stdio.h>
    /*
    小端系统: 低位数据存储在地地址内存中
    大端系统: 低位数据存储在高地址内存中

       0 x 00 00 00 01

    小端系统: [0X01][ 0 ][ 0 ][ 0 ]
               低   --------->   高
    大端系统: [0][ 0 ][ 0 ][ 0X01 ]
              低   --------->   高
    */
    int isLittleEnd()
    {
        union 
        {
            int i;
            char a[4];
        }test ={0};

        test.i = 1;
        return (test.a[0] == 1); //返回1,小端系统
    }
    int main(){
        printf("System Endian:%d\n",isLittleEnd());
        return 0;
    }

在这里插入图片描述

在这里插入图片描述在这里插入图片描述
注意:无名结构体类型总是互不相同的类型(互不兼容)下面看例子:

int main()
{
	struct 
	{
		int a; 
		int b;
	} v1;
	struct 
	{
		int a; 
		int b;
	} v2;
	struct 
	{
		int a; 
		int b;
	} *pv;

	v1.a = 1;
	v1.b = 2;
	
	v2 = v1; //错误的!!!!

	pv = &v2;	//错误的!!!!
}

柔性数组

结构体中有素组变量,但是却没有指定长度

#include<stdio.h>
struct softArray
{
	int len;
	int array[]; //不占用存储空间,所以sizeof softArray 为  4个字节
};

int main()
{
    printf ("len = %d\n",sizeof(struct softArray));  //len = 4
    return 0; 
}

柔性数组的使用:

#include<stdio.h>
#include<malloc.h>

struct softArray
{
	int len;
	int array[]; //不占用存储空间,所以sizeof softArray 为  4个字节
};

struct softArray* create_soft_array(int size)
{
	struct softArray* ret = NULL;
    
    if( size > 0){
        ret = (struct softArray*)malloc(sizeof(struct softArray) + sizeof(int) * size);
        ret->len = size;
    }
    
	return ret;
}

void delete_soft_array(struct softArray* sa)
{
    free(sa);
}

void func(struct softArray* sa)
{
    int i = 0;

    if( NULL != sa ){
        for(i=0; i<sa->len; i++){
            sa->array[i] = i + 1;
        }
    }
}
int main()
{
    int i = 0;
    struct softArray* sa = create_soft_array(10);

    func(sa);

    for(i=0; i<sa->len; i++){
        printf("%d\n",sa->array[i]);   //输出 1 23456789 10
    }
    delete_soft_array(sa);

    return 0;
}

位域

现在用得不多,位域成员必须是整形,占用的位数不能超过类型宽度,当存储位不足时,自动启用新的存储单元,可以舍弃当前未使用的位,重新启动新的单元

struct Bits1
{
    int a:   16; //正确
    short b:  8; //正确
    char  c:  8; //正确
    float f: 32; //错误  
}

struct Bits2
{
    unsigned char a:  6; //正确
    unsigned char b:  6; //正确
    unsigned char c:  4; //正确
    unsigned char d:  9; //错误  
}

struct Bits3
{
    unsigned char a:  4; //正确
    unsigned char  :  0; //正确
    unsigned char b:  4; //正确   [ a(4bits)  | 4bits(空)  ]  [ b(4bits) |    ]
}

枚举类型(enum)

  • enum 是C语言中的 自定义类型 关键字
  • enum能够定义 整形常量集合类型
  • 第一个常量值默认为 0,后续常量在前一个值的基础上加 1
  • 可以任意对美剧常量指定整形值(只能是整形
  • enum 枚举类型变量就是 整形 sizeof() 等于 4 ,就是int 类型
  • enum定义的值是真正意义上的常量

二、头文件相关

  • 头文件中只做函数声明和变量声明(不做具体定义
  • 头文件中可定义数据类型(typedef,struct,union,enum
  • 类型定义必须在头文件中,仅类型声明无法创建变量
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。