C语言进阶
发表于 2017-07-05 | 分类于 C语言
变量本质
变量的本质就是其名称所相对用的内存空间(内存地址)内的数据的别名而已
1、程序通过变量来申请和命名内存空间 int a=0;
2、通过变量名来访问内存空间(一段连续)内存空间的别名!(相当于一个简易的门牌号)
3、变量对内存,可读可写
(1)通过变量往内存中读写数据 (2)不是向变量读写数据 (3)是向变量所代表的内存空间中读写数据
#include "stdio.h"
int main(void)
{
int a;
int b; //a,b进行定义变量向系统要内存
a=10; //直接赋值 //这里是cpu进行执行代码!
printf("&a:%d\n",&a);
//-1938448308
//间接赋值
*((int *)-1938448308) = 200;
printf("a:%d\n",a);
system("pause");
return 0;
}
- 数据类型的不同导致的分配内存不一样,下面就是一个小小的例子
eg:
#include "stdlib.h"
#include "stdio.h"
#include "string.h"
//数据类型的用法
//数据类型的本质:固定大小内存块的别名
//b &b 数组数据类型
//1、数据类型
//2、数组指针
//3、数组类型和数组指针类型的关系
void mian()
{
int a; //告诉编译器分配4个字节的内存
int b[10]; //相当于10个整数的内存也就是40个字节
printf("b:%d, b+1:%d, &b: %d, &b+1:%d \n",b,b+1,&b,&b+1);
//b+1 和&b+1 代表的结果不同 是因为所代表的数据结构不同
//b 代表的是数组首元素的地址
//&b 代表的是整个数组的地址
system("pause");
}
数据类型
数据类型的封装
- (理解:总的来说就是数据类型就是让编译器知道如何给相应的变量分配相应大小的内存 )
1、void代表的是“无类型”也就是可以存储任何类型的指针
2、只有相同类型的指针才能够相互赋值
数据类型的理解
1、数组也是一种数据类型,它是“同一类型的数据构成的集合”
2 、构造类型:
a、从类型的定义上进行解释:每一个构造体(即组成该类型的抽象值集中的每一个抽象值)都是由若干属于某一数据类型的数据按一定规则所组成。
b、从数据结构角度进行解释:构造体的数据结构中的每一个节点(数据元素)都是一个属于某种数据类型的数据。
c、综上,构造体从数据类型角度分析,它是一种数据类型(一个值集+一个操作集),并且该类型是由若干属于某一数据类型的数据构造而成。
d、误区:构造类型并不是由某些“类型”构造而成,而是由某些“类型数据”构造而成。
3、数组是一种构造体,所以从类型角度看,数组当然是一种类型(事实上也如此,数组的确是中、高级语言中的一种重要的数据类型。
4、函数也是一种数据结构.比如说:void main()表明该函数是void型,即运行完main函数后没有数据返回,int main()则是int型,运行完该函数就要返回一个int型的数据,即在main函数体里面要有return语句,否则编译就会出错
。
5、是使用mian()函数的时候不推荐使用无返回类型的void mian(),推荐使用int类型的mian()函数,而且在C++上main()函数只有俩种。
int main( void )
int main( int argc, char *argv[] )
#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
//数据类型的用法
//数据类型的本质:固定大小内存块的别名
//b &b 数组数据类型
//1、数据类型
//2、数组指针
//3、数组类型和数组指针类型的关系
void main()
{
int a; //告诉编译器分配4个字节的内存
int b[10]; //相当于10个整数的内存也就是40个字节
printf("b:%d, b+1:%d, &b: %d, &b+1:%d \n",b,b+1,&b,&b+1);
//b+1 和&b+1 代表的结果不同 是因为所代表的数据结构不同
//b 代表的是数组首元素的地址
//&b 代表的是整个数组的地址
system("pause");
}
四区模型
- 四区分别是:栈区,堆区,全局区和代码区
C语言和java语言和其他语言的不一样的地方:及其恐怖
C语言中可以在栈上分配内存,也可以在堆上分配内存,可以清楚的知道你的内存空间来自何方去向何处!
- 这是一个非常好的内存四区模型图:http://blog.csdn.net/wu5215080/article/details/38899259
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
char * getStr1()
{
char *p1 = "abcdefg";
return p1;
}
char * getStr2()
{
char *p2 = "abcdefg";
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);
//按道理来说p1,p2的地址应该不同才对,为什么地址却是相同的。
//这就是四区模型导致的
system("pause");
return;
}
堆栈的属性
1、stack(栈)的生长方向(开口向上还是开口向下的)
2、向堆栈中导入a,b俩个变量,如果b的地址大则开口向上;b的地址小,则开口向下;
3、一般情况下其给堆栈方向的开口向下,但是我测试的时候开口是向上的
4、buf[64]这个的生长方向肯定是向上的,满足buf[i+1]这样的循环
- 下面是一个小小的检测的方式
#define _CRT_SECURE_NO_WARNINGS
#include "stdlib.h"
#include "string.h"
#include "stdio.h"
char *getMen(int num)
{
char *p1 = NULL;
p1 = (char *)malloc(sizeof(char) * num); //固定分配的空间。这个就是四区的概念了。变量直接定义的向内存空间索要的就是系统的一个栈的一个部分
//同样指针指向的地方或者变量不能是同一个栈(区)的地方
if (p1 == NULL)
{
return NULL;
}
return p1;
}
//栈
//注意 return不是把内存块的64个字节,给return出来,而是把内存块的首地址(内存的编号eg:oxaa11),返回给tmp
char *getMen2()
{
char buf[64];//临时变量 栈区存放
strcpy(buf,"123456789");
return buf; //在return的时候系统会释放buf的内存空间,但在main中tmp会接受buf这样会导致,tmp这个所在内存空间的指针,指向的不是数据,指向的是buf[64]这样的一个buf的首地址,而不是整个buf[64]这个集合的内存空间
}
void main()
{
char *tmp = NULL;
tmp = getMen(10);
if(tmp == NULL)
{
return;
}
strcpy(tmp,"111222");//往tmp所指向的内存空间copy数据
tmp = getMen2();
//tmp = Oxaa11 //相当于这个效果
printf("tmp:%s\n",tmp);
printf("Hello World\n");
system("pause");
return;
}
注
一:建立正确的“程序运行内存的布局图”是学好C的关键
二:四区分别是:栈区,堆区,全局区和代码区
三:C语言中可以在栈上分配内存,也可以在堆上分配内存,可以清楚的知道你的内存空间来自何方去向何处!
四:正确学好指针
1、指针指向谁,就把谁的地址给指针
2、指针变量和他指向的内存空间变量是不同的概念
3、想学好指针不是指针的加加减减,指针是指向相对应的内存空间的标号