目录
一,数组和指针的关系
1. 指针变量的大小是4/8个字节,专门用来存放地址的。数组就是数组,不是指针,数组一块连续的空间,可以存放1个或多个类型相同的数据。
2. 联系:
数组中,数组名是首元素的地址。数组名 == 地址 == 指针。当知道数组首元素地址时,因为数组是连续存放的,所以通过指针就可以遍历访问数组。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
for (i = 0; i < sz; i++)
{
printf("%p\n", arr[i]);
}
return 0;
}
可以看到数组的地址是连续的。
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
int sz = sizeof(arr) / sizeof(arr[0]);
int* p = arr;
for (i = 0; i < sz; i++)
{
printf("%p == %p\n",p+i, &arr[i]);
}
return 0;
}
二,二级指针
二级指针变量,用于存放一级指针变量的地址。
int main()
{
int a = 10;
int* pa = &a; //pa是一级指针变量。
int** pp = &pa; //pp就是二级指针变量,用来存放一级指针变量的地址。
return 0;
}
int main()
{
int a = 10;
int* pa = &a; //pa是一级指针变量。
int** pp = &pa; //pp就是二级指针变量,用来存放一级指针变量的地址。
*(*pp) = 100;
printf("%d", a);
return 0;
}
这样就把a的值改为100。
int main()
{
char arr1[] = "abc";
char arr2[] = "bcd";
char arr3[] = "e";
char* parr[] = { arr1,arr2,arr3 };
char** p = parr; //二级指针的运用
return 0;
}
三,指针数组
整形数组:存放整形的数组;
指针数组:存放指针的数组。
int main()
{
int arr1[] = { 1,2,3,4 };
int arr2[] = { 2,3,4,5 };
int arr3[] = { 3,4,5,6 };
int* parr[] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 4; j++)
{
printf("%d ", parr[i][j]);
}
printf("\n");
}
return 0;
}
四,结构体:
1. 含义:
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
数组:一组相同元素的集合。
结构体:一组不一定相同类型元素的集合。
2. 结构体的意义:
复杂对象不能通过内置类型直接描述和表示。就用结构体来描述。
//声明结构体类型
struct student
{
//成员变量,是用来描述结构体变量的相关属性的
char name[10];
int age;
char sex[5];
}s2,s3,s4; //这里的s1就是结构体变量,也可以不创建。它们是全局变量。
int main()
{
struct student s1; //局部变量s1
return 0;
}
3. 结构的成员
可以是标量、数组、指针,甚至是其他结构体。
struct S
{
double d;
};
struct A
{
int a;
char arr[5];
int* p;
struct S s;
};
4. 结构体变量的创建和初始化
struct S
{
double d;
int e;
}s1 = {3.14,3}; //第一种创建方式,且按顺序初始化
struct S s2 = { 2.22,4 }; //第二种创建方式,且按顺序
struct A
{
int a;
char arr[5];
int* p;
struct S s;
};
int main()
{
struct S s3 = {.d=5.22,.e=6}; //第三种创建方式,用点来初始化
printf("%.2f %d\n", s3.d, s3.e);
struct A a1 = { 2,"ab",NULL,{3.22,2} };
printf("%d %s %p %.2f %d\n", a1.a, a1.arr, a1.p, a1.s.d, a1.s.e);
return 0;
}
5.结构体传参
错误写法
struct S {
char name[20];
int age;
};
void set_stu(struct S t) //t是s的一份临时拷贝,改变t无法改变s
{
t.age = 20;
/*t.name = "jack";*/ //这种写法是错误的。
strcpy(t.name, "jack");
}
void print_stu(struct S t)
{
printf("%s %d\n", t.age, t.name);
}
int main()
{
struct S s = { 0 };
set_stu(s); //传值调用
print_stu(s);
return 0;
}
正确写法:
struct S {
char name[20];
int age;
};
void set_stu(struct S* p)
{
p->age = 18;
strcpy(p->name, "jack");
}
void print_stu(struct S t)
{
printf("%s %d\n", t.name, t.age);
}
int main()
{
struct S s = { 0 };
set_stu(&s);
print_stu(s);
return 0;
}
两种方法的对比,优选方案2。(传值和传地址)
struct s
{
int data[1000];
int num;
};
void print1(struct s s)
{
printf("%d\n", s.num);
}
void print2(struct s *s)
{
printf("%d\n", s->num);
}
int main()
{
struct s s1 = { {1,2,3,4},1000 };
print1(s1);
print2(&s1);
return 0;
}