---------------------------------------------------------------------

枚举:

// main.c

#include <stdio.h>

const int red = ;
const int yellow = ;
const int green = ; int main(int argc, const char * argv[]) {
/*
常量符号化:用符号而不是具体的数字来表示程序中的数字; 这样看到符号才能知道背后的意思
*/
int color = -;
char *colorName = NULL;
printf("输入颜色代码:");
scanf("%d", &color);
switch (color) {
case red: colorName = "red"; break;
case yellow: colorName = "yellow"; break;
case green: colorName = "green"; break;
default: colorName = "unknow"; break;
}
printf("颜色是:%s\n", colorName); return ;
}
// main.c

#include <stdio.h>

enum COLOR {RED, YELLOW, GREEN};

int main(int argc, const char * argv[]) {
/*
枚举:用枚举而不是定义独立的const int变量
*/
int color = -;
char *colorName = NULL; printf("输入颜色代码:");
scanf("%d", &color);
switch (color) {
case RED: colorName = "red"; break;
case YELLOW: colorName = "yellow"; break;
case GREEN: colorName = "green"; break;
default: colorName = "unknow"; break;
}
printf("颜色是:%s", colorName); return ;
}
// main.c

#include <stdio.h>

enum color {red, yellow, green};    //声明数据类型color

void f(enum color c);               //f函数需要传入叫color的枚举类型

int main(int argc, const char * argv[]) {
/*
枚举是一种用户定义的数据类型,用关键字enum以如下语法来声明:
enum 枚举类型名字 {名字0, ..., 名字n}; 枚举类型名字通常并不是真的使用,要用的实在大括号里的名字,因为它们就是常量符号,它们的类型是int,值依次从0到n。如:
enum colors {red, yellow, green};
这样就创建了三个常量,red的值是0,yellow是1,green是2。 当需要一些可以排列起来的常量值时,定义枚举的意义就是给了这些常量值名字。
*/ /*
枚举量可以作为值 枚举类型可以跟上enum作为类型 但是实际上是以整数来做内部计算和外部输入输出的
*/ enum color t = red; //t是color的枚举类型 scanf("%d", &t);
f(t); return ;
} void f(enum color c) {
printf("%d\n", c);
}
//  main.c
#include <stdio.h> enum COLOR {RED, YELLOW, GREEN, NumCOLORS}; int main(int argc, const char * argv[]) {
/*
套路:自动计数的枚举(如:NumCOLORS)
这样需要遍历所有的枚举量或者需要建立一个用枚举量做下标的数组的时候就很方便了 枚举量:声明枚举量的时候可以指定值
enum COLOR {RED=1, YELLOW, GREEN = 5, NumCOLORS};
*/
int color = -;
char *ColorNames[NumCOLORS] = {
"red", "yellow", "green",
};
char *colorName = NULL; printf("输入颜色代码:");
scanf("%d", &color);
if (color >= && color < NumCOLORS) {
colorName = ColorNames[color];
} else {
colorName = "unknown";
} printf("颜色是:%s\n", colorName); /*
虽然枚举类型可以当作类型使用,但是实际上很少用;
如果有意义上排比的名字,用枚举比const int方便;
枚举比宏(macro)好,因为枚举有int类型。
*/ return ;
}

结构:

