C和指针(第三章)
(一)看了半天,觉得最有价值的地方莫过于是数据的存储和字符类型和指针之间的混沌关系
#数据存储:
1.1栈区:编译器在需要的时候分配,不需要的时候回收(一般变量的生命周期到外面的"}"为止),它的内存空间相对于堆来说,要小很多(比如申请int A[10000000000000],编译器就会报错),但是好在执行效率高,因为malloc/new都是要通过复杂的算法才可以申请到空间,花费了一定的时间,更不用说还有delete/free了
1.2堆区:堆并不是一无是处,相反,它拥有较大的内存空间,相对栈来说可以存储大量数据
1.3全局区,静态区:全局变量和静态局部变量都放在这里,带到程序结束时,一同释放
1.4常量储存区:顾名思义,这里储存不允许修改的常量,数据,字符串,指针等等,程序结束时释放
1.5程序代码区存放二进制函数代码
#char和字符串(常量)之间~~“难以理解♂”~~ 的关系
char和char[]之间的区别,超过你的想象
前者是定义一个char的指针你比如:
char* a="hello world";
a[0]='H'
就会报错,提示为:不可以被written,因为char* a只是个指针,他不知道这个长度有多大,但是如果这样写:
char a[]="hello world";
a[0]="H"
就没有任何问题,这是常规操作
如果这样写:
char a[]="hello world";
char *A=a;
A[0]="H" //知道了大小后,访问就不存在问题了,编译通过
char *s = (char *)malloc(n);//其中n为要开辟空间的大小
char s[n];
这两句话等价,当然可以通过s[i]="*"之类的操作了
include <stdio.h>
int main(int argc, char* argv[]) {
char* buf1 = "this is a test";
char buf2[] = "this is a test";
printf("size of buf1: %d\n", sizeof(buf1));
printf("size of buf2: %d\n", sizeof(buf2));
return 0;
}
分别输出:
size of buf1:4
size of buf2:15
解释:buf1只是一个指针,我们知道任何一个指针都是4个字节,而buf2包含了15个字节(你数数就造了QVQ)
终于写完第一节了,红红火火恍恍惚惚
(二)作用域,作用域分为:文件作用域,函数作用域,代码块作用域和原型作用域,标识符声明的位置决定它的作用域
1.代码块作用域:任意一对’{}'之间的所有语句叫做代码块
int a,b,c;
{
int f; //1
int g; //1
int i; //1
......
{
int f,g,i; //2
}
{
int i; //3
}
}
代码块的内部可以对外部进行屏蔽…//3处的和//1处的i是完全不同的,//3执行完成后i在栈的空间就被释放,但是只有当程序走完后//1中的i才会被释放,他们之间半毛钱的关系都没有QVQ同理//1和//2也是这样的
提醒:这个在双层for循环里和命名上要格外注意(不要重复命名)!!!
2.文件作用域:图3.1
int a; //1
/*2*/ int b(int c); //3
/*4*/ int d(int e) //5
{
int f; //6
/*7*/ int g(int) //8;
.........
{
int f,g,i; //9
}
{
int i; //10
.......
}
}
比如声明1和2,还有4,至于include<***>的话,就好像他们把另一个文件放在了这里一样,里边的全局函数,全局变量和这里的全局函数全局变量具有相同地位
3.原型作用域:声明3和声明8,取名字无所谓,关键在于定义函数时的名称,声明时倒是无所谓的
4.函数作用域:一个函数中所有语句标签必须唯一(不要用goto语句,写大型程序时,别人看了想打人)
**(三)**链接属性
internal:内部(static)
static 用来修改链接属性为extern的声明语句,比如:
int b; //1
int c(int d) //2
{
int e;
int f(int g);
.....
}
为了不为其他的cpp文件访问,只在本编译单元内访问,才加上static关键字.
当在代码块内部变量声明时,加上static时,从自动变量修改为静态变量,但是变量的链接属性和作用域不变
external:外部
较复杂,在第一次声明的地方加上extern,可以让别人更好的知道你的意图
注意:
static int i; //1
int func()
{
int j;
extern int k;
extern int i; //2
}
//2处的extern不能影响第一次的static声明,换句话说//2处的extern无效!
none:无
****(四)结语
这些东西虽然有点难以理解,但是也没有算法题那么难以理解,它更像是学习生活中的调味品,在吃惯了苦涩的算法题后,换个口味,来些稍微轻松点的小知识,为自己以后的路打下坚实的基础