- int *p=NULL; // 定义指针变量
-
- int a = 5;
- int *p = &a;
- printf("a = %d", *p); // 访问指针变量
-
- char c = 'a';
- char *cp;
- cp = &c;
- char **cp2;
- cp2 = &cp;
- printf("c = %c", **cp2);
-
- int ***m1; //取值***m1
- int *****m2; //取值*****m2
-
##数组指针的概念及定义
- printf(“%p %p”, &(a[0]), a); //输出结果:0x1100, 0x1100
-
- 注意: 数组名a不代表整个数组,只代表数组首元素的地址。
- “p=a;”的作用是“把a数组的首元素的地址赋给指针变量p”,而不是“把数组a各元素的值赋给 p”
- int main (void)
- {
- int a[5] = {2, 4, 6, 8, 22};
- int *p;
- // p = &(a[0]);
- p = a;
- printf(“%d %d\n”,a[0],*p); // 输出结果: 2, 2
- }
- 如果指针变量p已指向数组中的一个元素,则p+1指向同一数组中的下一个元素,p-1指向同 一数组中的上一个元素。
- int x[10];
- x++; //错误
- int* p = x;
- p++; //正确
-
- char string[]=”I love lnj!”;
- printf("%s\n",string);
-
- // 数组名保存的是数组第0个元素的地址, 指针也可以保存第0个元素的地址
- char *str = "abc"
-
- har *str = "lnj";
- for(int i = 0; i < strlen(str);i++)
- {
- printf("%c-", *(str+i)); // 输出结果:l-n-j
- }
-
- // + 使用字符数组来保存的字符串是保存栈里的,保存栈里面东西是可读可写,所有可以修改字符串中的的字符
- // + 使用字符指针来保存字符串,它保存的是字符串常量地址,常量区是只读的,所以我们不可以修改字符串中的字符
- char *str = "lnj";
- *(str+2) = 'y'; // 错误
-
- // 错误的原因是:str是一个野指针,他并没有指向某一块内存空间
- // 所以不允许这样写如果给str分配内存空间是可以这样用 的
- char *str;
- scanf("%s", str);
-
- int sum(int a,int b)
- {
- return a + b;
- }
-
- int (*p)(int,int);
- p = sum;
-
- struct 结构体名{
- 类型名1 成员名1;
- 类型名2 成员名2;
- ……
- 类型名n 成员名n;
- };
-
- struct Student {
- char *name; // 姓名
- int age; // 年龄
- float height; // 身高
- };
-
- struct Student {
- char *name;
- int age;
- };
-
- struct Student stu;
-
- struct Student {
- char *name;
- int age;
- } stu;
-
- struct {
- char *name;
- int age;
- } stu;
-
- 第三种方法与第二种方法的区别在于,第三种方法中省去了结构体类型名称,而直接给出结构变量,这种结构体最大的问题是结构体类型不能复用
- struct Student {
- char *name;
- int age;
- };
- struct Student stu;
- // 访问stu的age成员
- stu.age = 27;
- printf("age = %d", stu.age);
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu = {“lnj", 27};
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu = {.age = 35, .name = “lnj"};
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu;
- stu.name = "lnj";
- stu.age = 35;
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu;
- stu2 = (struct Student){"lnj", 35};
-
- //定义一个全局结构体,作用域到文件末尾
- struct Person{
- int age;
- char *name;
- };
-
- int main(int argc, const char * argv[])
- {
- //定义局部结构体名为Person,会屏蔽全局结构体
- //局部结构体作用域,从定义开始到“}”块结束
- struct Person{
- int age;
- };
- // 使用局部结构体类型
- struct Person pp;
- pp.age = 50;
- pp.name = "zbz";
-
- test();
- return 0;
- }
-
- void test() {
-
- //使用全局的结构体定义结构体变量p
- struct Person p = {10,"sb"};
- printf("%d,%s\n",p.age,p.name);
- }
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu[2];
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu[2] = {{"lnj", 35},{"zs", 18}};
-
- struct Student {
- char *name;
- int age;
- };
- struct Student stu[2];
- stu[0] = {"lnj", 35};
- stu[1] = {"zs", 18};
-
- // 定义一个结构体类型
- struct Student {
- char *name;
- int age;
- };
-
- // 定义一个结构体变量
- struct Student stu = {“lnj", 18};
-
- // 定义一个指向结构体的指针变量
- struct Student *p;
-
- // 指向结构体变量stu
- p = &stu;
-
- /*
- 这时候可以用3种方式访问结构体的成员
- */
- // 方式1:结构体变量名.成员名
- printf("name=%s, age = %d \n", stu.name, stu.age);
-
- // 方式2:(*指针变量名).成员名
- printf("name=%s, age = %d \n", (*p).name, (*p).age);
-
- // 方式3:指针变量名->成员名
- printf("name=%s, age = %d \n", p->name, p->age);
-
- return 0;
- }
-
- (pstu)两侧的括号不可少,因为成员符“.”的优先级高于“”。
- 如去掉括号写作pstu.num则等效于(pstu.num),这样,意义就完全不对了。
+多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的起始地址的值是 某个数k的倍数,这就是所谓的内存对齐,而这个k则被称为该数据类型的对齐模数(alignment modulus)。
- 这种强制的要求一来简化了处理器与内存之间传输系统的设计,二来可以提升读取数据的速度。比如这么一种处理器,它每次读写内存的时候都从某个8倍数的地址开始,一次读出或写入8个字节的数据,假如软件能 保证double类型的数据都从8倍数地址开始,那么读或写一个double类型数据就只需要一次内存操作。否则,我们就可能需要两次内存操作才能完成这个动作,因为数据或许恰好横跨在两个符合对齐要求的8字节 内存块上
- struct Person{
- int age; // 4
- char ch; // 1
- double score; // 8
- };
- struct Person p;
- printf("sizeof = %i\n", sizeof(p)); // 16
-
- struct Person{
- int age; // 4
- double score; // 8
- char ch; // 1
- };
- struct Person p;
- printf("sizeof = %i\n", sizeof(p)); // 24
-
- struct Date{
- int month;
- int day;
- int year;
- }
- struct stu{
- int num;
- char *name;
- char sex;
- struct Date birthday;
- Float score;
- }
-
- 注意:
- 结构体不可以嵌套自己变量,可以嵌套指向自己这种类型的指针
- struct Student {
- int age;
- struct Student stu;
- };
- struct Date {
- int year;
- int month;
- int day;
- };
-
- struct Student {
- char *name;
- struct Date birthday;
- };
-
- struct Student stu;
- stu.birthday.year = 1986;
- stu.birthday.month = 9;
- stu.birthday.day = 10;
-
- struct Person{
- char *name;
- int age;
- };
- struct Person p1 = {"lnj", 35};
- struct Person p2;
- p2 = p1;
- p2.name = "zs"; // 修改p2不会影响p1
- printf("p1.name = %s\n", p1.name); // lnj
- printf("p2.name = %s\n", p2.name); // zs
-
- #include <stdio.h>
-
- struct Person{
- char *name;
- int age;
- };
-
- void test(struct Person per);
-
- int main()
- {
- struct Person p1 = {"lnj", 35};
- printf("p1.name = %s\n", p1.name); // lnj
- test(p1);
- printf("p1.name = %s\n", p1.name); // lnj
- return 0;
- }
- void test(struct Person per){
- per.name = "zs";
- }
-
- union 共用体名{
- 数据类型 属性名称;
- 数据类型 属性名称;
- ... ....
- };
-
- union 共用体名 共用体变量名称;
-
- union Test{
- int age;
- char ch;
- };
- union Test t;
- printf("sizeof(p) = %i\n", sizeof(t));
-
- t.age = 33;
- printf("t.age = %i\n", t.age); // 33
- t.ch = 'a';
- printf("t.ch = %c\n", t.ch); // a
- printf("t.age = %i\n", t.age); // 97
-
- enum 枚举名 {
- 枚举元素1,
- 枚举元素2,
- ……
- };
-
- // 表示一年四季
- enum Season {
- Spring,
- Summer,
- Autumn,
- Winter
- };
-
- enum Season {
- Spring,
- Summer,
- Autumn,
- Winter
- };
- enum Season s;
-
- enum Season {
- Spring,
- Summer,
- Autumn,
- Winter
- } s;
-
- enum {
- Spring,
- Summer,
- Autumn,
- Winter
- } s;
-
- enum Season {
- Spring,
- Summer,
- Autumn,
- Winter
- } s;
- s = Spring; // 等价于 s = 0;
- s = 3; // 等价于 s = winter;
- printf("%d", s);
-
- enum Season {
- Spring,
- Summer,
- Autumn,
- Winter
- };
- // 也就是说spring的值为0,summer的值为1,autumn的值为2,winter的值为3
-
- enum Season {
- Spring = 9,
- Summer,
- Autumn,
- Winter
- };
- // 也就是说spring的值为9,summer的值为10,autumn的值为11,winter的值为12
-
- auto int num; // 等价于 int num;
-
- register int num;
-
- #include <stdio.h>
- void test();
- int main()
- {
- test();
- test();
- test();
-
- return 0;
- }
- void test(){
- static int num = 0; // 局部变量
- num++;
- // 如果不加static输出 1 1 1
- // 如果添加static输出 1 2 3
- printf("num = %i\n", num);
- }
-
- // A文件中的代码
- int num; // 和B文件中的num共享
- void test(){
- printf("ds.c中的 num = %i\n", num);
- }
-
- // B文件中的代码
- #include <stdio.h>
- #include "ds.h"
-
- int num; // 和A文件中的num共享
- int main()
- {
- num = 666;
- test(); // test中输出666
- return 0;
- }
-
- // A文件中的代码
- static int num; // 不和B文件中的num共享
- void test(){
- printf("ds.c中的 num = %i\n", num);
- }
-
- // B文件中的代码
- #include <stdio.h>
- #include "ds.h"
-
- int num; // 不和A文件中的num共享
- int main()
- {
- num = 666;
- test(); // test中输出0
- return 0;
- }
-
- #include <stdio.h>
-
- int main()
- {
- extern int num;
- num = 998; // 使用时并没有存储空间可用, 所以声明了也没用
- int num; // 这里才会开辟
- printf("num = %i\n", num);
- return 0;
- }
-
- #include <stdio.h>
-
- int main()
- {
- extern int num; // 声明我们有名称叫做num变量
- num = 998; // 使用时已经有对应的存储空间
- printf("num = %i\n", num);
- return 0;
- }
- int num; // 全局变量, 程序启动就会分配存储空间
-