指针 总结
// 指针的简单使用
void func1();
void func1()
{
// 指针的定义?
// 答:指针其实就是内存地址,指针变量
// 整形指针
int a = 100;
int *p1 = &a; // 定义整形指针,指向整形变量a
printf("a = %d\n", *p1);
// 浮点型指针
float b = 3.1415926;
float *p2 = &b; // 定义浮点型指针,指向浮点型变量b
printf("b = %.2f\n", *p2);
// 字符型指针
char c = 'a';
char *p3 = &c; // 字符串型指针,指向字符型变量'a'
printf("c = %c\n", *p3);
// 指针的简单使用
// 取址运算符:’&‘符号,表示取出一个变量的内存地址
// 例如:&a &b &c 返回值都是当前对象的内存首地址,然后赋值给指针
// 取值运算符:’*‘符号,表示根据一个内存地址取出当前内存中保存的值
// 例如: *a, *b, *c 返回值都是当前指针指向的内存地址所对应的值
// 需要注意的一点是:
// ’*‘的作用有两种:
// 1. 当’*‘号处在变量定义的语句中时,’*‘的作用就是告诉编译器,要声明一个指针变量
// 2. 当’*‘号放在正常使用的语句中时,’*‘的作用是根据当前的内存地址取出值
// 指针的运算
// 指针只可以进行加减运算,不可以进行其他的运算
// 当指针增加1个单位的时候,它实际上增加的字节数取决于字典
}
// 指针与数组
void func2();
void func2()
{
// 创建整形数组,装着每名学生的nianli
int stusAge[] = {19, 20, 35, 10, 87, 79};
// 数组名称其实就相当于一个指针,我们使用数组名和指针是一样的,但是需要注意,数组名称是常量,不可以修改
int *p = stusAge;
// 使用数组名取值
stusAge[1] = 20;
stusAge[3] = 40;
*stusAge = 30;
*(stusAge + 3) = 50;
// 使用指针取值
p[1] = 20;
p[3] = 35;
*(p) = 34;
*(p + 1) = 20;
// 数组名不可以修改,指针可以修改
// stusAge++; // 写法错误
p++; // 写法正确
// 指针与数组的区别:
// 1. 大小不同,指针的大小只取决于系统的位数,64位环境下指针大小为8个字节;而数组的大小取决于数组的类型和数组元素的个数
// 2. 数组名是常量地址,不可以重新指向,而指针可以发生改变,可以重指向
// 使用指针,可以计算出有结束标示的数组的长度,比如字符串,但是无法计算出普通数组的长度
}
// 指针与字符串
void func3();
void func3()
{
// 创建字符串
char *p1 = "iPhone"; // 指针指向的字符串,指向的是常量区,不可以修改,但是可以重新指向
char p2[] = "iPad"; // 字符数组的字符串,存放在栈区,可以修改
// p1[0] = 'I'; // 注意,指针指向的字符串不可以修改内容,但是写上是不会报错的,只要运行起来就立马报错。为了在编译期间就出现错误,防止出现这种协防,建议在使用指针字符串的时候,前面添加 ’const‘ 关键字进行修饰:’const‘表示这是一个常量不可以进行修改,
// 例如这种写法
const char *p3 = "iPhone";
// p3[1] = 'p'; // 编译期间就会报错
// 指针数组:存放指针的数组
char *strings[] = {"iPhone", "iPad", "iPod", "iMac"};
for (int i = 0; i < 4; i++) {
// printf("%s ", strings[i]); // 使用下标的方式访问
printf("%s ", *(strings + i));// 使用指针的方式访问
}
}
// 指针与函数
void test1(int a[], int count);
void test2(int *a, int count);
void func4();
void func4()
{
// 当指针作为参数的时候,形参拷贝的不是实参的值,而是实参的内存地址,拿到内存地址就可以修改实参的值了。可以实现函数内部修改外部变量的值
// 数组名作为参数其实就相当于指针作为参数,例如 test1() 和 test2() 函数是一样的
}
// 指针与结构体
typedef struct {
char name[20]; // 姓名
int age; // 年龄
float score; // 分数
} Student;
void func5();
void func5()
{
// 创建结构体变量
Student stu1 = {"lidaze", 18, 100.0f};
// 用指针指向结构体
Student *p = &stu1;
// 普通访问方式
printf("name = %s\n", stu1.name);
printf("age = %d\n", stu1.age);
printf("score = %.2f\n", stu1.score);
// 以指针的方式访问,使用指针访问结构体成员的时候,使用箭头的方式,更直观,更方便,尤其在结构体数组中
printf("name = %s\n", p->name);
printf("age = %d\n", p->age);
printf("score = %.2f\n", p->score);
// 创建结构体数组
Student stus[] = {
{"BlackCode", 18, 98.5},
{"RedCode", 19, 99.9},
{"WhiteCode", 22, 97.7}
};
// 使用指针指向结构体数组,指针里存放的地址就是结构体数组首元素的首地址
Student *p2 = stus; // 注意:数组名相当于数组首元素首地址,不需要使用 ’&‘ 符号,这种写法同下
Student *p3 = &stus[0]; // 和上面的写法是一样的
printf("p2 = %p p3 = %p\n", p2, p3);
for (int i = 0; i < sizeof(stus) / sizeof(Student); i++) {
// 打印结构体数组中每一个结构体的信息
// 使用下标的方式
// printf("name = %s age = %d score = %.2f\n", stus[i].name, stus[i].age, stus[i].score);
// 使用指针的方式
printf("name = %s age = %d score = %.2f\n", (p2 + i)->name, (p2 + i)->age, (p2 + i)->score);
}
}
int main(int argc, const char * argv[])
{
return 0;
}