首页 > 其他分享 >C语言之typedef,位运算

C语言之typedef,位运算

时间:2024-07-20 14:01:13浏览次数:8  
标签:typedef 定义 int unsigned C语言 位段 类型 运算

typedef

用typedef 声明新的类型名来代替已有的类型名
声明 INTEGER 为整型Typedef int INTEGER

定义整形变量

定义结构体

定义数组

定义字符型

声明 POINT 为指向函数的指针类型,该函数返回整型值typedef int (*POINT)();

用typedef可以声明各种类型名,但不能用来定义变量
使用typedef只是对已经存在的类型增加了一个类型类型而没有创建新的类型。
当不同源文件中用到同一类型数据时,常用typecf声明一些数据类型,把它们单独放在一个文件中,然后在需要用到它们的文件中用#include命令把他们包含进来

1. 类型检查

  • typedeftypedef为已存在的类型定义一个新的名称(别名)。在使用这个别名时,编译器会进行类型检查,确保类型使用正确。如果类型不匹配,编译器会报错,有助于及早发现和修正错误。
  • definedefine是宏定义,它在预处理阶段进行简单的文本替换,不进行类型检查。因此,如果替换后的文本在类型上不匹配,编译器可能在后期才能发现错误,甚至可能引发难以追踪的bug。

