【C语言】通识篇4

#define定义标识符常量和宏

标识符常量

#include <stdio.h>
#define M 100//只是个符号,没有地址,编译期间用到M的地方全部变成100

int main()
{
    int arr[M] = {0};
    int m = M;
    printf("%d\n", sizeof(arr));//400
    printf("%d\n", M);//100
    printf("%d\n", m);//100
    return 0;
}

test.c 源文件怎么使用的:

(预编译) - 编译 - (汇编) - 链接 - 运行 - test.exe

//预编译解析

#define MAX 1000

int main()
{
    int m = 1000;   //此时 define 定义的符号在预编译(预处理)阶段会被替换成它的内容
    printf("%d", m);
    
    return 0;
}

define 定义的数据类型依据具体情况而定,上文代码 MAX 本身是没有类型的,它的内容 1000 是有类型的,所以使用 MAX 可以把它当成整型来用

#define STR "hello bit"//STR 是 sting(字符串) 的缩写

int main()
{
    printf("%s", STR);
    
    return 0;
}

根据编译环境来看能否打印汉字

#include <stdio.h>
#define ADD(x, y) ((x)+(y))//宏

int Add(int x, int y)//函数
{
    return x + y;
}

int main()
{
    int a = 10;
    int b = 20;
    int c = ADD(a, b);
    //编译后变为int c = ((a)+(b))
    int d = Add(a, b);
    printf("%d\n", c);//输出30
    printf("%d\n", d);//输出30
    return 0;
}

宏:#define+宏名ADD+参数(x, y)+实现体((x)+(y))

函数:返回类型int+函数名Add+参数(int x, int y)+函数体{ ...code... }

函数与宏的区别:

  1. 函数参数有类型及名字 (int x, int y),宏参数没有类型;只有名字 (x, y)
  2. 函数有返回类型;宏没有
  3. 函数体需要用 { } 括起来;宏直接写实现方式
  4. 函数名字一般不会全大写;宏名一般全大写

宏的语句可以是多条语句

指针

内存

内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的(寄存器集成在 CPU 上,没有地址;内存才有地址)

为了有效的使用内存,就把内存划分成一个个小的内存单元,每个内存单元的大小是1个字节

为了能够有效的访问到内存的每个单元,就给内存单元进行了编号,这些编号被称为该内存单元的地址

右侧为内存单元对应的地址,常用16进制表示

地址就是为了让我们很方便地找到内存里面的空间

32位/64位

32位:32根地址线/数据线

在计算机上,有地址线,有强弱两种电信号,电信号依照高低电频转换为数字信号1/0

00000000000000000000000000000000

00000000000000000000000000000001

11111111111111111111111111111111

2 32 2^{32} 232个可能的二进制序列,一个二进制序列可以对应一个内存单元(1Byte),内存单元有编号,编号就是内存单元的地址

2 32 2^{32} 232个二进制序列—— 2 32 2^{32} 232个内存单元—— 2 32 2^{32} 232(4,294,967,296)Byte——4GB

所以32位机器真正能管理的物理空间只有4GB,同理64位机器真正能管理的物理空间有16EB(17179869184GB)

程序运行起来,要加载到内存中,也要申请内存空间使用

内存窗口

输入 &a - 取a的地址

int a = 10;
printf("%p", &a);//%p - 打印地址,输出0x000000FCD3CFFB44,为 a 的起始地址,而不是所有地址

取地址

#include <stdio.h>

int main()
{
    int a = 10;
    int* pa = &a;//pa的数据类型为int*,pa叫做指针变量,是用来存放指针的变量
    printf("%p\n", &a);//%p是专门用来打印地址的,表示形式为16进制
    printf("0x%p\n", &a);
    
    *pa = 20;
    printf("%d\n", a);//20
    return 0;
}

内存单元编号=地址=指针,口头说的指针,基本上都是指针变量

& 是取地址,* 是通过地址找回去,是相反的动作