//  main.c
// Created by weichen on 15/6/28.
// Copyright (c) 2015年 weichen. All rights reserved.
#include <stdio.h> // 声明一种新的结构类型,非实体;.运算符左边的结构变量才是实体
struct date {
int month;
int day;
int year;
}; int main(int argc, const char * argv[]) {
/*
   - 结构类型 -
结构类型:复合数据类型, 成员变量可以是不同类型,声明结构类型是一条语句,结尾需要分号。
1.和本地变量一样,在函数内部声明的结构类型只能在函数内部使用。
2.所以通常在函数外部声明结构类型,这样就可以被多个函数所使用了。
3.结构类型和结构变量是两件事情,通过一种结构类型可以定义出很多结构变量,每个结构变量按照结构声明的样子具有相同的成员变量。 声明结构的形式:
1.
struct point {
int x;
int y;
}; struct point p1,p2;
// p1和p2都是point里面有x和y的值(变量)。 2.
struct {
int x;
int y;
} p1, p2;
// p1和p2都是一种无名结构,里面有x和y;p1和p2并不是类型的名字,这里只是想要两个变量p1和p2,而且以后不想继续使用这个结构,所以没有起名字;做法不常见。 3.
struct point {
int x;
int y;
} p1, p2;
// 声明一个point结构,并定义两个变量p1和p2,常见。 结构的初始化:
struct date today = {07, 31, 2014}; //以数组的方式顺序赋值
struct date thismonth = {.month=7, .year=2014}; //数组内以.成员变量的方式赋值,没有赋值的为0 结构成员:
结构和数组有点像
数组的成员类型必须一样,结构的成员类型可以不一样
数组用[]运算符和下标访问其成员,a[0] = 10;
结构用.运算符和名字访问其成员,today.day; student.firstName; p1.x; p1.y; 结构运算:
要访问整个结构,直接用结构变量的名字
对于整个结构,可以做赋值、取地址,也可以传递给函数参数
p1 = (struct point){5, 10}; //将5,10强制转换为point结构的变量, 赋给p1,相当于p1.x = 5; p1.y = 10;
p1 = p2; //相当于p1.x = p2.x; p1.y = p2.y; 数组变量在初始化后无法做这种赋值的运算 结构指针:
和数组不同,结构变量的名字并不是结构变量的地址,必须使用&运算符
struct date *pDate = &today; */ /*
定义一个结构的变量today(类型是struct date,下面就可以使用today)
struct date today; today.month = 06;
today.day = 28;
today.year = 2015;
*/ struct date today = {, , };
struct date thismonth = {.month=, .year=}; struct date t; //未赋值的结构变量
t = (struct date){, , }; //赋值
struct date m;
m = t; //m和t是两个不同的变量,赋值之后,m就得到了t所有成员的值
//m.year = 2016; 给m单独赋值,不会改变t的值 struct date *pDate = &today; printf("Today's date is %i-%i-%i\n", today.year, today.month, today.day); //Today's date is 2015-6-28 printf("This month is %i-%i-%i\n", thismonth.year, thismonth.month, thismonth.day); //This month is 2015-6-0 printf("t is %i-%i-%i\n", t.year, t.month, t.day); //t is 2015-6-28 printf("m is %i-%i-%i\n", m.year, m.month, m.day); //m is 2015-6-28 printf("%p", &pDate); //0x7fff5fbff7d8 return ;
}
//  main.c
// Created by weichen on 15/6/29.
// Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> struct point {
int x;
int y;
}; void getStruct(struct point);
struct point getStruct2(void);
void output(struct point); int main(int argc, const char * argv[])
{
/*
- 结构和函数 - 结构作为函数参数:
int numberOfDays(struct date d); 整个结构可以作为参数的值传入函数
这时候是在函数内新建一个结构变量,并复制调用者的结构的值
也可以返回一个结构
这与数组是不一样的 输入结构:
没有直接的方式可以一次scanf一个结构(就像%d这种)
写一个函数来读入结构
->
但是读入的结构如何送回来呢?
记住C在函数调用时是传值的
在函数中的p与main中的y是不同的
在函数读入了p的数值之后,没有任何东西回到main,所以y还是{0, 0} 解决方案:
之前的方案,把一个结构传入了函数,然后在函数中操作,但是没有返回回去
问题在于传入函数的是外面那个结构的克隆体,而不是指针
传入结构和传入数组是不同的
在这个输入函数中,完全可以创建一个临时的结构变量,然后把这个结构返回给调用者 结构指针作为参数:
如果一个大的结构传到函数里,通常更有效的是传递一个指针而不是拷贝整个结构 指向结构的指针:
struct date {
int month;
int day;
int year;
} myday; //声明一个date结构和结构变量myday struct date *p = &myday;
(*p).month = 12; //点运算符
p->month = 12; //用->运算符表示指针所指的结构变量中的成员 结构指针参数: struct point* getStruct2(struct point *p)
{
scanf("%d", &(p->x));
scanf("%d", &(p->y));
return p;
} void output(struct point p)
{
printf("%d, %d", p.x, p.y);
} void print(const struct point *p)
{
printf("%d, %d", p->x, p->y);
} void main()
{
struct point y = {0, 0};
getStruct2(&y);
output(y);
output(*getStruct2(&y));
printf(getStruct2(&y));
getStruct(&y)->x = 0;
*getStruct(&y) = (struct point){1, 2};
} */ struct point y = {, };
getStruct(y);
output(y); //0, 0 传的是结构变量y的"值",而不是指针,所以在getStruct内即使成员变量被赋值,不会影响y y = getStruct2(); //两个结构变量可以赋值
output(y); //4, 5 return ;
} void getStruct(struct point p)
{
scanf("%d", &p.x); //
scanf("%d", &p.y); //
printf("%d, %d\n", p.x, p.y); //2, 3
} struct point getStruct2(void)
{
struct point p; //本地变量
scanf("%d", &p.x); //
scanf("%d", &p.y); //
printf("%d, %d\n", p.x, p.y); //4, 5
return p;
} void output(struct point p)
{
printf("%d, %d\n", p.x, p.y); //0, 0
}
//  main.c
// Created by weichen on 15/7/5.
// Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> struct time {
int hour;
int minutes;
int seconds;
}; struct time timeUpdate(struct time now); int main(int argc, const char * argv[]) {
/*
- 结构中的结构 - 结构数组
struct date dates[100]; // 声明一个结构变量为数组
struct date dates[] = { // 初始化数组,每一个成员是struct
{4,5,2005}, {2,4,2005}
}; 结构中的结构
struct dateAndTime {
struct date sdate;
struct time stime;
}; 嵌套的结构
struct point {
int x;
int y;
};
struct rectangle {
struct point pt1;
struct point pt2;
};
如果有变量:
struct rectangle r;
就可以有:
r.pt1.x 、r.pt1.y, r.pt2.x 和 r.pt2.y 如果有变量定义:
struct rectangle r.*rp;
rp = &r;
那么下面的四种形式是等价的:
r.pt1.x #正常形式
rp->pt1.x #指针访问结构变量的成员
(r.pt1).x #加括号形式,不影响
(rp->pt1).x #加括号形式,不影响
但是没有rp->pt1->x(因为pt1不是指针),示意图: |--------------|
| |-----| |
r . |pt1 . |x | |
| |-----| |
+-> | |y | |
| | |-----| |
| |pt2 . x |
| | y |
| |--------------|
|
| |--------------|
rp | 指针 |
|--------------| 结构中的结构的数组:
struct point {
int x;
int y;
}; struct rectangle {
struct point p1;
struct point p2;
} void printRect(struct rectangle r)
{
printf("<%d, %d> to <%d, %d>\n", r.p1.x, r.p1.y, r.p2.x, r.p2.y);
} int main(int argc, char const *argv[])
{
int i;
struct rectangle rects[] = { //2rectangles, 1,2是rects[0]的pt1的x和y,3,4是rects[0]的pt2的x和y
{{1,2},{3,4}},
{{5,6},{7,8}}
};
for (i=0; i<2; i++) {
printRect(rects[i]);
}
} */ struct time testTimes[] = {
{,,}, {,,}, {,,}, {,,}, {,,}
}; int i; for (i=; i<; i++) {
printf("Time is %.2i:%.2i:%.2i\n", testTimes[i].hour, testTimes[i].minutes, testTimes[i].seconds); testTimes[i] = timeUpdate(testTimes[i]); printf("one second later is %.2i:%.2i:%.2i\n", testTimes[i].hour, testTimes[i].minutes, testTimes[i].seconds);
} // 结构成员变量的sizeof即为类型的大小,结构变量的sizeof为成员变量的sizeof之和
// 结构内成员之间连续,相邻成员的地址差不等于对应成员的sizeof
struct time ab = {, , };
printf("%ld, %ld, %ld, %ld\n", sizeof(ab), sizeof(ab.hour), sizeof(ab.minutes), sizeof(ab.seconds)); //12,4,4,4
printf("%p, %p, %p, %p, %ld\n", &ab, &(ab.hour), &(ab.minutes), &(ab.seconds), (&(ab.minutes) - &(ab.hour))); //0x7fff5fbff798, 0x7fff5fbff798, 0x7fff5fbff79c, 0x7fff5fbff7a0, 1 return ;
} struct time timeUpdate(struct time now)
{
++now.seconds;
if (now.seconds == ) {
now.seconds = ;
++now.minutes; if (now.minutes == ) {
now.minutes = ;
++now.hour; if (now.hour == ) {
now.hour = ;
}
}
} return now;
}

