跟着顶尖程序员4小时彻底掌握C指针
前言
印度顶尖程序员Harsha Suryanarayana深入浅出讲解C指针
我在b站上,看印度程序员小哥讲c指针的学习笔记。
Introduction to pointers in C 指针的基本介绍
代码如下(示例):
//Pointers ---- variables that store address of another variable 指针----是一个变量,它存放着另一个变量的地址
//设变量a的address在204 指针变量p的address在64 如上图
int a;
int *p;//定义了一个 指向a地址的 指针变量
p = &a;//&是取地址符,这个表达式的意思是 把a的address赋给p;
a = 5;
printf p;//得到的是a的地址204
printf ("%d\n",&a);//204 注意输出格式
printf &p;//输出的是指针变量p的address
printf *p;//5 p->address *p->valus at address
//图二
*p = 8;//赋值
printf a;//8
下面是图二
Working with pointers 指针代码示例
int a;// integer 声明变量时:变量数据类型 变量名
int *p;// point to integer 声明指针变量:变量数据类型 *变量名
//其他类型也相似
char c;//character
char *p0;//pointer to character
double d;//double
dpuble *p1;//pointer to double
p = &a;//取地址操作 上面只是定义指针,还没有赋值
下面是能正常运行的代码:
#include<stdio.h>
int main()
{
int a;
int *p;
a = 10;
p = &a;//&a = address of a
printf("%d\n",p);//在a没有初始化时,p也就是a的地址是随机的 ,每次分配内存不同
printf("%d\n",*p);//*p- p指向地址的值
printf("%d\n",&a);
}
利用指针修改变量的值
#include<stdio.h>
int main(){
int a;
int *p;
a = 10;
p = &a;//address of a
printf("*p = %d\n",*p);
printf("a = %d\n",a);
printf("a 的地址 %d\n",p);
printf("\n");
printf("\n");
*p = 15;//利用指针p修改变量a的值
printf("利用指针p修改变量a的值\n");
printf("a = %d\n",*p);//15
printf("a = %d\n",a);
}
int b = 20;
*p = b;//Will the address in p change to point b??
#include<stdio.h>
int main(){
int a = 10;
int *p;
p = &a;
printf("Address of P is %d\n",p);//p指向的变量地址是
printf("Value of p is %d\n",*p);//p指向的变量值是
int b = 20;
*p = b;//Will the address in p change to point b??
printf("Address of P is = %d\n",p);//p still point to a;
printf("Value of p is = %d\n",a);//但是改变了a的值a=20
}
定义、初始化 - 简写
int a;
a = 10;
//等同于
int a = 10;
//指针同理
int *p;//指针第一种方式较为常用
p = &a;
//等同于
int *p = &a;
Pointer arithmetic//指针算数运算
#include<stdio.h>
int main(){
int a =10;
int *p;
p = &a;
//Pointer arithmetic
printf("Address p is = %d\n",p);//p指向的地址是
printf("value at address p is %d\n",*p);//10
printf("\n");
printf("size of integer is %d btyes\n",sizeof(int));//这个打印语句会告诉我们整型的大小
printf("\n");
printf("Address (p+1) is = %d\n",p+1);//p+1会得到下一个整型数据的地址,一个整型的大小是4个字节。
//也就是说,如果p = 2000,那么(p+1) = 2004;
printf("value at address (p+1) is %d\n",*(p+1));//一个我们所不知道的随机值,也就是垃圾值。因为我们实际上并没有为这个特定的内存地址分配一个整型变量。这是使用指针算数运算的时候一个危险的地方
printf("value at address p+1 is = %d\n",*p+1);
printf("\n");
printf("Address p+2 is = %d\n",p+2);
}
你可以试着改成用char指针、float指针、double指针或者指向其他类型的指针
Pointers types,void pointer ,pointer arithmetic 指针的类型,算数运算,void指针
指针是强类型的,你需要一个特定类型的指针变量来存放特定类型变量的地址( int型变量就要int指针,char变量就要char指针)。
Why strong types?
Why not some generic type?//为什么指针不是通用的类型呢
我们不仅仅使用指针来存储内存地址,同时也用它来解引那些地址的内容。(//*p = &a:)这样我们就可以访问和修改这些地址对应的值了。
int-4 byte;
char- 1 byte;
float- 4 byte;
//如上图是一个int型的数,假设4个字节从右往左分别是200,201,202,203
并且根据二进制转是十进制,是1025
int a = 1025;
int *p;
p = &a;
printf p; //此时输出的是地址应该是 200;
地址是起始地址!!!如果我们想知道那个地址的值(内容),就用*p去解引用这个地址。
如果p是一个字符类型的指针,那么在解引用的时候机器只会看1个字节。
让我们写一些程序看会发生什么。
#include<stdio.h>
int main(){
int a =1025;
int *p;
p = &a;
printf("size of integer is %d bytes\n",sizeof(int));
printf("Address of p = %d,Value of p = %d\n",p,*p);
char *p0;
p0 = (char*)p;//typecasting 强制类型转换
printf("size of char is %d bytes\n",sizeof(char));
printf("Address of p0 = %d,Value of p0 = %d\n",p0,*p0);
//1025 = 00000000 00000000 00000100 00000001
//当我们强制转换为char时,最右边的这个字节的地址会被存入'p0',
//(这里要注意大小端……我还不知道大小端是什么……可能就是从左往右的顺序。)
//当机器解引p0时,会认为它是一个指向字符型的指针,字符型只有1个字节所以机器只看一个字节,即00000001 = 1
//我们再来看看p+1 和p0+1
printf("Address of p+1 = %d,Value of p+1 = %d\n",(p+1),*(p+1));//按理说因为没有指定p+1的值
//所以*(p+1)会出现一个随机值(垃圾值),但是我不知道为什么我的跑出来是p指向的地址,每次运行都是
printf("Address of p0+1 = %d,Value of p+1 = %d\n",(p0+1),*(p0+1));
//00000000 00000000 00000100 00000001 ,p0+1会向左移动,即00000100 = 4;
}
以上我们讲解的时 解引用一个指针变量的时候内存中将会发生什么,以及对指针进行特定类型的算数操作(事实上,唯一的指针运算就是以整数值大小增加减少 来改变指针值)会发生什么。
void 类型指针//通用类型指针
不针对某个特定的数据类型
#include<stdio.h>
int main(){
int a = 1025;
int *p;
p = &a;
printf("size of integer is %d bytes\n",sizeof(int));
printf("Address of p = %d,Value of p = %d\n",p,*p);
//Void pointer - Genric pointer
void *p0;
p0 = p;//这是合法的,不会有任何编译错误。
printf("Address of p0 is %d\n",p0);//但是不能 value = %d,*p0;我们会得到一个编译错误(我也不知道为什么这里不是随机值)
//printf("Address of (p+1) is %d\n",(p0+1));
//这个也会出现编译错误。因为void没有规定的字节数,所以不知道加多少
}