c语言 指针与内存,C语言指针与内存

初始指针

使用指针来进行交换值

#include

void change(int *a,int *b){

int tmp=*a;

*a = *b;

*b = tmp;

}

int main(){

int a=5,b=3;

change(&a,&b);

printf("num a = %d\nnum b = %d\n",a,b);

return 0;

}```

- gdb调试工具

`brew install gdb`

调试的时候,生成可以调试的版本,`gcc -g main.c -o main.out`

`gdb ./main.out`对程序进行调试,Mac里面必须是这样`sudo gdb ./main.out`才能对程序进行调试。

`l`列出源代码,按回车继续刚才的命令

`break 12`断点放在12行

`start`单步调试

`n`下一步

`p a`打印出a的变量值

`q`退出

`s`进入函数里面

`bt`查看函数堆栈

`f 1`跳到1这个栈里面

- 计算机中的数据表示方法

计算机中内存中最小单位是字节,1Byte字节=8bit位

- 内存管理

操作系统统一管理,32bit系统,最大使用4G内存,由寻址空间决定的,地址总线是32位,寻址空间是32位,也就是给内存编号只能有32位。

地址总线可以存在多种状态,2^32个状态,所以就是2^32字节,4GB,64位操作系统,64位的地址总线,所以内存足够了,操作系统会给内存地址进行编号,编号就是唯一的内存字节的地址,一个字节存放8个二进制位的数据。

64位操作系统中,用户应用程序使用的内存只要有前面的48位就够了,其他的内存空间是给操作系统内核使用的

高位内存:系统内核->栈->堆->数据段->代码段:低位内存

代码编译后的二进制数据加载到内存中,代码段

声明的全局变量和一些常量在数据段

中间的区域是自由可分配的内存

- 变量和指针的本质

静态变量,静态局部变量,作用域是当前函数,从定义位置,到其所在的{}结束位置,生命周期是从程序运行到程序退出,贯穿整个运行时间,下次函数调用的时候,静态局部变量不会再次初始化,而是沿用上次函数退出时的值。

静态全局变量,作用域为当前文件,从定义位置到文件结尾,声明周期为从程序运行到程序退出,贯穿整个运行时间,但是动态全局变量的作用域是整个项目,即最终编译成可执行文件的所有文件均可以使用动态全局变量。

C语言语法是不允许直接操作代码段的,代码段也是有地址的,除了代码编译后存在代码段外,代码的状态信息是存在内存的栈区域。

C语言是强类型,静态类型的。

变量的本质是一个代号,标识符,代表的是某个地址空间

指针本身也是一个变量,保存的数据是地址,指针变量的地址也就是指针的指针。指针的本质是保存内存地址。

- 操作系统对内存的管理

编译器的优化功能,对源代码进行优化,将同一类型的变量内存地址分配在一块,使得程序执行更快。64位系统中指针是8个字节,因为地址总线是64位的。

栈的内存空间保存了程序运行时候的状态。

代码段的内存地址是向上增长分配的,然后栈段的内存地址是从大往小进行分配的。

- 函数栈以及数据段内存

栈里最先分配地址的函数内存地址更大一些,静态变量,常量还有全局变量默认是在数据段中,静态变量属于某个函数特定的,一个函数被多次调用,但是都在数据段中。

- 函数指针与指针指向的数据访问

`int (*pquadrate)(int a) = &quadrate;`定义一个函数指针

`int s = (*pquadrate)(a);`使用这个函数指针,()表示地址指向某个函数整体,然后后面调用传参数a。如果指向栈内存,数据段内存表示直接去变量里面的值,指向代码段,就是一片代码块。

- 示例代码

include

int global = 0;

int rect(int a,int b){

static int count = 0;

count++;

global++;

int s = a * b;

return s;

}

int quadrate(int a){

static int count = 0;

count++;

global++;

int s = rect(a,a);

return s;

}

int main(){

int a = 3;

int b = 4;

int *pa = &a;

int *pb = &b;

int pglobal = &global;

int (pquadrate)(int a) = &quadrate;

int s = quadrate(a);

printf("%d\n",s);

}```

数组申明的内存排列

x/3d 0x7fffffffde14从这个地址开始显示3个十进制,默认是按照4字节显示

这里经过gcc优化,b的地址在最前面,其次是a,但是i的地址在$10 = (int *) 0x7fff5fbffc54, b的地址$9 = (int *) 0x7fff5fbffc60,a的地址$8 = (int *) 0x7fff5fbffc64,array的地址$12 = (int (*)[3]) 0x7fff5fbffc6c,说明这些变量之间的地址分配还不是连续的,但是数组间的地址分配是连续的。

#include

int main(){

int a = 3;

int b = 2;

int array[3];//必须是常量

array[0] = 1;

array[1] = 10;

array[2] = 100;

int *p = &b;

int i;

for(i = 0;i < 6;i++){

printf("*p = %d\n",*p);

p++;

}

printf("------------------------\n");

p = &b;

for(i = 0;i<6;i++){

printf("p[%d]=%d\n",i,p[i]);

}

return 0;

}```

- 指针运算

`p++`定义了p是int类型,所以大小是4字节,自增就是到下一个4字节的地址。

`p[1]`表示把p向下偏移4个字节

指针是变量,数组是指针常量,数组本身也是地址。

- 字符数组和指针字符串

include

int main(){

char str[] = "hello";

char *str2 = "world";

char str3[10];

printf("input the value\n");

scanf("%s",str3);

printf("str is %s\n",str);

printf("str2 is %s\n",str2);

printf("str3 is %s\n",str3);

}```

str2在代码段,str2是指向这个地址而已,字符类型的指针,字符数组str3本身就是内存地址。str2指向字符串的指针,不能向里面scanf,str2是存的world字符串的地址,在代码段的地址,不能被修改,而str是字符数组的地址,str地址是在栈里面,字符数组是以\0为结尾。x/6cb 0x7ffffffde00打印6个字符,单字节显示。

栈和堆内存才能被写入。

字符数组

str[3]='\0'表示字符串结束位置,str2指向的是常量字符串,所以不能被修改

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值