C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)
文章目录
- 2-3 : C语言内存空间的使用
-
- 指针概述
-
- 示例:
- 指针+修饰符
- 指针+运算符
-
- 示例
- 示例1
- 多级指针
-
- 例子
- 省略argc(个数)的常用写法:
参考:
麦子学院-嵌入式C语言高级-内存空间
2-3 : C语言内存空间的使用
指针概述
内存类型资源地址、门牌号的代名词
指针:地址的代名词
指针变量:存放指针这个概念的盒子
*P
char *p
*p;
C语言娟译器对指针这个特殊的概念,有2个疑问?
1、分配一个盒子,盒子要多大?
在32bit系统中,指针就4个字节
2、盘子里存放的地址所指向内存的读取方法是什么?
3、指针指向内容空间,一定要保证合法性。
示例:
#include <stdio.h>int main()
{int *p1;char *p2;printf("the p1 is %u,p2 is %u\\n",sizeof(p1),sizeof(p2));return 0;}返回值(64位系统):
```bash
E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
the p1 is 8,p2 is 8
读内存空间(int):
#include <stdio.h>int main()
{int a = 0x12345678;int *p1;p1 = &a;printf("the p1 is %x\\n",*p1);return 0;}
// 返回值
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// the p1 is 12345678
读内存空间(char):
#include <stdio.h>int main()
{int a = 0x12345678;char *p1;p1 = &a;printf("the p1 is %x\\n",*p1);return 0;}
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// 2.c: In function 'main':
// 2.c:8:8: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 78
浮点数的存储(形式非常特殊)
显示方法1:
#include <stdio.h>int main()
{float a = 1.2;int *p;p = &a;printf("the p1 is %x\\n",*p);return 0;}
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// 2.c: In function 'main':
// 2.c:8:7: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 3f99999a
显示方法2:
#include <stdio.h>int main()
{float a = 1.2;unsigned char *p;p = &a;printf("the p1 is %x\\n",*p);return 0;}
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// 2.c: In function 'main':
// 2.c:9:7: warning: assignment from incompatible pointer type [enabled by default]
// the p1 is 9a
注意:如果用char *p,会打印符号位,导致显示为:the p1 is ffffff9a。
指针+修饰符
const
常量,只读【不能变】。
内存用性:
1、内存操作的大小
2、内存的变化性,可写可读
const char *p 【推荐】 字符串常量 p是门牌号
char const *p 同上,
char *const p【推荐】 硬件资源 LCD 指向固定地址,内容可以刷新
char *p const 同上,
const char *const p ROM
示例:
#include <stdio.h>int main()
{char *p = "hello world!\\n";char buf[] = {"hello world!\\n"};char *p2 = buf;printf("the one is %x\\n",*p);*p2 = 'a'; //不合法,会出现段错误printf("%s\\n",p2); //无输出return 0;}
正确的写法应该是:
const char p = “hello world!\\n”;
此时p2 = 'a’编译器提示错误:
E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
2.c: In function 'main':
2.c:11:5: error: assignment of read-only location '*p'
volatile
防止编译器优化指向内存地址,每次都要强制更新或者执行地址所指的值
volatile char *p
*p== 0x10
while(p == 0x10 );
xxx
typedef
char *p;
什么类型,变量名称;
char *name_t; name_t是一个指针(存储地址的盒子),指向了一个char类型的内存
typedef char *name_t; name_t是一个指针类型的名称(别名),指向了一个char类型的内存
name_t abc;
指针+运算符
++,–,+,-
int *p = xxx [0x12]
p+1 [012+1(sizeof(*p))] +1是指向下一个单位,操作的是单位。
指针的加法运算,实际上加的是一个单位,单位的大小可以使用sizeof(p[0])
int *p p+1
char *p p+1
p++ p-- 更新地址
[]
变量名[n] p+n等到地址, p[n]自动将该地址的内容取出来
n ID 标签
地址内容的标签访问方式,取出标签里的值。
示例
#include <stdio.h>int main()
{int a = 0x12345678;int b = 0x99991199;int *p1 = &b; //指针与地址类型一致char *p2 = (char *) &b; //如果不强制转换,编译器会报警告,变量类型与指针不一样printf("the p1+1 is %x ,or is %x, *p1+1 is %x\\n",*(p1+1),p1[1],*p1+1);printf("the p2+1 is %x \\n",p2[1]);return 0;}
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// the p1+1 is 64fe14 ,or is 64fe14, *p1+1 is 9999119a
// the p2+1 is 11
与教程有差异,没有得到预想的结果,见图:
另外对于const的缺陷,编译器也做了优化,不再能够修改,如一下代码:
#include <stdio.h>int main()
{const int a = 0x12345678; //编译器告知结果int b = 0x11223344;//a = 100; //2.c:8:5: error: assignment of read-only variable 'a'int *p = &b;//*(p+1);p[1] = 0x100;printf("the a is %x\\n",a);return 0;}
// p[1] = 0x100未能实现
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// the a is 12345678
const的详细解释:可参考C语言中的const
P+1与*(P+1)的延伸可参考:关于C语言中二维数组的P+1与*(P+1)个人浅见
逻辑操作符>= <= == !=
1、跟一个特殊值进行比较,0x0,地址的无效值,结束标志。
if (p==0x0);
建议用NULL进行比较。
2、指针必须是同类型的比较才有意义
char *
int *
示例1
#include <stdio.h>int main()
{int a = 0x12345678; //编译器告知结果int b = 0x99991199;int *p1 = &b;char *p2 = (char *)&b;if(p1 >= p2){printf("===========\\n");}// printf("the a is %x\\n",a);return 0;}
// E:\\temp>cd "e:\\temp\\" && gcc 2.c -o 2 && "e:\\temp\\"2
// 2.c: In function 'main':
// 2.c:12:11: warning: comparison of distinct pointer types lacks a cast [enabled by default]
多级指针
int p;
存放地址的地址空间,
如:char p 描述内存与内存之间的线性关系,
p[0] p[1] p[n]
p[m]==NULL —>二维空间结束了(结束标志)
例子
#include <stdio.h>int main(int argc,char argv)
{int i;for(i = 0;i < argc;i++){printf("the argv[%d] is %s\\n",i,argv[i]);}return 0;}
// gcc 2.c -o 2
// E:\\temp>2 123 456
// the argv[0] is 2
// the argv[1] is 123
// the argv[2] is 456
省略argc(个数)的常用写法:
#include <stdio.h>int main(int argc,char argv)
{int i = 0;while(argv[i] != NULL){printf("the argv is %s\\n",argv[i]);i++;}return 0;}
// E:\\temp>2 123 456
// the argv is 2
// the argv is 123
// the argv is 456