C/C++学习之C提高----C程序数组排序、数据类型(大小,别名,封装)、变量、程序的内存四区模型(栈,堆,全局,代码区)
2017-10-29 13:41
1031 查看
1.BS模型和CS模型
2.第一个C程序之数组排序
#include<stdlib.h> #include<string.h> //排序 void main() { int i = 0,j = 0; int tmp = 0; int a[] = { 33, 55, 22, 66, 44, 99, 11 }; printf("排序前\n"); for (i = 0; i < 7; i++){ printf("%d", a[i]); } //排序 //外层循环 当i=0的时候,让j从1到n进行变化 //外层循环 当i=1的时候,让j从2到n进行变化 //外层循环 当i=2的时候,让j从3到n进行变化 //外层循环 当i=3的时候,让j从4到n进行变化... //结论:按照一个i变量不变,让另外一个变量j进行变化;下一轮,依次进行 for (i = 0; i< 7; i++){ for (j = i+1; j < 7; j++){ if (a[i]>a[j]){//如果a[i]>a[j],则交换 tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } printf("排序后\n"); for (i = 0; i < 7; i++){ printf("%d", a[i]); } printf("hello...\n"); system("pause"); }
代码优化
#include<stdlib.h> #include<string.h> //void printArray(int a[],int num) void printArray(int *a,int num) { int i = 0; for (i = 0; i < num; i++){ printf("%d", a[i]); } } //void sortArray(int a[],int num) void sortArray(int *a,int num) { //排序 int i, j, tmp; for (i = 0; i< num; i++){ for (j = i + 1; j < num; j++){ if (a[i]>a[j]){//如果a[i]>a[j],则交换 tmp = a[i]; a[i] = a[j]; a[j] = tmp; } } } } //数组做函数参数的退回问题 退回为一个指针 //结论:把数组的内存地址和数组的有效长度传给被调用函数 //排序 void main() { int i = 0, j = 0; int tmp = 0; int num = 0; int a[] = { 33, 55, 22, 66, 44, 99, 11 }; num = sizeof(a) / sizeof(a[0]); printf("num:%d", num); printf("排序前\n"); printArray(a,num); //排序 sortArray(a, num); printf("排序后\n"); printArray(a, num); printf("hello...\n"); system("pause"); }
结论
数组做函数参数的退回问题 退回为一个指针1.把数组的内存地址和数组的有效长度传给被调用函数
2.实参的a和形参的a的数据类型本质不一样
3.形参中的数组,编译器会把它当成指针处理 这是c语言特色
4.形参写在函数上,和写在函数内是一样的,只不过是具有对外的属性而已。
运行结果
3.数据类型本质分析
(1)数据类型概念
“类型”是对数据的抽象类型相同的数据有相同的表示形式、存储格式以及相关的操作
程序中使用的所有数据都必定属于某一种数据类型
(2)求数据类型大小
#include "stdlib.h" #include "stdio.h" #include "string.h" void main() { int a; //告诉c编译器分配4个字节的内存 int b[10] ; //告诉c编译器分配40个自己内存 printf("b:%d, b+1:%d, &b:%d, &b+1:%d \n", b, b+1, &b, &b+1); printf("sizeof(b):%d \n", sizeof(b)); //40 printf("sizeof(a):%d \n ", sizeof(a)); //4 //sizeof是操作符,不是函数;sizeof测量的实体大小为编译期间就已确定 // b+1 &b+1 结果不一样 //b &b所代表的数据类型不一样 //b 代表的数组首元素的地址 //&b代表的是整个数组的地址 printf("hello....\n"); system("pause"); }
(2)数据类型别名
#include "stdlib.h" #include "stdio.h" #include "string.h" //复杂类型别名 struct Teacher { char name[64]; int age; }Teacher; typedef struct Teacher2 { char name[64]; int age; }Teacher2; //简单类型别名 typedef typedef int u32; void main() { int a; //告诉c编译器分配4个字节的内存 int b[10] ; //告诉c编译器分配40个自己内存 struct Teacher t1;//前要加struct Teacher2 t2; //不需要加struct t1.age = 31; printf("u32:%d \n", sizeof(u32)); printf("hello....\n"); system("pause"); }
(3)数据类型的封装
{ char *p2 = NULL; void *p1 = NULL; p2 = (char *)malloc(100); p1 = &p2; } { //void a;//编译器不知道如何分配内存 }
4.变量的本质
(1)变量的概念
概念:既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量。变量定义形式: 类型 标识符, 标识符, … , 标识符 ;
例如:
int x ;
int wordCut , Radius , Height ;
double FlightTime , Mileage , Speed ;
(2)变量的本质
1、程序通过变量来申请和命名内存空间 int a = 02、通过变量名访问内存空间
(一段连续)内存空间的别名(是一个门牌号)
3、修改变量有几种方法?
1) 直接
2) 间接。内存有地址编号,拿到地址编号也可以修改内存;于是横空出世了!(编程案例)
3) 内存空间可以再取给别名吗?
4) 数据类型和变量的关系
通过数据类型定义变量
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> void main() { int a ; int b; a = 10; //1 直接赋值 //cpu里面执行 printf("&a: %d\n", &a); //2间接赋值 直接通过内存 *((int*)&a) = 200; printf("a: %d\n", a); printf("hello...\n"); system("pause"); return ; }
5.程序的内存四区模型
(1)内存四区的建立流程
流程说明
1、操作系统把物理硬盘代码load到内存
2、操作系统把c代码分成四个区
3、操作系统找到main函数入口执行
4000
(2)静态存储区案例理解
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> char * getStr1() { char *p1 = "abcdefg"; //char *p1 = "abcdefg2"; return p1; } char *getStr2() { char *p2 = "abcdefg2"; return p2; } void main() { char *p1 = NULL; char *p2 = NULL; p1 = getStr1(); p2 = getStr2(); //打印p1 p2 所指向内存空间的数据 printf("p1:%s , p2:%s \n", p1, p2); //打印p1 p2 的值 printf("p1:%d , p2:%d \n", p1, p2); printf("hello...\n"); system("pause"); return ; }
把char *p1 = “abcdefg”;改为char *p1 = “abcdefg2”;发现指针所指地址一样。
静态存储器内存四区图
(3)堆栈案例理解
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> //堆 char *getMem(int num) { char *p1 = NULL; p1 = (char *)malloc(sizeof(char) * num); if (p1 == NULL) { return NULL; } return p1; } //栈 //注意 return不是把内存块 64个字节,给return出来,而是把内存块的首地址(内存的标号0xaa11) ,返回给 tmp // 理解指针的关键,是内存. 没有内存哪里的指针 // char *getMem2() { char buf[64]; //临时变量 栈区存放 strcpy(buf, "123456789"); //printf("buf:%s\n", buf); return buf; } void main() { char *tmp = NULL; tmp = getMem(10); if (tmp == NULL) { return ; } strcpy(tmp, "111222"); //向tmp做指向的内存空间中copy数据 //tmp = getMem2(); tmp = 0xaa11; printf("hello..tmp:%s.\n", tmp); system("pause"); return ; }
堆栈图解
(4)指针
指针是一种数据类型
1) 指针也是一种变量,占有内存空间,用来保存内存地址2)*p操作内存
在指针声明时,*号表示所声明的变量为指针
在指针使用时,*号表示 操作 指针所指向的内存空间中的值
*p相当于通过地址(p变量的值)找到一块内存;然后操作内存
*p放在等号的左边赋值(给内存赋值)
*p放在等号的右边取值(从内存获取值)
3)指针变量和它指向的内存块是两个不同的概念
//含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
//含义2 给*p赋值*p=’a’; 不会改变指针变量的值,只会改变所指的内存块的值
//含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
//含义4 =左边char *p
//含义5 保证所指的内存块能修改
4)指针是一种数据类型,是指它指向的内存空间的数据类型
含义1:指针步长(p++),根据所致内存空间的数据类型来确定
p++=->(unsigned char )p+sizeof(a);
结论:指针的步长,根据所指内存空间类型来定。
注意:
不断的给指针变量赋值,就是不断的改变指针变量(和所指向内存空间没有任何关系)。
测试
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> void main() { int a = 10; char *p1 = 100; //分配4个字节的内存 char ****p2 = 100; int *p3 = NULL; p3 = &a; *p3 = 20; //间接的修改a的值 //*就像一把钥匙 通过一个地址(&a),去修改a变量的标示的内存空间 { int c = 0; c = *p3; //c=20 //*p放在=号左边 写内存 //*p放=号的右边 读内存 printf("c:%d \n", c); } { char *p4 = NULL; p4 = (char *)malloc(100); p4 = (char *)malloc(200); //0xcc11 } printf("a:%d , p1:%d , p2: %d", sizeof(a), sizeof(p1), sizeof(p2)); printf("hello...\n"); system("pause"); return ; }
运行结果
保证所指的内存块能修改
#define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> char *getStr() { char *tmp = NULL; tmp = "abcdefgf"; return tmp; } void main() { char *p = getStr(); printf("p:%s \n", p); *(p+2) = 'r'; //经常出现的错误 保证指针所指向的内存空间 可以被修改 system("pause"); return ; }
运行结果
图解
相关文章推荐
- C\C++ 程序员从零开始学习Android - 个人学习笔记(四) - java基础 - 数据类型、变量、字符串、数组
- 数据内存存储(常量,局部变量,全局变量,程序代码)
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- C/C++学习之C提高----C数组的定义、类型、定义数组指针变量、多维数组的本质、多维数组做函数参数、将两个数组中的字符串copy到第三个数组
- C++学习笔记2--函数重载 复杂的数据 内存对齐 指针数组 结构与指针 传值传址传引用 联合枚举类型别名
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- C++程序运行时内存布局之----------局部变量,全局变量,静态变量,函数代码,new出来的变量
- symbian c++ 学习 2 数据类型及代码规范
- 程序在的内存中的分配(常量,局部变量,全局变量,程序代码)(转)
- C/C++中不同数据类型所占用的内存大小
- 程序代码,常量,局部变量,全局变量,在内存中的储存位置
- 探讨:程序在内存中的分配(常量,局部变量,全局变量,程序代码)问题
- 【MFC学习笔记2】MFC中的数据类型,全局变量,全局函数和宏。
- Java学习之数组1(1.数组的声明;2.元素为引用数据类型的数组;3.关于main方法里的String[] args;4.数组排序;5.数3退1 数组算法,(用数组模拟链表);6数组查找之二分法;7数组的拷贝)
- 程序在的内存中的分配(常量,局部变量,全局变量,程序代码)
- Safe C++ 读书笔记:对基本数据类型进行封装,以编写更安全的C++代码
- C++复合数据类型数组学习笔记
- 程序代码,常量,局部变量,全局变量在内存中的保存位置
- C++学习第5篇-变量范围及其他数据类型
- 改善C++ 程序的150个建议学习之建议35:使用内存池技术提高内存申请效率与性能