您的位置:首页 > 编程语言 > C语言/C++

c语言==复合数据类型(14)

2016-07-25 11:38 260 查看

struct结构体

作用:封装数据,即将多种不同类型的数存在一起

注释:

1、最后大括号后面记得加分号

2、结构体变量用.去访问

3、结构体指针用->去访问

如给结构体定义一个stu对象,则sizeof(stu)

字对齐:给每个变量分配4个字节

半字对齐:分配2个字节(short)

char  a;
short b;
char c;

sizeof(stu) = 8

char a;
char b;
short c;

sizeof(stu) = 4;


意义:防止内存空洞,将相同数据类型放在一起

用途:

传很多参数,用结构体封装起来传送

返回很多参数,用结构体封装起来返回

以下是一些程序语言里的注意点:

1、
char name[200];
strcpy(stu.name, "zhangsan");
//利用strcpy来给字符串赋值

2、
char * name;
stu.name = (char *)malloc(sizeof(char) * 100);
strcpy(stu.name, "zhangsan");
//指针要先分配空间再赋值

3、
struct student stu;
struct student *p_stu = &stu;
scanf("%d", &(p_stu->id));
//可以用一个结构体指针来指向一个结构体对象,然后通过这个指针来给对象里的数据成员赋值

4、
struct student stu = {
.id = 12;
.name = "zhangsan";
.age = 17
};
//在定义对象的时候就对她进行初始化,这时的字符串可以直接等于

5、
struct student stu_array[3] =
{
{1,"zhangsan",12},
{2,"lisi",13},
{3,"wangwu",14}
};
//定义了一个对象数组,所以在给他初始化的时候,要给他初始化三个对象。

6、
int i;
for(i = 0; i < 3; i++)
{
scanf("%d", &(stu_array[i].id));
scnaf("%s" , &(stu_array[i].name));
}
//手动给这个数组赋值


union共用体

他的访问与结构体一致

sizeof(stu)是数据成员里面最长的长度,同时这个数据成员的长度也满足字对齐和半字对齐

作用:测大小端

CPU属性:

大端字节序:高字节存放在低地址

小端存放:低字节存放在低地址



union共用体的一些程序特点

1、
union node
{
int num;
char ch;
};

int main()
{
union node p;
p.num = 1;
p.ch = 'a';
printf("%d\n", p.num);
return 0;
}
//答案是97,因为是共用体,所以是共用的一个存储单元,而a把1给覆盖掉了。所以最后输出的是97

2、
p.num = 0x12345678;
if(p.ch == 0x78)
{
printf("small\n");
}
else
{
printf("big\n");
}
//判断大小端存放

3、
int num = 0x12345678;
char *p = #
if(*p = 0x78)
{
printf("small\n");
}
else
printf("big\n");
//也是一种测大小端的方法


enum 枚举

注释:main函数中,int len = 17; 此时17是个幻数,指意不明

作用:显示整数宏

何时用:有大量的整数宏需定义

enum枚举程序的注意事项

enum node
{
A,
B,
C,
D,
E
};

enum node p = E;
printf("%d\n" , p);
//答案是4,若p = A, 答案是0
//sizof(p)永远都是4,不管p等于谁。

//总之,enum默认0,1,2,……,也可以自己赋值,如
INSERT_USER = 1,
DELETE_USER = 2,
DISPLAY_USER = 3,


预处理

分为宏定义和条件编译

作用:定义常量与命令,避免幻数

注释:后无分号

注意事项:1、大写字母 2、不要以_ _开头,否则会和内置宏冲突

注释:内置宏的格式: _ _ xxxx_ _

__LINE __代表函数, __func__代表所在函数名,  __TIME__代表时间,  __DATE__代表日期


debug_msg 打印调试信息

宏定义与枚举的区别

1、枚举常量是实体中的一种,但宏不是实体;

2、枚举常量属于常量,但宏不是常量;