结构和数组的联系和区别

  原本结构和数组没什么联系。FORTRAN就出现了数组的概念,结构是在Algol中出现的,C++开始结构成为定义新的数据类型的主要方式。结构在编程语言中的地位是为了让用户可以定义集成在一起的一些量,给这个整体一个名字;而数组是为了表达能表达一连串相同类型的数据的。现在,如果离开C语言,站在更高的高度,我们如何看到结构和数组?

类型定义

//  main.c
// Created by weichen on 15/7/6.
// Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> int main(int argc, const char * argv[]) {
/*
- 自定义数据类型(typedef) - C语言提供了一个叫做typedef的功能来声明一个已有的数据类型的新名字,如:
typedef int Length; // Length成为int类型的别名, 等价于int类型
typedef *char[10] Strings; // Strings是10个字符串的数组的类型,10个字符指针的数组
typedef struct node {
int data;
struct node *next;
} aNode; 或 typedef struct node aNode; // 这样用aNode就可以代替struct node 这样,Length这个名字就可以代替int出现在变量定义和参数声明的地方了:
Length a,b,len;
Length numbers[10]; Typedef
声明新的类型的名字
新的名字是某种类型的别名
改善了程序的可读性 typedef long int64_t; // 重载已有的类型名字,新名字的含义更清晰,具有可移植性
typedef struct ADate { // 在typedef和最后单词中间的所有东西是它原来的类型
int month;
int day;
int year;
} Date; // 简化了复杂的名字 int64_t i = 1000000000;
Date d = {9, 1, 2005}; // 把一个struct命名为Date (struct名字我们不关心,因为有更好的方式来表达它了 - Date)
typedef struct {
int month;
int day;
int year;
} Date
*/ typedef struct {
int month;
int day;
int year;
} Date; Date a = {,,};
printf("%ld,%ld,%ld", a.month, a.day, a.year); //1,2,3 return ;
}
//  main.c
// Created by weichen on 15/7/6.
// Copyright (c) 2015年 weichen. All rights reserved. #include <stdio.h> typedef union {
int i;
char ch[sizeof(int)];
} CHI; int main(int argc, const char * argv[]) {
/*
- 联合 - 和struct非常相似 union AnElt {
int i;
char c;
} elt1, elt2; // 成员是一个int i 还是一个char c, sizeof(union ...) = sizeof(每个成员)的最大值 elt1.i = 4;
elt2.c = 'a';
elt2.i = 0xDEADBEEF; 和struct不一样的是:
存储
所有的成员共享一个空间
同一时间只有一个成员是有效的
union的大小是其最大的成员
初始化
对第一个成员做初始化
可以得到整数/float/double内部的各个字节
*/ CHI chi;
int i;
chi.i = ;
for (i=; i<sizeof(int); i++) {
printf("%02hhX", chi.ch[i]); //D2040000
}
printf("\n"); return ;
}

