十二、#define 定义的常量和宏
1.#define定义常量
#define MAX 100//#define定义的整数 #define STR "hehe"//#define定义的字符串 int main() { printf("%d\n", MAX);//相当于printf("%d\n",100); printf("%s\n", STR);//相当于printf("%s\n","hehe"); return 0; }
代码运行结果为:100 hehe。
2.#define定义的宏
#define ADD(x,y)((x)+(y))//#define定义的宏 int main() { int a = 10; int b = 20; int sum = ADD(a,b); printf("%d\n", sum); return 0; }
代码运行结果如下:
代码中#define ADD(x,y)((x)+(y))实现两数相加的功能,第一个()中分别是参数x和y,第二个()实现(x)+(y),建议给参数x和y也加上括号,因为在后面使用时,x和y可能不是一个值,而是一个表达式,带上括号避免因符号优先级引起的程序错误。
我们可以看到在上面定义时,#define定义的常量和宏都用的是大写字母,这是一种约定俗成,以后我们看见代码中的大写字母,它大概率就是#define定义的。
十三、指针
1.内存
内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的。
所以为了有效的使用内存,就把内存划分成一个个小小的内存单元,每个内存的大小是一个字节
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为内存单元的地址。
内存单元的编码具体如下图:
例如:
打开监视和内存窗口:
在监视中输入&a(取地址a)查看a的地址,在内存窗口中输入&a会发现,虽然a在内存中用4个字节存放,但a的地址使用的是a的第一个字节的地址
2.指针的定义
上面我们知道&a是取出a的地址,那么取出的地址该如何存储呢?
这时候就需要定义指针变量了。
int a=10; int *p;//p为一个整型指针变量 p=&a;
其中p作为指针变量存储a的地址。
3.指针的使用
int main() { int num = 10; int *p=#//地址 *p = 20;//通过p中的地址找到num,并重新赋值20 printf("%d\n", num); return 0; }
运行结果:
先把num的地址保存在p中,然后通过p中的地址找到num,并重新赋值20。
在内存中如下:
总结一下:
1.内存会被划分为小的内存单元,一个内存单元的大小是1个字节
2.每个内存单元都有编号,这个编号也被称为:地址/指针
3.地址/指针就可以存放在一个变量里,这个变量被称为指针变量
4.通过指针变量中存储的地址,就能找到指针指向的空间
4.指针变量的大小
一段测试指针变量大小的代码:
int main() { int a = 0; char b = "K"; double c = 3.14; int* pi= &a; char* pc = &b; double* pe = &c; printf("%d\n", sizeof(pi)); printf("%d\n", sizeof(pc)); printf("%d\n", sizeof(pe)); return 0; }
运行结果:
上述代码不论指针变量是什么类型,它的大小都是4byte
指针变量是用来存放地址的,地址的存放需要多大空间,指针变量的大小就应该是多大。
不同机器需要的空间不同:
32位机器 - 支持32位虚拟地址空间 - 产生的地址就是32bit位 - 需要32bit的空间存储 -指针变量的大小是4byte
64位机器 - 支持64位虚拟地址空间 - 产生的地址就是64bit位 - 需要64bit的空间存储 - 指针变量的大小是8byte
同样是上段代码,在x86和x64输出的结果不同:
上述代码不论指针变量是什么类型,它的大小都是8byte
十四、结构体
结构体是C语言中特别重要的知识, 前面我们学过int, short, long, float, double, long long, char这些统称为内置类型, 但是生活中的复杂对象不能用简单的一个数字或者字符就能描述出来,
比如描述学生,学生包含:名字+年龄+性别+学号这几项信息。
比如描述书籍,书籍包括:书名+出版社+作者+定价这些信息
这里只能用结构体来描述了。
//描述一个学生 //创建一个学生类型 struct stu { char name[20]; int age; char sex[5]; double score; };
注意:在结构体外面大括号要加上分号;
结构体的使用
struct stu { char name[20]; int age; char sex[5]; double score; }; int main() { struct stu s1 = { "张三",20,"男",90.5 }; struct stu s2 = { "如花",25,"女",95.0 }; printf("%s %d %s %lf", s1.name, s1.age, s1.sex, s1.score); //.是结构体成员访问操作符 //结构体变量.结构体成员 return 0; }
输出结果为:张三 20 男 90.500000
上述代码中的 . 是我们前面学操作符时没有讲的结构体成员访问操作符,我们要访问结构体成员是用“结构体变量.结构体成员”即可。
我们也可以用指针来访问结构体成员:
struct stu { char name[20]; int age; char sex[5]; double score; }; int main() { struct stu s1 = { "张三",20,"男",90.5 }; struct stu s2 = { "如花",25,"女",95.0 }; struct stu* p = &s1; printf("%s %d %s %lf", (*p).name, (*p).age, (*p).sex, (*p).score); return 0; }
以上代码结果依然为:张三 20 男 90.500000
但这样写好像有点复杂,下面我们还有种简单的方式:
struct stu { char name[20]; int age; char sex[5]; double score; }; int main() { struct stu s1 = { "张三",20,"男",90.5 }; struct stu s2 = { "如花",25,"女",95.0 }; struct stu* p = &s1; printf("%s %d %s %lf", p->name,p->age,p->sex,p->score); return 0; }
输出结果还是不变:张三 20 男 90.500000
用 p->name,p->age,p->sex,p->score代替了 (*p).name, (*p).age, (*p).sex, (*p).score
写起来更加简单,->同样是前面没有讲到的结构体成员访问操作符。我们要访问结构体成员是用“结构体指针->结构体成员”即可。
注意:输入时有所不同:
上述代码中结构体变量name和sex在输入时并没有取地址,原因是它们是数组,数组名本身就是地址,所以不需要取地址。
今天就先学到这里了,初识C语言已经完结,接下来我们将更加详细的学习前面的知识点,未完待续。。。