3、枚举常量具有类型,但宏没有类型,枚举变量具有与普通变量相同的诸如作用域、值等性质,但宏没有,宏不是语言的一部分,它是一种预处理替换符。枚举类型主要用于限制性输入,例如,某个函数的某参数只接受某种类型中的有限个数值,除此之外的其它数值都不接受,这时候枚举能很好地解决这个问题。能用枚举尽量用枚举,否则在调试的时候你是看不到当时的值的。

4、用宏去定义一个变量如果你定义了一个相同的变量那么要看谁在前面,如果宏在前面变量会产生编译错误,而且这个错误很难查找,如果那个宏隐藏的很深的话。如果你定义的变量在前那么更可怕了,直接没有错误,但是宏定义被自定义的变量悄悄替换了。用枚举定义的话不管你定义的顺序前后关系怎样都会产生重复定义的错误。从上面的举例来看枚举比宏好用的多。宏还有一个特性是没有作用域,这里的作用域是指宏定义以后的代码都可以使用这个宏。宏可以被重复定义这个可能导致宏的值被修改。所以建议不要用宏去定义整形的变量,用枚举或者const。又会有用const还是枚举呢,世界一向如此纠结,枚举只能表示整形,const可以修饰任何类型。整形的情况下如果你要定义几种有关系的数值那么用枚举,否则用const。

5、枚举类型和define定义出来的常量,define 它可是是任意类型的数据,而枚举只能是整型的数据

宏函数

定义宏函数:#define Max(a,b) a>b?a:b

函数式的宏定义 : int num = Max(a,b);

注释:自定义函数与宏函数的区别

宏函数:不安全,不做语法检查,只做替换

自定义函数:效率低,要做分配和释放栈帧,传参,传返回值

编译时间换内存空间:宏函数

用时间换空间:宏函数

用内存空间换执行时间:内联函数/内嵌函数

用空间换时间:内联函数

//内联函数:将函数的内部实现搬迁到了调用的地方

//inline只修饰函数

typedef和#define的区别

1) #define是预处理指令,在编译预处理时进行简单的替换,不作正确性检查,不关含义是否正确照样带入,只有在编译已被展开的源程序时才会发现可能的错误并报错。例如:

#define PI 3.1415926


程序中的:area=PI*r*r 会替换为3.1415926*r*r

如果你把#define语句中的数字9 写成字母g 预处理也照样带入。

2)typedef是在编译时处理的。它在自己的作用域内给一个已经存在的类型一个别名,但是You cannot use the typedef specifier inside a function definition。

3)typedef int * int_ptr;



#define int_ptr int *


作用都是用int_ptr代表 int * ,但是二者不同,正如前面所说 ,#define在预处理 时进行简单的替换,而typedef不是简单替换 ,而是采用如同定义变量的方法那样来声明一种类型。也就是说;

//refer to (xzgyb(老达摩))

#define int_ptr int *


int_ptr a, b; //相当于int * a, b; 只是简单的宏替换

typedef int* int_ptr;

int_ptr a, b; //a, b 都为指向int的指针,typedef为int* 引入了一个新的助记符

这也说明了为什么下面观点成立

//QunKangLi(维护成本与程序员的创造力的平方成正比)

typedef int * pint ;

#define PINT int *


那么:

const pint p ;//p不可更改,但p指向的内容可更改

const PINT p ;//p可更改,但是p指向的内容不可更改。

pint是一种指针类型 const pint p 就是把指针给锁住了 p不可更改

而const PINT p 是const int * p 锁的是指针p所指的对象。

3)也许您已经注意到#define 不是语句 不要在行末加分号,否则 会连分号一块置换。

条件编译

#if 0
……
#endif
//表示注释掉了

#if 1
……
#endif
//表示重新恢复

#ifdef,#ifndef
//防止头文件包含带来的重复定义
//具体操作:
在头文件b.h里
加入头文件
#ifndef B_H
#define B_H
……
#endif

//这样写的目的就是防止重复定义
//所以写头文件的时候都要写#ifndef
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息