メモリの概要
メモリ
メモリの意味:
- メモリ:コンピュータの組成、プログラムやデータ、補助演算処理のCPUの重要な部分を格納します。
- メモリ:内蔵メモリ、一時的なプログラム/データ - ブラウンは、SRAM、DRAM、DDR、DDR2、DDR3を失いました。
- 外部メモリ:外部メモリ、長期プログラム/データ - ない損失ROM、ERRROM、FLASH(NAND、NOR)、ハードディスク。
CPUやハードディスク、メモリ、通信ブリッジであります:
- 一時的にCPUでの動作データを格納します
- 交換データへの一時的な外部メモリやハードディスク
メモリアドレス空間と物理メモリ
メモリアドレス空間と物理メモリ:メモリの二つの概念。
物理メモリ:特定のメモリチップの実際の存在。
- 取締役会は、補間メモリトップス
- RAMチップは、ディスプレイカード上に表示しました
- チップRAMおよびROMチップの各種アダプタ
メモリアドレス空間:メモリのエンコーディングの範囲。私たちは、メモリが意味のこの層を意味するソフトウェアで言うために使用されます。
- コード:各物理記憶装置(1バイト)に番号を割り当てます
- アドレッシング:書き込みデータを読み取るために割り当てられた番号に応じて、各ストレージ装置に見出すことができ、
メモリアドレス
- メモリは、文字の大きな一次元アレイに抽象化。
- メモリの各バイトは、(32ビットまたは64ビットのプロセッサに関連付けられている)32ビットまたは64ビットの番号が割り当てられるコードします。
- メモリの数は、我々はメモリアドレスを呼び出します。
各データは、メモリ内の対応するアドレスが割り当てられます。
- 文字:アドレス割り当て1つのバイト
- INT:4を割り当てられ、4バイトのアドレスを占めます
- フロート、構造体、機能、アレイ、等
ポインタの基礎
ポインタとポインタ変数
- 各バイトのメモリ領域がある数、持っている「アドレスを。」
- 変数は、プログラムで定義されている場合、プログラムは、コンパイルまたは実行されたとき、システムは変数にメモリを割り当てるであろう、それはメモリアドレス(番号)を決定します
- ポインタはメモリの本質である「アドレス」。ポインタはアドレスで、アドレスがポインタです。
- ポインタ変数がアドレスを格納する変数で、メモリセルポインタの数です。
- 通常、我々は、ポインタ、彼らは同じではありません実際の意味と呼ばれるポインタ変数を物語るます。
ポインタ変数の定義と使用
- データ型は、ポインタ変数は、変数のポインタであります
- ポインタ変数に割り当てられたアドレスを入れへのポインタ変数ポイント、
- 「*」オペレータの操作変数は、メモリ空間へのポインタがポイントです
#include <stdio.h>
int main()
{
int a = 0;
char b = 100;
printf("%p, %p\n", &a, &b); //打印a, b的地址
//int *代表是一种数据类型,int*指针类型,p才是变量名
//定义了一个指针类型的变量,可以指向一个int类型变量的地址
int *p;
p = &a;//将a的地址赋值给变量p,p也是一个变量,值是一个内存地址编号
printf("%d\n", *p);//p指向了a的地址,*p就是a的值
char *p1 = &b;
printf("%c\n", *p1);//*p1指向了b的地址,*p1就是b的值
return 0;
}
注意:&
可以取得一个变量在内存中的地址。但是,不能取寄存器变量,因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的。
通过指针间接修改变量的值
int a = 0;
int b = 11;
int *p = &a;
*p = 100;
printf("a = %d, *p = %d\n", a, *p);
p = &b;
*p = 22;
printf("b = %d, *p = %d\n", b, *p);
指针大小
- 使用sizeof()测量指针的大小,得到的总是:4或8
- sizeof()测的是指针变量指向存储地址的大小
- 在32位平台,所有的指针(地址)都是32位(4字节)
- 在64位平台,所有的指针(地址)都是64位(8字节)
int *p1;
int **p2;
char *p3;
char **p4;
printf("sizeof(p1) = %d\n", sizeof(p1));
printf("sizeof(p2) = %d\n", sizeof(p2));
printf("sizeof(p3) = %d\n", sizeof(p3));
printf("sizeof(p4) = %d\n", sizeof(p4));
printf("sizeof(double *) = %d\n", sizeof(double *));
野指针和空指针
指针变量也是变量,是变量就可以任意赋值,不要越界即可(32位为4字节,64位为8字节),但是,任意数值赋值给指针变量没有意义,因为这样的指针就成了野指针,此指针指向的区域是未知(操作系统不允许操作此指针指向的内存区域)。所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题
int a = 100;
int *p;
p = a; //把a的值赋值给指针变量p,p为野指针, ok,不会有问题,但没有意义
p = 0x12345678; //给指针变量p赋值,p为野指针, ok,不会有问题,但没有意义
*p = 1000; //操作野指针指向未知区域,内存出问题,err
但是,野指针和有效指针变量保存的都是数值,为了标志此指针变量没有指向任何变量(空闲可用),C语言中,可以把NULL赋值给此指针,这样就标志此指针为空指针,没有任何指针。
int *p = NULL;
NULL是一个值为0的宏常量: #define NULL ((void *)0)
万能指针 void *
void *
指针可以指向任意变量的内存空间:
void *p = NULL;
int a = 10;
p = (void *)&a; //指向变量时,最好转换为void *
//使用指针变量指向的内存时,转换为int *
*( (int *)p ) = 11;
printf("a = %d\n", a);
const修饰的指针变量
int a = 100;
int b = 200;
//指向常量的指针
//修饰*,指针指向内存区域不能修改,指针指向可以变
const int *p1 = &a; //等价于int const *p1 = &a;
//*p1 = 111; //err
p1 = &b; //ok
//指针常量
//修饰p1,指针指向不能变,指针指向的内存可以修改
int * const p2 = &a;
//p2 = &b; //err
*p2 = 222; //ok
指针和数组
数组名
数组名字是数组的首元素地址,但它是一个常量,且不能修改
指针的加减运算
指针的加减并不是存储的值的加减,而是代表着指针的移位,移位的大小由指针的类型决定
p + i
相当于&p[i]
*(p + i)
相当于p[i]
int a[5] = {1,2,3,4,5};
int *p = a; // p这里就是数组第一个元素的地址
// *p 取出第一个元素的值
// p+1 指向数组的第二个元素
// *(p+1) 取出数组第二个元素的值
// 总结:*(p+i) 相当于 p[i]
指针数组
指针数组,它是数组,数组的每个元素都是指针类型,仅此而已
多级指针
指针也是一个变量,也有地址,也可以通过另一个指针存储这个地址
存储指针的地址的指针就叫做多级指针
指针与函数
函数名是一个地址,所以指针也可以指向函数名
指针可以用来给函数传参:这样在函数中就可以通过形参修改外部的数据
指针可以作为函数的返回值:返回一个地址
指针和字符串
字符串常量,例如:"Hello"
直接用 %d
或者 %p
打印出来发现是一个数字,因为字符串常量也保存在某个内存块中,也有一个地址
可以用字符指针来指向字符串,因为字符串的地址也是字符串中第一个字符的地址