如果完成某项任务需要10个步骤、20个数据,如何实现整个流程的自动化?
如果指令和数据是一步步输入的,整个过程就离不开人工操作。 如果将这10个步骤编辑成指令,指令和数据按照一定的编码规则存储,一个组件一步步接受指令,将其解释为电信号,然后另一个组件执行,中间结果也可以被存储。 通过重复这个过程,就可以实现自动化。
这就是冯·诺依曼的存储程序控制概念。 这样的计算机称为冯诺依曼机,它是当今大多数计算的理论模型。
存储指令和数据的部分称为存储器,可以通过地址随机访问,属于线性结构。 无论是电存储(存储电路或电容器)还是磁存储,都是用两种状态的二进制来表示的。 存储器属于采用电容器的电存储,8位构成一个字节,每个字节都是线性寻址的。
“要存储和检索”的数据的价值必须与其地址密不可分。 虽然可以使用的地址之间存在线性关系,但是显示和使用地址访问数据还是很不方便,所以高级语言使用标识符的概念来理解,隐含了内存单元的地址通过变量名来表示,通过变量名直接获取数据值。 即便如此,变量名称作为左值和右值仍然略有变化。 右值只是指内存单元中01字符串表示的数据值,而右值是可寻址的非只读表达式,可以修改一个对象,当重新出现在表达式的右侧时,仍然代表一个数据值。
我们知道,在内存中,如果我们知道一块内存的首地址及其编码规则,我们就可以根据变量类型的长度对其进行解码,并访问其中对应的相邻单元的值转动。 对于数组、结构体和类也是如此。 为了利用地址的这种线性关系,变量名称更有可能直接获取数据值。 如果用下面的运算符来操作,比较麻烦,而且无法通过地址访问相邻单元的值:
int n=22; int m=33; *&n*=2; *(&n+sizeof(int))*=2; cout<如何显式获取其地址并隐式获取其数据值? 这就是指针变量,指针就是地址,指针变量就是用来存储内存单元地址的变量。
指针变量作为左值,意味着修改一个地址,指向一个新的内存单元,也可以理解为指针的移动。 理解指针的关键是要明白指针作为左值时被修改,得到一个新的地址值,这就形成了指针的移动。
1 数组中指针的移动
int arr[]={1,2,3,4,5}; for(int i=0;i<5;++i) cout<<" "<数组名就是基地址,下标相当于基地址的偏移量,得到不同的变量地址。
比如指针在字符数组中的移动:
char dst[] = "abcdef"; char* src = "ghi"; char* ch=dst; while(*ch++=*src++); cout<2 链表中指针的移动
与数组元素可以随机访问(下标可以进行算术运算)不同,链表节点只能顺序访问(相邻节点一一访问),这是通过指针移动来实现的。
理解链表的关键是要明白节点的链接、剪切、指针移动都是通过指针(节点的指针域)的赋值来实现的。 指针赋值表达式的左值可以理解为左值的重新指向。 换句话说,左值和右值完成相同的指向。
插入节点的方法如下:
删除节点的方法如下:
链表节点遍历:
链表中常见的指针操作:
(指针为左值时的赋值符号可以理解为左值指针)
3 STL中的迭代器也是一种特殊的指针容器
int arr[] = {10,20,30,40,50}; vectorvec(arr,arr+5); vector ::iterator it; for (it = vec.begin(); it!=vec.end(); ++it) cout << ' ' << *it; //10 20 30 40 50 4 文件指针的移动
FILE *stream; stream = fopen("MYFILE.TXT", "a+"); fprintf(stream, "This is a test");//读写文件时,编译器隐式实现了文件指针的移动 printf("The file pointer is at byte \ %ld\n", ftell(stream));//ftell()可以返回文件指针的位置 fseek(stream,3,SEEK_SET); //fseek()可以让程序员设置文件指针的位置 char ch = fgetc(stream);//返回文件中的第4个字符,s printf("%c",ch); fclose(stream);-结尾-