9.1 作用域 static extern malloc relloc

windows里命令行参数

只有可执行程序的时候,可以把文件拖拽到可执行程序上面

相当于 把文件名当参数传递了

变量作用域:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. int i = 10;
  6. while( i-- ) //这个i是上面的i,所以只会输出10次
  7. {
  8. int i = 0;    //去掉这一句,结果会变成一个死循环,会无限输出9
  9. printf("i = %d\n" , i++);
  10. }
  11. return 0;
  12. }

指针指向一个局部的变量:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. int *p = NULL;
  6. {
  7. int i = 100;
  8. p = &i;
  9. }
  10. *p = 10;
  11. printf("*p = %d\n" , *p);
  12. return 0;
  13. }

结果是正确的,但是极其不建议这样使用

register寄存器变量 不能取其地址

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. //int i = 10;
  6. register int i = 10;
  7. printf("%p\n",&i); //编译就不通过
  8. return 0;
  9. }

static 静态变量:

static虽然在块作用域内,但在程序刚加载的时候就存在了,并且只初始化了一次,在内存中位于静态区。

不过块作用域外面还是无法访问到

  1. int main()
  2. {
  3. while( i-- )
  4. {
  5. static int i = 0;
  6. }
  7. return 0;
  8. }

两个不同文件之间, static用来限制变量只在当前文件有效:

a.c

  1. int a = 5;
  2. int main()
  3. {
  4. printf("%d\n" , a);
  5. return 0;
  6. }

b.c

  1. int a = 10;

