内存,计算机中的内存,通常说的是虚拟内存, 它是所有硬件内存条在操作系统,并且是运行起来的OS中的一个地址映射 比如,电脑中插入4个16G的内存条,那么电脑的内存为64G 这个64G就是从0开始,然后1,2,3,...,直到64G-1 可以将之看作一个刻度尺,0代表第1格,1代表第2格,64G-1代表最后一格 所有的进程使用的都这一个虚拟内存,毕竟整个电脑 也就这64G内存 0,1,2,3,...虚拟内存对应的数字标记,就是内存地址,也叫指针 地址3,就是虚拟内存的第4个格, 每个格是一个字节,一个Byte,代表了8位,就是8bit, 一个bit可以是0或1, 8bit表示一个字节是这样的:00000010,这个数表示2,是2进制 指针就是地址,就是一个数字,这个数字对应着虚拟内存上的一个字节位置
数字变量
int a =1; 这是一个整数变量,也是一个变量,也就是说它不是常量,即a的值可以变化,比如 a =2; a这个字符标记,对应着虚拟内存上的一个地址,就是一个数字, &a可以取变量a的地址
C语言中进制前缀
二进制 前缀 0b 示例 0b100 十进制 4 八进制 前缀 0 示例 0100 十进制 64 十进制 无前缀 示例 100 十进制 100 十六进制 前缀 0x 示例 0x100 十进制 256
#include <stdio.h>
int main(){
int a=1;
printf("%p\n",&a);//0x7ffcf4fb0a7c
a=2;
printf("%p\n",&a);//0x7ffcf4fb0a7c
return 0;
}
变量a从1到2的过程中,其地址是不变的, 就是将虚拟内存中地址为0x7ffcf4fb0a7c为开头及之后的三个格子,一个共四个格子,存储的数字从1变更为2 一个地址只能表示一个格子,但整数int在计算机中占用4个字节,变量a的数据类型为int,就表示它要用四个格式 但&变量返回的地址,只有一个数字,是一个地址, 将前后连续的四个格子看作一个数据单元这个操作由C语言自动完成
变量a
操作一个变量,比如输出,是则是输出 变量a的值
&a 每个变量在栈上,也只能是在栈上,分配有一个地址,&a指取变量a在栈上的地址
*(&a) 即*号可以从一个地址中取出该地址对应的值
指针与指针变量
指针就是地址 指针变量就是存放指针的,即存放地址的 任何一个变量都对应着一个地址/指针,比如int a=1; 符号a就对应着一个地址,&a表示其符号a的地址, a=1;表示将1这个数字赋值到符号a对应的地址上 指针变量也对应着一个地址,该地址中存放的是地址/指针
#include <stdio.h>
int main(){
int a=1;
int* b=&a;
printf("%p\n",b); //0x7ffcb9d9cc8c
printf("%p\n",&b);//0x7ffcb9d9cc80
return 0;
}
符号b是一个指针变量,它的值是一个地址/指针, 符号b本身也有一个地址0x7ffcb9d9cc80,并且是整数
数据类型**:双星,指向指针的指针
终于来到了高能时刻...
int a=1;
int* b=&a;
b是一个指针变量,其值是指针,通常提到一个变量其实意在指这个变量的值,
比如这里,b 指 变量a的地址
b本身也是有地址的,&b是取变量b的地址,这是一个值,也可以用一个变量来存储,这就是指向指针的指针
#include <stdio.h>
int main(){
int a=1;
int* b=&a;
int** c = &b;
printf("%p\n",b); //0x7ffec0cc0504
printf("%p\n",&b);//0x7ffec0cc04f8
printf("%p\n",c); //0x7ffec0cc04f8
*(*c) =2;
printf("a=%d\n",a); //a=2
return 0;
}
对于整数来说,很少这么操作,请看下面的字符串:
C语言经典字符串传参
#include <stdio.h>
void change(char** tmp){
*tmp = "abc";
}
int main(){
char* a;
change(&a);
printf("-%s-\n",a);//-abc-
return 0;
}
change函数传递的是指针变量a的地址,即&a
进入函数再使用*,即*(&a),相当于直接修改了变量a
*(&a) = "abc";
相当于
a = "abc";
a = "abc";对应的操作是,向符号a对应的地址存入"abc"的首地址
("abc"返回的是字符串的首地址,因为变量a是指针变量,其值是要放指针的),
函数中的一系列操作,建立在对地址的操作上,而一个计算机的虚拟内存只有一个
所以从函数中出来后,变量a的值也随之改变
这里change函数传参这个过程本身是值的复制, &a是一个数,将这个数复制给另外一个变量,再取这个变量的值进程操作 只是先向上追溯一个向量的地址,将地址传进去后,再取其值,就回到该变量本身了 这样就做到了,在函数中,直接操作外部向量 这里说的参数值复制,意思是说*tmp与a的值是一样的, 即指向的地址相同,但它们不是一个符号,只是彼此等价, 说到底,函数并没有将变量a真的传递进函数,传递的只有地址... 符号什么的,只是一个表示,人看着方便就行... 你要是乐意,你可以将无数个符号指向同一个地址
这个过程并不复杂,只是字符变量本身多了一个指针,在形式上看着复杂了,其实这个过程就两步:
1. 向函数上传入一个变量的地址,&变量
2. 在函数中取出这个变量,*变量
这样就做到在函数中直接操作外部变量了
#include <stdio.h>
void ch(int* i){
*i = 2;
}
int main(){
int i=1;
ch(&i);
printf("i=%d\n",i);//i=2
return 0;
}
字符指针指向一个字符串的首地址 "abc"的特殊在于,它本身多占一个字符'\0' 输出字符串时,从其首地址开始,遇'\0'字符结束,这个过程是自动的 为什么会这样,为什么要这样? 因为整数有固定长度,比如int占四个字节, int*指针指向第一个字节的地址,自动向后移动三次,凑够四个字节,就凑齐了所需要的字节了 而字符串中的字符数字是不固定的,一个字符串与另外一个字符串的长度是否相等不确定, 它可以很短,也可以很长... 所以,就使用'\0'这个字符来统一表示字符串的结尾,遇到这个就表示结束了