2. 作用范围

  • typedeftypedef定义的类型别名具有作用域限制,它只在定义它的作用域内有效。这有助于避免命名冲突,提高代码的可维护性。
  • definedefine定义的宏是全局的,除非在定义时使用了某种形式的作用域限制(如通过#undef取消定义)。这可能导致意外的命名冲突,特别是在大型项目中。

3. 执行时间

  • typedeftypedef是在编译过程中处理的,它作为类型别名存在,不增加额外的运行时间开销。
  • definedefine在预处理阶段就进行了文本替换,虽然它本身不增加运行时间开销,但由于其不进行类型检查,可能导致编译后的代码中存在潜在的性能问题或错误。

4. 对指针的操作

  • typedefdefine 在定义指针类型时表现不同。使用typedef定义指针类型时,可以更清晰地表达指针的层次结构,提高代码的可读性。而使用define定义指针时,可能会因为文本替换的特性导致指针的层次结构变得模糊,增加理解和维护的难度。

5. 代码可读性和可维护性

  • typedef:通过为复杂类型定义简洁的别名,typedef可以显著提高代码的可读性和可维护性。它使得代码更加简洁明了,易于理解和修改。
  • define:虽然define在某些情况下(如定义常量)很有用,但它也可能导致代码的可读性和可维护性下降。特别是当宏定义变得复杂或宏之间存在相互作用时,维护起来可能会非常困难。

位运算

1.位运算符中除~以外,均为双目运算符,即要求两侧各有一个运算量。
2.运算量只能是整型或字符型的数据,不能为实型数据。

1 清零作用

2 取数中某些指定位

按位或

异或

^   运算符

取反运算符

左移运算符

右移运算符

位运算赋值运算符

循环移位

位段

位段(或称“位域”,Bit field)是C语言特有的一种数据结构,它允许开发者以位(bit)为单位来定义结构体(或共用体)中成员所占的内存长度。这种数据结构的主要目的是为了减少存储数据的位数,从而节省内存空间。下面我将以通俗易懂的方式解释位段:
1. 基本概念

    位段成员:位段的成员必须是int、unsigned int、signed int或char类型(但通常只用unsigned int和int,因为位操作通常与无符号数相关)。
    位段声明:位段的声明类似于结构体,但成员名后面会跟一个冒号(:)和一个数字,这个数字表示该成员所占的位数。
    节省空间:通过精确指定每个成员所需的位数,位段能够比传统的结构体更节省内存空间。

2. 举例说明

假设我们有一个场景,需要存储一个标志位(flag,只需要1位)、一个类型(type,需要4位)和一个索引(index,需要9位)。在传统的方法中,我们可能会这样声明:

unsigned int flag; // 实际上只用了1位,但浪费了31位  
unsigned int type; // 用了4位,但浪费了28位  

unsigned int index; // 用了9位,但浪费了23位

使用位段,我们可以这样声明:

struct packed_struct {  
    unsigned int flag : 1;  
    unsigned int type : 4;  
    unsigned int index : 9;  

};

这样,packed_struct总共只需要14位(实际上可能会因为内存对齐而占用更多字节,但原则上只需要这么多位)。
3. 注意事项

    内存对齐:位段在内存中的布局可能会受到内存对齐规则的影响,导致实际占用的空间比理论上多一些。
    跨平台问题:位段在不同平台上的表现可能会有所不同,因为不同的编译器和平台可能有不同的内存对齐和位段处理规则。
    位段长度限制:位段的长度不能大于其基础类型的长度(如int类型通常是32位,所以位段长度不能超过32)。
    无法定义位段数组:位段不支持定义数组,因为每个位段成员的大小是固定的。
    无法取地址:位段没有地址,因此不能对位段进行取地址运算。

4. 使用场景

位段通常用于需要节省内存空间的场景,如嵌入式系统、网络通信协议中的数据打包等。在这些场景中,数据的每一位都有明确的含义,使用位段可以高效地处理和存储这些数据。
5. 示例代码

#include <stdio.h>  
 
struct packed_struct {  
    unsigned int flag : 1;  
    unsigned int type : 4;  
    unsigned int index : 9;  
};  
 
int main() {  
    struct packed_struct data;  
    data.flag = 1;  
    data.type = 7;  
    data.index = 123; // 注意:如果index的值超出了9位的范围,超出的部分会被截断  
 
    // 假设有一个函数可以打印位段的值(这里仅作示意)  
    // print_bitfield(data);  
 
    return 0;  

}

在这个示例中,我们定义了一个packed_struct类型的变量data,并为其成员赋值。由于index的值123超出了9位的范围,因此只有低9位(即01111011)会被存储在index中。

标签:typedef,定义,int,unsigned,C语言,位段,类型,运算
From: https://blog.csdn.net/2302_81386929/article/details/140568977

相关文章

  • c语言学习
    double中用%lf进行输入scanf("%lf",&x); .在整型数组中用%d进行输入scanf("%d",&a); 注意:数组名必须带取地址符&  注意:此时&a传输的是首地址   4.在字符串数组中用%s进行输入scnaf("%s",a); 注意:数组名不能带取地址符& scanf("%s",a)函数输入字......
  • ## 学习笔记day05-C语言基础:控制语句 if else、do while、for循环
    day05六、控制语句1.顺序语句​在模块内部没有分支、跳转、循环等条件时,程序按照顺序执行2.分支语句选择语句if...else单分支if(表达式){代码块;} step:先判断表达式是否为真(非0为真,0为假)如果为真,进入if选择结构,执......
  • 【C语言】实现一个通讯录,一步一步详细讲解,小白也能看!!!
    目录设计思路代码实现 代码仓库 设计思路1.通讯录存放的信息这个通讯录保存的信息包括:名字,年龄,性别,电话,住址。2.通讯录的功能1.通讯录可以存放100个人的信息。2.增加联系人3.删除联系人4.修改联系人5.查询联系人6.显示所有人3.文件规划我们准......
  • Java入门基础:Java中的标识符;Java常量与变量;Java基本数据类型;Java运算符
    一,Java标识符【1】标识符:读音 biaozhifu (注意是标zhi符,不是标shi符,“识”这个字是多音字,我也是才发现^_^,你呢?)【2】标识符是?     包,类,变量,方法.....等等,只要是起名字的地方,那个名字就是标识符。【3】标识符定义规范:  1.四个可以(组成部分):数字,字母,下划......
  • C语言典型例题7
    本系列博客针对于《C程序设计教程(第四版)——谭浩强编著》这本书中的所有例题和习题进行了详细的解释和学习,希望可以对你学习C语言可以有所帮助。有些代码可能会在前面详细解释,后面会一笔带过,希望大家可以多多翻阅,谢谢大家啦!!!嘻嘻!!!例题:求5!。//《C程序设计教程(第4版)——谭浩强......
  • 洛谷P1012 拼数 C语言
    这个题可以用字符串去做,接受字符来去计算大小,这里可以用到strcmp函数str1="123"str2="124"strcmp(str1,str2)如果说str1比str2大就会返回大于0的数,一般是1;如果相等返回0,小于返回-1.它是比较这两个字符串的ascll值来比较的,比方说3的ascll值就比4小,那么前面的都相同,那......
  • Python入门知识点 4--格式化输出与运算符
    1、格式化输出name='小赵'age=18#print('大家好,我是'+name+'我今年'+age+'岁了')#字符串和整型不能拼接print('大家好,我是'+name+'我今年'+str(age)+'岁了')#把整型转换成字符串输出,但比较麻烦print('大家好,我是',name,'我今年',age,&#......
  • 奇妙的 c++ 混合运算式
    先来看看如下的式子:a*b+c当你在c++中运行它时,你很清楚它是先计算*再计算+的。那么请再来看看这个式子:a+b+c请问它是先执行第一个+,还是先执行第二个+呢?这个问题看上去无解,但实际上我们可以解答:#definelllonglonginta=INT_MAX,b=INT_MAX;llc......
  • C语言_数组(1)
    一、一维数组1、数组的创建方式:数组是有限个相同类型数据元素的集合。type_t arr_name [const_n];//type_t是指数组的元素类型//const_n是一个常量表达式,用来指定数组的大小创建例子:注意:数组在创建时,[]里的必须是常量。但是如果编译器支持C99标准的话可以使用......
  • 采用反相正基准电压电路的反相运算放大器(运放)
    采用反相正基准电压电路的反相运算放大器(运放)采用反相正基准电压电路的同相运算放大器(运放)设计目标输入ViMin输入ViMax输出VoMin输出VoMax电源电压Vcc电源电压Vee电源电压Vref-5V-1V0.05V3.3V5V0V5V设计说明1此设计使用具有反相正基准的反相放大器将–5V至–1V的输......