一、#define 定义常量和宏
1、#define定义标识符常量
#define MAX 1000
2、#define定义宏-带参数
#define ADD(x,y) ((x)+(y))
#include<stdio.h>
int main()
{
int sum = ADD(2, 3);
printf("sum = %d\n", sum);
sum = 10*ADD(2, 3);
printf("sum = %d\n", sum);
return 0;
}
同理,求最大值函数的宏应该这样写:
#define MAX(X,Y) X>Y?X:Y
二、指针
1、内存
内存是电脑上特别重要的存储器,计算机中所有程序的运行都是在内存中进行的 。
所以为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节。
为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址。
如何产生地址?
32位指的是32根地址线/数据线
一旦通电,就有正电和负电的区别
那么可以定义正电为1,负电为0
00000000000000000000000000000000
00000000000000000000000000000001
00000000000000000000000000000010
......
1111111111111111111111111111111111111
一共有2^32的二进制序列
那么可以把每一个序列作为内存编号
可以编2^32个编号
分配给2^32个内存块
这个编号就叫做对应内存块的地址
那么一个单元多大好呢?
假设一个单元1个bit位
那么一共有2^32bit = 0.5GB
对于现代计算机来说是远远不够用的
如果是1个字节(1B)呢?
则是4GB
还是比较合理的
变量都有地址,取出变量地址如下:
int main()
{
int num = 10;
#//取出num的地址
printf("%p\n", &num);//打印地址,%p--以地址的形式打印
return 0;
}
运行结果:
具体过程如下:
2、指针变量
那地址如何存储?这时候我们需要定义指针变量。
int num = 10;
int* p;//p为一个整形指针变量
p = #
存放整型的变量我们用int类型来定义;
存放整型变量的地址的变量,我们用int*类型来定义。
我们想用p这个指针变量来存放num的地址,
所以首先我们应该定义p:
int* p;
代表p是一个存放整型变量地址的指针变量。
p中的值是num的地址,
那么*p呢?
*是一个解引用操作符。
*和&是一对操作符
也就是说,*&num = num;
又因为p = &num,
所以*p = num。
所以,
*p = 20;
这段代码的意思是,把num的值改成20。
这里,int*是一个类型!建议写int* p,而不是int *p,后者会让人产生*p是一个int类型变量的误解。
指针使用实例:
#include<stdio.h>
int main()
{
int num = 10;
int *p = #
*p = 20;
return 0;
}
具体过程如下:
以整形指针举例,可以推广到其他类型,如:
#include <stdio.h>
int main()
{
char ch = 'w';
char* pc = &ch;
*pc = 'q';
printf("%c\n", ch);
return 0;
}
指针变量的大小:
#include <stdio.h>
int main()
{
printf("%d\n", sizeof(char *));
printf("%d\n", sizeof(short *));
printf("%d\n", sizeof(int *));
printf("%d\n", sizeof(double *));
return 0;
}
结论:指针大小在32位平台是4个字节,64位平台是8个字节。
三、结构体
结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。
比如描述学生,学生包含: 名字+年龄+性别+学号 这几项信息。
这里只能使用结构体来描述了。
举例:
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};
结构体的初始化:
//打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id);
//->操作符
struct Stu* ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps-
>id);
1、s.name等价于(*ps).name;
因为ps是一个指向Stu这个结构体的指针,里面存放着这个结构体的地址
而*ps对其进行了解引用,即*ps = s;
2、->操作符
s.name等价于(*ps).name等价于ps->name;
点操作符运用于结构体变量
即结构体变量.成员
或者(*结构体指针).成员
箭头操作符运用于结构体指针
即结构体指针->成员
也就是说,以下三种写法等价:
struct Stu {
int age;
char sex;
};
Stu s = { 10,'男' };
struct Stu* ps = &s;
printf("%d\n", s.age);
printf("%d\n", (*ps).age);
printf("%d\n", ps->age);
均打印出10。
更改结构体中数组类型成员
struct Stu
{
char name[20];//名字
int age; //年龄
char sex[5]; //性别
char id[15]; //学号
};
对于age,因为它是一个变量
所以我们可以直接用
s.age = 20;
来更改s这个学生的年龄;
那么如何改上述s这个人的名字呢?
如果直接用:
s.age = 20;
程序会报错,
因为name[20]是一个数组。
要更改的话,需要用到以下这一个函数:
strcpy();
全名:string copy--字符串拷贝函数。
意思是把一个新的字符串拷贝到name这个数组中。
需要用到头文件:#include<string.h>
strcpy(b1.name,"C++");