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 

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

C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第1张图片

读内存空间(int):

#include 

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 

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 

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 

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
常量,只读【不能变】。
C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第2张图片

内存用性:
1、内存操作的大小
2、内存的变化性,可写可读

const char *p 【推荐】 字符串常量 p是门牌号
char const *p 同上,

char *const p【推荐】 硬件资源 LCD 指向固定地址,内容可以刷新
char *p const 同上,

const char *const p ROM

示例:

#include 

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 

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 

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

C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第3张图片
C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第4张图片

const的详细解释:可参考C语言中的const
P+1与*(P+1)的延伸可参考:关于C语言中二维数组的P+1与*(P+1)个人浅见

逻辑操作符>= <= == !=

1、跟一个特殊值进行比较,0x0,地址的无效值,结束标志。
if (p==0x0);
建议用NULL进行比较。
2、指针必须是同类型的比较才有意义
char *
int *

示例1

#include 

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]
C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第5张图片

p[m]==NULL —>二维空间结束了(结束标志)

例子

#include 

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(个数)的常用写法:

C/C++|物联网开发入门+项目实战|指针|嵌入式C语言高级|C语言内存空间的使用-学习笔记(9)_第6张图片

#include 

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

你可能感兴趣的:(物联网开发入门与实战,c语言,学习,内存空间,指针,多级指针)