Link:http://www.cnblogs.com/farwish/p/4604233.html

[C语言]进阶|结构类型: 枚举, 结构, 类型定义的更多相关文章

  1. 苹果新的编程语言 Swift 语言进阶(九)--方法和下标

    一.方法 方法是与特定类型相关的函数.与属性一样,方法也包括实例方法和类型方法. 类.结构.枚举都能定义实例方法,用来封装或实现给定类型的一个实例相关的功能或特定任务. 类.结构.枚举也能定义与类型本 ...

  2. 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符

    [源码下载] 不可或缺 Windows Native (8) - C 语言: 结构体,共用体,枚举,类型定义符 作者:webabcd 介绍不可或缺 Windows Native 之 C 语言 结构体 ...

  3. C语言的结构体,枚举类型在程序中的作用

    http://www.xue63.com/xueask-1221-12212854.html 结构和枚举类型从程序实现的角度来说,是用更接近自然语言的方式来表达数据.比如说实现2维空间的点,你可以使用 ...

  4. 苹果新的编程语言 Swift 语言进阶(七)--枚举、结构、类

    Swift语言中,具有类特征的类型包括三种,即枚举类型.结构类型(包括基本类型,基本类型实际都是结构类型的特例).类.其中枚举类型.结构类型是属于值类型,类属于引用类型.三种类型都可以添加属性.方法. ...

  5. 自定义数据类型 C++ 结构体类型 共同体类型 枚举类型 类类型{}

    一.结构体类型 结构体类型,共用体类型,枚举类型,类类型等统称为自定义类型(user-defined-type,UDT). 结构体相当于其他高级语言中的记录(record);例如: struct St ...

  6. C语言进阶——结构体,联合,枚举

    ----------------------------------------------------------我是一条划分线----------------------------------- ...

  7. C#枚举类型和结构体

    注意:枚举类型和结构体都属于值类型. 结构体:就是一个自定义的集合,里面可以放各种类型的元素,用法大体跟集合一样. 一.定义的方法: struct student { public int nianl ...

  8. C语言中的系统时间结构体类型

    在C语言涉及中经常需要定时触发事件,涉及到获取系统时间,其结构体类型有多种.Unix/Linux系统下有以下几种时间结构: 1.time_t 类型:长整型,一般用来表示从1970-01-01 00:0 ...

  9. C# 结构体 枚举类型

    注意:枚举类型和结构体都属于值类型. 结构体:就是一个自定义的集合,里面可以放各种类型的元素,用法大体跟集合一样. 一.定义的方法: struct student { public int nianl ...

随机推荐

  1. Django-----加入MD5格式上传图片

    上传图片为什么要加 MD5 ? 答 :避免用户上传图片的时候图片名重复,而引起先上传的图片被后上传的图片所覆盖的失误! MD5是什么? 答:一种被广泛使用的密码散列函数,可以产生出一个128位(16字 ...

  2. 2--Postman脚本介绍

    Postman是访问各种API的客户端.它的强大之处在于其允许在对某一个request访问的之前和之后分别运行自定义的一段Javascript脚本,可以将数条request连结成一个流程完成一体化测试 ...

  3. 基于redis的延迟消息队列设计(转)

    需求背景 用户下订单成功之后隔20分钟给用户发送上门服务通知短信 订单完成一个小时之后通知用户对上门服务进行评价 业务执行失败之后隔10分钟重试一次 类似的场景比较多 简单的处理方式就是使用定时任务 ...

  4. es6学习日记4

    数组的扩展 扩展运算符是三个点(...).它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列. console.log(...[1, 2, 3]) // 1 2 3 console.l ...

  5. CSS3 transform变形(3D转换)

    一.三维坐标 空间中三维坐标如下图所示: 向上为-Y,向下为+Y,向左为-X,向右为+X,向前为+Z,向后为-Z. 二.perspective(n)为 3D 转换元素定义透视视图 perspectiv ...

  6. SQLI DUMB SERIES-7

    (1)查看PHP源代码 可以看见输入的id被一对单引号和两对圆括号包围 (2)根据提示:Dump into Outfile可知,此次攻击需要导出文件 (3)在第一关获取 @@datadir 读取数据库 ...

  7. 浏览器执行代码 是jsp 服务端执行的是<%%>

    接着上一个视频,想使得注销页面有一个很好的效果,那到底能不能再首页页面的<head>标签里写如下代码呢? 答案是肯定不行的.看执行以后的效果,执行之后,看到的网页源代码,如下图所示,造成这 ...

  8. Python数据存储:pickle模块的使用讲解

    在机器学习中,我们常常需要把训练好的模型存储起来,这样在进行决策时直接将模型读出,而不需要重新训练模型,这样就大大节约了时间.Python提供的pickle模块就很好地解决了这个问题,它可以序列化对象 ...

  9. Head First 设计模式 (Eric Freeman / Elisabeth Freeman / Kathy Sierra / Bert Bates 著)

    1. 欢迎来到设计模式世界:设计模式入门 (已看) 策略模式 定义了算法族,分别分装起来,让它们之间可以互相替换,此模式让算法的变化独立于使用算法的客户. 设计原则 找出应用中可能需要变化之处,把它们 ...

  10. git bash的安装与配置

    作业要求来自于:https://edu.cnblogs.com/campus/gzcc/GZCC-16SE2/homework/2097 1.下载安装配置用户名和邮箱. (1)下载安装Github配置 ...