指针
存储器中某条数据的地址(用于保存存储器地址的变量)
目的
避免副本
共享数据
存储器
计算机系统中的记忆设备,用来存放程序和数据
它分为(低位到高位):
代码块
一般会放置在存储器地址的低位。它是只读的,是存储器用来加载机器代码的部分
常量段
程序一开始运行时创建,但保存在只读存储器中。它是程序中用到的不变量
全局量
定义在函数之外,对所有函数可见。程序一开始运行就会创建全局量,可以修改他们
堆
用于动态存储:程序在运行时创建一些数据,然后使用很长一段时间
栈
存储器用来保存局部变量的部分。每当调用函数,函数的所有局部变量都在栈上创建。它之所有叫栈是 因为它看起来就像堆积而成的栈板:当进入函数时,变量会放到栈顶;当离开函数时,把变量从栈顶拿走。它从存储器的顶部开始,向下增长。
如何找出变量在存储器中的指针(使用&运算符)
#include <stdio.h>
int main()
{
int point = 4;
/*
%p用于打印指针
*/
printf("point的指针位置是:%p\n", &point);
return 0;
}
如何读取指针中的内容(使用*运算符)
#include <stdio.h>
int main()
{
int c = 10;
/*
获取变量c的指针地址 &运算符
注意需要用int *申明指针变量
*/
int *point = &c;
/*
获取指针地址对应的值 *运算符
*/
int val = *point;
printf("指针是%p\n", &c);
printf("指针对应的值是%d\n", val);
}
改变地址中的内容
#include <stdio.h>
int main()
{
int c = 10;
int *point = &c;
int val = *point;
*point = 99;
printf("改变后的c的值为%d", c);
}
数组和函数中的指针变量
#include <stdio.h>
void size(char str[])
{
printf("传入的字符串是%s\n", str);
/*
如果函数参数申明为数组类型,他会被当做指针处理,因此sizeof得到的值是8(64为系统,sizeof(* int))
*/
printf("字符串的长度是:%i\n", sizeof(str));
char str_size[] = "this is demo";
char * point = *str_size;
/*
sizeof直接传入数组依然计算的是数组的长度
*/
printf("数组变量的长度是:%i\n", sizeof(str_size));
printf("数组变量指针的长度是:%i\n", sizeof(point));
/*
数组变量可以用作指针
*/
printf("数组的变量的地址是:%s\n", &str_size);
/*
数组变量指向数组的第一个值
*/
printf("数组指针变量的地址是:%s\n", &point);
*point = "test";
/*
编译不能通过,数组变量不能指向其他地方
*/
printf("指针变量被赋值了吗?%s\n", point);
}
int main()
{
size("test");
}
为什么数组变量不能指向其他地方?
当创建指针变量时,计算机会分配4或8个字节的存储空间。如果创建的是数组,计算机会为数组分配存储空间,但不会为数组变量分配任何空间,编译器仅在出现它的地方把它替换成数组的起始地址
对于数组取值的两种方式
#include <stdio.h>
int main()
{
char str[] = "this is arr";
printf("看看结果%c\n", str[3]);
printf("另外一种方式看看结果%c\n", *(str+3));
int nums[] = {1,2,3};
printf("看看结果%i\n", nums[2]);
printf("另外一种方式看看结果%i\n", *(nums+2));
return 0;
}
1.arr[i]
2.*(arr+i)
指针为什么需要有类型?
#include <stdio.h>
int main()
{
int nums[] = {1,2,3};
/*
两个地址相隔四个字节(注意是16进制)
*/
printf("看看第一个元素的位置%p\n", nums);
printf("看看第二个元素的位置%p\n", nums+1);
return 0;
}
因为对于char指针加1,指针会指向存储器的下一个地址,因为char就占1字节
int通常占四个字节,如果int指针加1,编译后的代码就会对存储器加4
指针输入数据
scanf
fgets
scanf
#include <stdio.h>
int main()
{
/*
输入字符串
*/
char test[20];
scanf("%19s", test);
printf("输入的字符串为:%s\n", test);
/*
输入数字
*/
int t;
scanf("%i", &t);
printf("输入的数字是%i\n", t);
}
为什么数组传入变量名就可以,数字需要传'&'呢?
scanf和函数一样,传入数组的变量名会当做指针使用,它会根据指针去修改对应的值
为什么scanf的时候需要指定'%19s'?
如果不指定scanf读取的长度,当用户输入的值超过test数组的长度的时候会导致内存溢出。因此一般指定scanf的长度为test长度减1(去掉一个结束字符'\0')
fgets
#include <stdio.h>
int main()
{
char str[4];
/*
此处需要注意的是str是数组变量,所以传入的是str不是* str
*/
fgets(str, sizeof(str), stdin);
printf("输入的字符为%s\n", str);
}
scanf和fgets
1.scanf记得在格式串中加入限制长度,sacnf就能限制用户输入长度(没有强制要求),并且输入的字符长度需要减去结束符的长度,fgets强制限制用户输入字符数
2.scanf允许输入多个字段,而且能指定结构化数据根据什么字符划分。fgets只允许缓冲区输入一个字符串,而且只能是字符串,不能是其他数据类型
3.sanf不能输入空格,遇到空格就会停止读取。fget可以输入空格
字符串创建的过程
1.载入字符串字面值(也就是在常量(只读)中定义字面值)
2.在栈上新建一个数组,主要会分配数组的存储块大小
3.初始化数组,把字符串字面值复制到栈(可修改)上