指针
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| int a=10; int *p; p=&a; printf("%d",*p);
printf("%p",&a); printf("%p",p);
printf("%d",a); printf("%d",*p);
|
- 意义:存储变量的地址
指针地址为十六进制的值,如果以%d输出地址将转化为十进制输出
找到地址->依靠指针类型得到数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| void swap(int a,int b) { int temp=b; b=a; a=temp; }
swap(c,d)
void swap(int *a, int *b) { int temp = *b; *b = *a; *a = temp; }
swap(&c,&d);
|
- 指针做加减法:指针加减某个整数:指向前或向后偏移几个位置,使其指向前/后几个位置
***指针之间相减:得到两个指针之间间隔的元素数量,即偏移量(地址上相差几个位置)
- 打印指针的地址:***%p***(打印指针指向的对象是用对象的占位符,如整数就是%d)
- 多重指针:一个指针指向零一个指针
- 指针数组:一个数组里储存的全是指针
- 函数指针:写法int/void (*p)() = Func;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| void Func() { printf("Hello World!\n"); } int main() { void (*p)() = Func; p(); return 0; }
int Func() { printf("Hello World!"); return 1; } int main() { int a;FunC int (*p)() = FunC; a=p(); printf("%d",a); return 0; }
|
动态内存分配
- malloc在堆上分配内存,通过free手动回收内存
1 2 3 4 5 6 7 8 9
| #include <malloc.h>
int *ptr=(int*)malloc(4); free(ptr); *ptr = 10; *ptr = a;
void *p = int *p = &a
|
- int a在栈上分配内存,生命周期结束后自动回收内存
- 生命周期:所在函数结束,大括号代表生命周期结束(全局变量会始终存在)
堆和栈都是内存中的区域
- 内存泄漏:用malloc分配后未释放,形成无用内存(影响程序运行)
malloc记得和free成组搭配使用
字符串
- 内存布局:环境,栈,堆,未初始化数据段(BSS)和初始化数据段(DS)
- 字符串声明方式
1 2 3
| char t[] = "Hello World"; char t* = "Hello World";
|
1 2 3 4
| scanf("%s",str); scanf("%[^\n]",str); gets(str); fgets(str,100,stdin)
|
1 2 3
| printf("%s",str); puts(str); fputs(str,stdout);
|
结构体
- 定义:一种数据结构,它由不同类型的数据组合成一个整体,以便引用,这些组合在一个整体中的数据是互相联系的,这样的数据结构称为结构体
1 2 3 4 5 6
| struct student{ char *name; int age; double score; }
|
- 定义类型typedef:为已有的数据类型定义一个新名字(类型别名) def意味define-定义
1 2 3 4 5 6 7 8 9 10 11
| typedef int myint; myint a = 1;
typedef struct { char *name; int age; double score; } student;
student a; student b;
|
1 2 3 4 5 6 7 8
| struct student{ char name[20]; int age; double score; }a={"ytm666",114514,1919.810},b={"hades",222222,52.886};
struct student b={"hades",222222,52.886}; 是student,因此可省略struct
|
1 2 3 4 5
| a.age=20; printf("%d",a.age);
struct student *p = &a; printf("%d",(*p).age);
|
printf(“%d”,p->age); //指针第二两种写法(代表指针指向的值
- 结构体只能存放变量,不可以定义函数,但我们可以在结构体中定义函数指针来调用不同函数
1 2 3 4 5 6 7 8 9
| typedef struct { void (*p)(); int age; double score; } student;
student a={"ytm666",114514,1919.810}; a.p() = Func1; a.p() = Func2;
|
- 32位系统中4字节一组(存储一个地址),指针占4个字节; eg:
00 00 00 01
- 64位(当今)系统中8字节一组,指针占8个字节;eg:
00 00 04 01 00 00 04 02
(现在都是64位计算机,因此指针默认占8个字节)
- 结构体内存对齐规则:
1.第一个成员在与结构体变量偏移量为0的地址处 2.从第二个成员开始,以后每个成员都要对齐到某个对齐数的整数倍位置,这个对齐数是自身成员大小和默认成员对齐数的较小值 3.当成员全部放入后,结构体的总大小必须是所有成员对齐数(每个成员变量都有一个对齐数)中最大对齐数的整数倍
typedef struct {
char b;
int *a;
char c;
int e;
} student;
- 对齐的意义:便于计算机访问,适配多种平台,提升运行速度