指针变量的大小

printf("%d\n", siezeof(int*));//4
printf("%d\n", siezeof(char*));//4,而不是1

32位机器上:地址是32个二进制位,这个地址存储需要4个字节,所以32位机器上指针变量的大小是4Byte

64位机器上:地址是64个二进制位,这个地址存储需要8个字节,所以64位机器上指针变量的大小是8Byte

结构体

#include <stdio.h>
//创建结构体类型
struct Stu
{
    //创建结构体成员
    char name[20];//名字
    int age;//年龄
    char sex[5];//性别:男/女/保密
};

void print1(struct Stu s)//需要写在创建结构体类型下面
{
    printf("%s %d %s\n", s.name, s.age, s.sex);
    printf("%s %d %s\n", (&s)->name, (&s)->age, (&s)->sex);
}

void print2(struct Stu* ps)
{
    printf("%s %d %s\n", (*ps).name, (*ps).age, (*ps).sex);//写法1,.结构成员访问操作符,格式:结构体变量.结构体成员
    printf("%s %d %s\n", ps->name, ps->age, ps->sex);//写法2,->结构成员访问操作符,格式:结构体指针->结构体成员
}

int main()
{
    //创建结构体变量
    struct Stu s1 = {"张三", 18, "男"};//初始化学生1
    struct Stu s2 = {"如花", 45, "女"};//初始化学生2
    
    printf("%s %d %s\n", s1.name, s1.age, s1.sex);//直接打印s1
    print1(s2);//函数打印s2
    print2(&s2);//函数打印s2
    
    scanf("%s %d %s", s1.name, &(s1.age), s1.sex)//输入(替换)s1结构体数据,name、sex是数组,数组名本来就是地址,故不需取地址
    return 0;
}
//typedef 类型重命名
typedef struct Stu
{
    char name[20];
    int age;
    char sex[5];
}Stu;//将struct Stu重命名为Stu

int main()
{
    //结构体变量
    Stu s1 = {"张三", 18, "男"};//重命名使之简写
    struct Stu s2 = {"如花", 45, "女"};
    return 0;
}

课后习题

4 BC101 班级成绩输入输出

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
    float score[5] = { 0.0 };
    int i = 0;
    for (i = 0; i < 5; i++)
    {
        int j = 0;
        float sum = 0.0;
        for (j = 0; j < 5; j++)
        {
            scanf("%f", &score[j]);
            sum += score[j];
        }
        for (j = 0; j < 5; j++)
        {
            printf("%.1f", &score[j]);
        }
        printf("%.1f\n", sum);
    }
    return 0;
}
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
    int i = 0;//初始化i表示5个同学,用来循环5次

    for (i = 1; i <= 5; i++)
    {
        double score = 0.0;//初始化,防止上一个同学影响到下一个同学
        double sum = 0.0;//初始化,防止上一个同学影响到下一个同学
        int j = 0;//初始化j表示5科成绩,用来循环5次
        for (j = 1; j <= 5; j++)
        {
            scanf("%lf", &score);//输入单科成绩
            printf("%.1lf ", score);//输出单科成绩,注意空格
            sum += score;
        }
        printf("%.1lf\n", sum);//输出单行成绩之和
    }
    return 0;
}

注意:空格把数据进行分隔,scanf进行获取时只能以空格为间隔一个个进行获取

5 BC56 线段图案

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
    int i = 0;//线段长度
    int n = 0;//循环次数
    while (scanf("%d", &i) != EOF)//!= EOF可以替换成== 1
    {
        for (n = 1; n <= i; n++)
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

6 时间转换

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>

int main()
{
    int sec = 0;//输入秒数
    scanf("%d", &sec);
    int h = sec / 60 / 60;//时
    int m = sec / 60 % 60;//分
    int s = sec % 60;//秒
    printf("%d %d %d\n", h, m, s);
    return 0;
}

注意:时分秒的简便计算

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值