新手理解c语言指针
void changeI(int i) {
i = 25;
printf("changeI:%d\n", i);
}
void changeI(int *p) {
*p += 2;
printf("changeI:%d\n", *p);
}
void changeP(int *p) {
p = NULL;
printf("changeP:%d\n", p);
}
int main()
{
int i = 21, j = i;
int *p1 = &i, *p2 = &i;
*p1 = 23;
printf("i:%d\n", i);
printf("j:%d\n", j);
printf("p1:%d\n", *p1);
printf("p2:%d\n", *p2);
changeI(i);
printf("i:%d\n", i);
changeI(&i);
printf("i:%d\n", i);
changeI(p1);
printf("i:%d\n", i);
changeP(p2);
printf("p2:%d\n", p2);
}
如上所示:
代码仅用于本示例,不纠文件结构,函数申明什么的。
从主函数从上往下输出:
前四个输出 :
- i = 21, j = i;是常见的赋值语句,即变量j的值现在为21。
- *p1 = &i, *p2 = &i;现在p1,p2均为i的地址。
- *p1 = 23;在主函数中很容易理解,将p指向的地址的值改为23,而p1本身的值没变,p2与p1的值相同,均指向变量i在内存中的地址,此地址的值现在被修改为23,即i的值现在为23。
- 前三条对应四个printf()。
- 第一个changeI中,我们传入的i,系统以值得方式传入,即传入的不是变量i,而是变量i的值,即传入了23;在函数内的i为函数局部变量,值为23,所以+=2得到25,随后输出25;
- 回到主函数,再次输出i,主函数中的i未发生变化。
- 第二个changeI,传入i的地址,此时传入的则对应主函数中的变量i,因此在函数内改变了主函数中的i,输出两次均为23+=2的结果;
- 随后changeI,传入p1的值,即传入了变量i的地址,同上,输出了两次27。
- changeP中,我们传入了p2的值,即i的地址,然后将此值赋值为NULL,注意:p2仅记录了i的地址, 其值得变化并不会导致i得地址发生变化,因此i与p1都为收到影像,且p2由于传值得原因,也为收到影响。最后两次输出的值分别为NULL与i得地址。
思考如何在函数中改变p2的值
我们应该将p2得地址传入函数。p2记录了i得地址,但其本身也是变量,也存在内存中,也有地址。
思考将int类型变成结构体
如果我们定义指针,而不定义变量,希望给指针所指区域赋值,则需要先申请空间。
typedef struct MyStruct
{
int ID;
char name[7];
int age;
} stu1;
void setValue(stu1 stu, int ID, char name[7], int age) {
stu.ID = ID;
for (int i = 0; i < 7; i++) {
stu.name[i] = name[i];
}
stu.age = age;
}
void setValue(stu1 *stu, int ID, char name[7], int age) {
(*stu).ID = ID;
for (int i = 0; i < 7; i++) {
(*stu).name[i] = name[i];
}
stu->age = age;
}
void printStu(stu1 stu) {
printf("ID:%d\t", stu.ID);
printf("name:%s\t", stu.name);
printf("age:%d\n", stu.age);
}
int main()
{
stu1 *st = (stu1*)malloc(sizeof(stu1));
stu1 stu;
char name[] = "张三";
stu.ID = 2000;
setValue(stu, 2000, name, 18);
printStu(stu);
char name1[] = "李四";
setValue(st, 2001, name1, 21);
printStu(*st);
char name2[] = "张三";
setValue(&stu, 2000, name2, 18);
printStu(stu);
printf("");
}
- 创建了一个结构体指针st,并申请了空间
- 创建了一个结构体变量stu
- 试图对stu调用赋值函数,注意本例通过参数不同,区分函数,如同int类型,我们传入stu被视为传入结构体的值,无法修改结构体本身,因此输出函数乱码,如果不加stu.ID赋值,则系统报错未初始化。
- 传入结构体指针变量,成功修改所指向的值,其中(*stu)表示指针指向的结构体,stu->可以找的结构体中的变量。
- 传入stu的地址,结果同上。
指针使用只需要注意以下几点:
- 定义变量时(包括函数的参数定义):"*"表示定义指针类型变量,如int *i;
- 代码执行过程中:变量名表示指针如i;"* 变量名"表示指针指向的类容如* i;"&"表示取地址,如&(*i)同i。int j=0;&j 则是j的地址,**&i则是int指针类型变量i的地址(指针变量的地址/地址的地址)**在函数中想要修改指针变量,也需要传其地址。