C/C++学习之C提高----C程序数组排序、数据类型(大小,别名,封装)、变量、程序的内存四区模型(栈,堆,全局,代码区)

1.BS模型和CS模型

这里写图片描述

2.第一个C程序之数组排序

#include<stdlib.h>
#include<string.h>

//排序
void main()
{
    int i = 0,j = 0;
    int tmp = 0;
    int a[] = { 33, 55, 22, 66, 44, 99, 11 };
    printf("排序前\n");
    for (i = 0; i < 7; i++){
        printf("%d", a[i]);
    }

    //排序
    //外层循环 当i=0的时候,让j从1到n进行变化
    //外层循环 当i=1的时候,让j从2到n进行变化
    //外层循环 当i=2的时候,让j从3到n进行变化
    //外层循环 当i=3的时候,让j从4到n进行变化...

    //结论:按照一个i变量不变,让另外一个变量j进行变化;下一轮,依次进行
    for (i = 0; i< 7; i++){
        for (j = i+1; j < 7; j++){
            if (a[i]>a[j]){//如果a[i]>a[j],则交换
                tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
    printf("排序后\n");
    for (i = 0; i < 7; i++){
        printf("%d", a[i]);
    }
    printf("hello...\n");
    system("pause");
}

代码优化

#include<stdlib.h>
#include<string.h>

//void printArray(int a[],int num)
void printArray(int *a,int num)
{
    int i = 0;
    for (i = 0; i < num; i++){
        printf("%d", a[i]);
    }
}
//void sortArray(int a[],int num)
void sortArray(int *a,int num)
{
    //排序
    int i, j, tmp;
    for (i = 0; i< num; i++){
        for (j = i + 1; j < num; j++){
            if (a[i]>a[j]){//如果a[i]>a[j],则交换
                tmp = a[i];
                a[i] = a[j];
                a[j] = tmp;
            }
        }
    }
}
//数组做函数参数的退回问题    退回为一个指针
//结论:把数组的内存地址和数组的有效长度传给被调用函数
//排序
void main()
{
    int i = 0, j = 0;
    int tmp = 0;
    int num = 0;
    int a[] = { 33, 55, 22, 66, 44, 99, 11 };

    num = sizeof(a) / sizeof(a[0]);
    printf("num:%d", num);

    printf("排序前\n");
    printArray(a,num);
    //排序
    sortArray(a, num);

    printf("排序后\n");
    printArray(a, num);
    printf("hello...\n");
    system("pause");
}

结论

  • 数组做函数参数的退回问题 退回为一个指针
  • 1.把数组的内存地址和数组的有效长度传给被调用函数
  • 2.实参的a和形参的a的数据类型本质不一样
  • 3.形参中的数组,编译器会把它当成指针处理 这是c语言特色
  • 4.形参写在函数上,和写在函数内是一样的,只不过是具有对外的属性而已。

运行结果

这里写图片描述

3.数据类型本质分析

(1)数据类型概念

  • “类型”是对数据的抽象
  • 类型相同的数据有相同的表示形式、存储格式以及相关的操作
  • 程序中使用的所有数据都必定属于某一种数据类型

这里写图片描述

(2)求数据类型大小

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

void main()
{
    int a; //告诉c编译器分配4个字节的内存
    int b[10] ; //告诉c编译器分配40个自己内存

    printf("b:%d, b+1:%d, &b:%d, &b+1:%d \n", b, b+1, &b, &b+1);

    printf("sizeof(b):%d \n", sizeof(b));  //40
    printf("sizeof(a):%d \n ", sizeof(a)); //4

    //sizeof是操作符,不是函数;sizeof测量的实体大小为编译期间就已确定

    // b+1  &b+1 结果不一样  //b &b所代表的数据类型不一样
    //b 代表的数组首元素的地址
    //&b代表的是整个数组的地址  

    printf("hello....\n");
    system("pause");
}

这里写图片描述

(2)数据类型别名

#include "stdlib.h"
#include "stdio.h"
#include "string.h"

//复杂类型别名
struct Teacher
{
    char name[64];
    int age;
}Teacher;


typedef struct Teacher2
{
    char name[64];
    int age;
}Teacher2;


//简单类型别名 typedef
typedef int u32;


void main()
{
    int a; //告诉c编译器分配4个字节的内存
    int b[10] ; //告诉c编译器分配40个自己内存

    struct Teacher t1;//前要加struct

    Teacher2 t2; //不需要加struct
    t1.age = 31;

    printf("u32:%d \n", sizeof(u32));

    printf("hello....\n");
    system("pause");
}

这里写图片描述

(3)数据类型的封装

{
    char *p2 = NULL;
    void *p1 = NULL;
    p2 = (char *)malloc(100);

    p1 = &p2;
}
{
    //void a;//编译器不知道如何分配内存
}

4.变量的本质

(1)变量的概念

  • 概念:既能读又能写的内存对象,称为变量;若一旦初始化后不能修改的对象则称为常量。
  • 变量定义形式: 类型 标识符, 标识符, … , 标识符 ;
  • 例如:
  • int x ;
  • int wordCut , Radius , Height ;
  • double FlightTime , Mileage , Speed ;

(2)变量的本质

  • 1、程序通过变量来申请和命名内存空间 int a = 0
  • 2、通过变量名访问内存空间
  • (一段连续)内存空间的别名(是一个门牌号)
  • 3、修改变量有几种方法?
  • 1) 直接
  • 2) 间接。内存有地址编号,拿到地址编号也可以修改内存;于是横空出世了!(编程案例)
  • 3) 内存空间可以再取给别名吗?
  • 4) 数据类型和变量的关系
  • 通过数据类型定义变量