编译报错,`a‘被多次定义

解决方法在a.c文件里 int前面加个static

访问的就是当前这个文件的a,即输出5

如果两个文件都有static,说明两个文件内都有a这个变量

a.c

  1. #include <stdio.h>
  2. static int a = 5;
  3. int main()
  4. {
  5. printf("%d\n" , a);
  6. return 0;
  7. }

b.c

  1. static int a = 10;

结果也是5

两个不同文件之间, extern引用同一个变量:

a.c

  1. #include <stdio.h>
  2. int main()
  3. {
  4. printf("%d\n" , a);
  5. return 0;
  6. }

b.c

  1. int a = 10;

编译报错,找不到a

解决方法在a.c里全局变量里加入int a 或者 extern int a  或者 extern a 只进行一个声明

  1. #include <stdio.h>
  2. extern int a;
  3. int main()
  4. {
  5. printf("%d\n" , a);
  6. return 0;
  7. }

或者在a.c局部变量里 extern int a 或者 extern a    注意 这里直接int a 不行 ,就相当于定义了一个未初始化的局部变量;

  1. #include <stdio.h>
  2. int main()
  3. {
  4. extern int a;
  5. printf("%d\n" , a);
  6. return 0;
  7. }

两个不同文件之间  函数声明引用同一个函数:


下面可以正确执行,但是建议在a.c里 声明一下 func ,就是函数的原型

a.c

  1. #include <stdio.h>
  2. void func(); //省略一样正确执行
  3. int main()
  4. {
  5. func();
  6. return 0;
  7. }

b.c

  1. #include <stdio.h>
  2. void func()
  3. {
  4. printf("func\n");
  5. }

如果在b.c文件里的func函数前面加个static,那么就会访问不到这个函数

因此可以得出结论

不同文件之间 使用同一个函数    需要函数声明

不同文件之间 使用同一个变量    需要extern

全局变量和静态变量:

注意,全局变量和静态变量,不初始化的时候,系统会自动初始化为0

  1. #include <stdio.h>
  2. int a;
  3. int main()
  4. {
  5. printf("%d\n" , a);
  6. return 0;
  7. }

内存栈区是从高地址到低地址,和堆顺序相反

  1. #include <stdio.h>
  2. void test(int a , int b)
  3. { //注意,参数是在这个位置才开始入栈,不是在main函数调用时入的
  4. printf("%p , %p\n" , &a , &b); //注意,函数形参也是在栈区,形参是从右到左入栈,所以右面的参数地址高于左边的参数地址
  5. }
  6. int main()
  7. {
  8. int a = 10 ;
  9. int b = 20;
  10. printf("%p , %p\n" , &a , &b);
  11. test( a , b);
  12. return 0;
  13. }

free一个函数返回的指针,因为地址一样:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. char *test()
  5. {
  6. char *s = malloc(sizeof(char) * 10);
  7. printf("s = %p\n" , s);
  8. strcpy( s , "hello");
  9. return s;
  10. }
  11. int main()
  12. {
  13. char *p = test();
  14. printf("%s\n",p);
  15. printf("p = %p\n" , p);
  16. free(p); //这种情况完全是可以free的,因为返回的地址和你要释放的地址是一个地方
  17. return 0;
  18. }

函数参数指针的类型,严重错误,加强理解

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void test( char * p)
  5. {
  6. p = malloc(sizeof(char) * 10);
  7. strcpy( p , "hello");
  8. printf("%p\n",p);
  9. }
  10. int main()
  11. {
  12. char *s = NULL;
  13. test(s);
  14. printf("%p\n",s);
  15. printf("%s\n" , s);
  16. return 0;
  17. }

这个严重新手级的错误,你传递的指针只是传递的当前的NULL,新开辟的内存返回地址,你不知道

解决方案有三种:


第一种解决方案是把传递指针的地址     上策

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void test( char ** p)
  5. {
  6. *p = malloc(sizeof(char) * 10);
  7. strcpy( *p , "hello");
  8. printf("%p\n",*p);
  9. }
  10. int main()
  11. {
  12. char *s = NULL;
  13. test(&s);
  14. printf("%p\n",s);
  15. printf("%s\n" , s);
  16. free(s);
  17. return 0;
  18. }


第二种解决方案是把指针返回。     中策

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. char * test( char * p)
  5. {
  6. p = malloc(sizeof(char) * 10);
  7. strcpy( p , "hello");
  8. printf("%p\n",p);
  9. return p;
  10. }
  11. int main()
  12. {
  13. char *s = NULL;
  14. s = test(s);
  15. printf("%p\n",s);
  16. printf("%s\n" , s);
  17. free( s );
  18. return 0;
  19. }

第三种解决方案是在main函数里开辟      下策

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void test( char * p)
  5. {
  6. strcpy( p , "hello");
  7. printf("%p\n",p);
  8. }
  9. int main()
  10. {
  11. char *s = NULL;
  12. s = malloc(sizeof(char) * 10);
  13. test(s);
  14. printf("%p\n",s);
  15. printf("%s\n" , s);
  16. free(s);
  17. return 0;
  18. }

malloc的应用:

  1. #include <stdio.h>
  2. #include <string.h>
  3. int main()
  4. {
  5. int *p = malloc(sizeof(int) * 5);
  6. memset(p, 0, sizeof(p)); //注意这里只把4个字节的内存清零了
  7. }

sizeof(p)      p是个纯指针,不是数组名, 两者sizeof有区别

解决方法:

memset(p, 0, sizeof(int) * 5);

realloc的应用:动态添加字符串

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. void init_str( char **p )
  5. {
  6. *p = malloc( sizeof(char) * 10 );
  7. memset( *p , 0 ,sizeof(char) * 10 );
  8. strcpy( *p , "hello" );
  9. }
  10. char* append_str( char *p , const char * s)
  11. {
  12. p = realloc( p , strlen(p) + strlen(s) + 1);
  13. memset( p+strlen(p) , 0 , strlen(s)+1); //这是把申请的新内存清零
  14. strcat(p,s);
  15. return p;
  16. }
  17. int main()
  18. {
  19. char *s = NULL;
  20. init_str( &s );
  21. s = append_str( s , " world");
  22. printf("%s\n" , s);
  23. return 0;
  24. }

先malloc得到一块新的内存地址,都是垃圾值

init_str 初始化  先把所有内存清零

然后strcpy hello

realloc 申请内存,不过新申请的内存还是垃圾值。

通过memset把realloc申请的新内存 清零

通过strcat 连接两个字符串

realloc新增加的的不会清0,需要自己清理

解决方法:

memset( p+strlen(p) , 0 , strlen(s)+1);

realloc缩小内存:

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include <stdlib.h>
  4. int main()
  5. {
  6. char *p = malloc(sizeof(char) * 20);
  7. memset(p, 0, 20);
  8. strcpy(p , "123456789");
  9. p = realloc(p , 5);
  10. printf("%s\n",p);
  11. }

可以得出realloc缩小内存的情况,原来的值都会变成垃圾值。如果需要输出正常,要在最后修改成\0

realloc的其他用法:

char *p = realloc ( NULL , 5 );  等于   char *p  = malloc( 5 );

来自为知笔记(Wiz)

时间: 2024-10-13 00:30:43

9.1 作用域 static extern malloc relloc的相关文章

typedef Define static extern的区别

typedef Define static  extern的区别 1) #define#definePI 3.1415926 程序中的:PI*r*r 会替换为#define语句中的数字9 g 2)typedef是在编译时处理的.它在自己的作用域内给一个已经存在的类型一个别名,但是You cannot use the typedef specifier inside a function definition. extern可置于变量或者函数前,以表示变量或者函数的定义在别的文件中,提示编译器遇到

[C语言 - 6] static &amp; extern

A. extern函数 一个c文件生成一个obj文件 外部函数:允许其他文件访问.调用的函数(默认函数为外部函数),不允许存在同名的外部函数 my.c 1 //define a extern function perfectly 2 void extern testEx() 3 { 4 printf("my.c ==> call external function\n"); 5 } 6 main.c 1 //declare the function first to apply

iOS之const,static,extern简介

const,static,extern简介 一.const与宏的区别: • const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. ? 编译时刻:宏是预编译(编译之前处理),const是编译阶段. ? 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误. ? 宏的好处:宏能定义一些函数,方法. const不能. ? 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换. • 注意:很多Blog都说使用宏,

static extern const

static 1.局部变量 // 该变量生命周期不仅仅是进入该函数后,而是整个程序运行期间 void foo() { static int nVar = 0; printf("var = %d\n", ++nVar); } 2.保护本地变量 static int g_nVar; // g_nVar只能在本文件中使用,其他文件不能通过extern访问该变量 3.静态成员变量 // 该变量不属于对象,而属于这个类 class Foo { public: static int nCount;

【编程语言】变量的存储时期/作用域以及static/extern的用法

存储类:               存储时期       链接         内存管理 对于一个变量(不同的存储类型)可以通过存储时期,链接属性,以及相应的作用域来描述它. 存储时期就是变量在内存中的保留时间,变量的作用域和链接在一起表明程序的哪些部分可以通过变量名来使用该变量.于是就有了不通过的存储时期,链接属性,以及作用域的组合 [1]存储时期(变量的生命期,表示存取一个变量在内存空间的存放以及释放时间)                           局部变量          

const/static/extern/self/super

一 .const 和 宏 的区别 const简介:之前常用的字符串常量,一般是抽成宏,但是苹果不推荐我们抽成宏,推荐我们使用const常量. 编译时刻:宏是预编译(编译之前处理),const是编译阶段. 编译检查:宏不做检查,不会报编译错误,只是替换,const会编译检查,会报编译错误. 宏的好处:宏能定义一些函数,方法. const不能. 宏的坏处:使用大量宏,容易造成编译时间久,每次都需要重新替换. 注意: 有很多博客(Blog)描述宏时,说使用宏会消耗很多内存,这种说法并不正确.它并不会生

static extern

static 1>修饰全局变量 *全局变量的作用域仅限于当前文件内部,其他文件无法访问 2>修饰局部变量 ***局部变量的生命周期,与全局变量类似 *但是不能改变作用域 *能保证局部变量永远只初始化一次 - (void)vieDidLoad{      for (int i = 0; i < 5; i++) {        [self test];    } } - (void)test{    static int a = 1;     a++;     NSLog(@"%

const&amp;static&amp;extern

const 结论: 如果const写在指针变量名的旁边, 那么指针的指向不能变, 而指向的内存空间的值可以变 如果const写在数据类型的左边或者右边, 那么指针的指向可以改变, 但是指向的内存空间的值不能改变 // 字符串常量,修饰account,既:account这个是常量不能改,但是他所指向的值 @"这个是可以改的",而且文档字符串常量都是这样的,颜色和宏的颜色也不一样. static NSString * const account = @"account"

变量存储类型(auto static extern)

auto 动态存储类型变量(函数内部变量存储默认为 auto型) auto只用于函数内部定义,单片机在执行这个函数时为它分配内存地址,当函数执行完毕返回后,auto变量会被销毁,再次进入这个函数时,它的初值是不确定的,必须对她重新进行初始化.auto变量是局部变量,只允许在定义它的函数内部使用,在函数外的其他地方都不能使用.由于auto变量在定义它的函数以外的任何地方都是不可见的,所以允许在这个函数以外的其他地方或是其他函数内部定义同名的变量,它们之间是不会发生冲突的,因为他们都有自己的区域性,