#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

void main()
{
    int a ;
    int b; 
    a = 10; //1 直接赋值  //cpu里面执行

    printf("&a: %d\n", &a);

    //2间接赋值  直接通过内存
     *((int*)&a) = 200;

     printf("a: %d\n", a);

    printf("hello...\n");
    system("pause");
    return ;
}

这里写图片描述

5.程序的内存四区模型

(1)内存四区的建立流程

这里写图片描述

  • 流程说明
  • 1、操作系统把物理硬盘代码load到内存
  • 2、操作系统把c代码分成四个区
  • 3、操作系统找到main函数入口执行

这里写图片描述

(2)静态存储区案例理解

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

char * getStr1()
{
    char *p1 = "abcdefg";
    //char *p1 = "abcdefg2";
    return p1;
}
char *getStr2()
{
    char *p2 = "abcdefg2";
    return p2;
}

void main()
{
    char *p1 = NULL;
    char *p2 = NULL;
    p1 = getStr1();
    p2 = getStr2();

    //打印p1 p2 所指向内存空间的数据
    printf("p1:%s , p2:%s \n", p1, p2);

    //打印p1 p2 的值
    printf("p1:%d , p2:%d \n", p1, p2);

    printf("hello...\n");
    system("pause");
    return ;
}

这里写图片描述

  • 把char *p1 = “abcdefg”;改为char *p1 = “abcdefg2”;发现指针所指地址一样。

这里写图片描述

静态存储器内存四区图

这里写图片描述

(3)堆栈案例理解

#define  _CRT_SECURE_NO_WARNINGS 
#include <stdlib.h>
#include <string.h>
#include <stdio.h>

//堆
char *getMem(int num)
{
    char *p1 = NULL;
    p1 = (char *)malloc(sizeof(char) * num);
    if (p1 == NULL)
    {
        return NULL;
    }
    return p1;
}

//栈
//注意 return不是把内存块 64个字节,给return出来,而是把内存块的首地址(内存的标号0xaa11) ,返回给 tmp

// 理解指针的关键,是内存. 没有内存哪里的指针 

//
char *getMem2()
{
    char buf[64]; //临时变量 栈区存放
    strcpy(buf, "123456789");
    //printf("buf:%s\n", buf);
    return buf;
}

void main()
{
    char *tmp = NULL;
    tmp = getMem(10);
    if (tmp == NULL)
    {
        return ;
    }
    strcpy(tmp, "111222"); //向tmp做指向的内存空间中copy数据

    //tmp = getMem2();
    tmp = 0xaa11;

    printf("hello..tmp:%s.\n", tmp);
    system("pause");
    return ;
}

堆栈图解

这里写图片描述

(4)指针

指针是一种数据类型

  • 1) 指针也是一种变量,占有内存空间,用来保存内存地址
  • 2)*p操作内存
  • 在指针声明时,*号表示所声明的变量为指针
  • 在指针使用时,*号表示 操作 指针所指向的内存空间中的值
  • *p相当于通过地址(p变量的值)找到一块内存;然后操作内存
  • *p放在等号的左边赋值(给内存赋值)
  • *p放在等号的右边取值(从内存获取值)
  • 3)指针变量和它指向的内存块是两个不同的概念
  • //含义1 给p赋值p=0x1111; 只会改变指针变量值,不会改变所指的内容;p = p +1; //p++
  • //含义2 给*p赋值*p=’a’; 不会改变指针变量的值,只会改变所指的内存块的值
  • //含义3 =左边*p 表示 给内存赋值, =右边*p 表示取值 含义不同切结!
  • //含义4 =左边char *p
  • //含义5 保证所指的内存块能修改
  • 4)指针是一种数据类型,是指它指向的内存空间的数据类型
  • 含义1:指针步长(p++),根据所致内存空间的数据类型来确定
  • p++=->(unsigned char )p+sizeof(a);
  • 结论:指针的步长,根据所指内存空间类型来定。
  • 注意:
  • 不断的给指针变量赋值,就是不断的改变指针变量(和所指向内存空间没有任何关系)。

测试

    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>

    void main()
    {
        int a = 10;
        char *p1 = 100;  //分配4个字节的内存
        char ****p2 = 100;


        int *p3 = NULL;

        p3 = &a;

        *p3 = 20; //间接的修改a的值
        //*就像一把钥匙 通过一个地址(&a),去修改a变量的标示的内存空间

        {
            int c = 0;
            c = *p3;  //c=20
            //*p放在=号左边 写内存
            //*p放=号的右边 读内存
            printf("c:%d \n", c);
        }

        {
            char *p4 = NULL;
            p4 = (char *)malloc(100);
            p4 = (char *)malloc(200); //0xcc11

        }

        printf("a:%d , p1:%d , p2: %d", sizeof(a), sizeof(p1), sizeof(p2));
        printf("hello...\n");


        system("pause");
        return ;
    }

运行结果

这里写图片描述

保证所指的内存块能修改

    #define  _CRT_SECURE_NO_WARNINGS 
    #include <stdlib.h>
    #include <string.h>
    #include <stdio.h>  
    char *getStr()
    {
        char *tmp = NULL;
        tmp = "abcdefgf";
        return tmp;
    }   
    void main()
    {
        char *p = getStr();
        printf("p:%s \n", p);
        *(p+2) = 'r';  //经常出现的错误 保证指针所指向的内存空间 可以被修改
        system("pause");
        return ;
    }

运行结果

这里写图片描述

图解

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值