C语言入门6

文章介绍了C语言中的宏定义,包括常量宏和函数宏,强调了宏替换的特性。接着讲解了指针的概念,如何通过指针访问和修改内存中的值,以及指针在返回多个值时的作用。然后讨论了内存的组织和地址的计算。最后,文章阐述了结构体的使用,如何创建和初始化结构体,以及通过指针操作结构体成员。
摘要由CSDN通过智能技术生成

常量和宏/指针/结构体

Define 定义常量和宏

define 是一个预处理指令

  1. define 定义标识符常量
#define MAX 1000
  1. define 定义宏
#define ADD(X,Y) X+Y

int main()
{
    printf("%d\n",ADD(2, 3));
    
    return 0;
}

这个结果是5
但是如果我的程序是这样的话:

#define ADD(X,Y) X+Y

int main()
{
    printf("%d\n", 4*ADD(2, 3));
    
    return 0;
}

结果并不是20,而是11,WHY?
原因在于4*ADD(2,3),ADD(2,3)被完整地替换成了2+3。
也就是4 * 2+3,相当于并不是先算了ADD,再相乘,而是完整的替换成了2+3。
这就说明一个概念就是宏,它是完整替换的。
如果我想得到20的话,就要这样定义:

#define ADD(X,Y) ((X)+(Y))


指针

这是一个有难度的概念。
要谈指针就必须要讲明白内存

内存

计算机所有的程序的运行就在内存上运行,内存被划分为不同的内存单元,每个内存单元的大小是1个字节。为了有效访问内存单元,就给内存单元编了号,这些编号被称为该内存单元的地址。
这个时候需要回答两个问题:

  1. 内存是怎么编号的?
  2. 一个这样的内存单元是多大的空间?

内存怎么编号?我们有的机器是32位的,有的是64位的。32位指的是32根地址线,它是物理线,通电了之后,产生了1,0这样的信号。如果一条线上通电了,那么就表示1,不通电就是0.所以一个32位地址线产生了从0000000…到11111…的可能。这个可能性是232 个。也就是说我可以管理2的32次方个内存单元,一个内存单元是1 bit。

换句简单的话说,多少个位的机器就用2的那么多位次方。再把这个数字转换成十进制。再用这个十进制的数字除以8得到byte,再除以1024得到KB,再除以1024得到MB。。。所以32位的机器可以管理0.5G左右的内存。

一个内存单元多大?一个内存单元是一个字节。

不是很懂,但是总结下来就是,一个内存就是8个bit,也就是一个字节。
比方说我现在要存储一个int

int a = 0;

之前说了,一个int是4个字节,那也就是说,我要用四个内存单元去储存这个a。
那我如果要取a的地址怎么办?当a占有的内存是四个字节,也就是说四个内存单元的时候,取地址取的是第一个内存单元的地址。取地址的指令是:

 &a

如果我想将这个地址打印出来该怎么办?

 printf("%p",&a);

用%p来表示地址
地址它本身也是一个值,那么存放地址的地方是pa(这个只是名字),它是专门用来存放地址的。

   int * pa = &a;

而这个所谓的pa,在C语言中就叫做指针变量,这个变量的类型,如果是储存int的话,它的类型就是int*。这一个“*”说明了pa是指针变量,而int说明pa指向的对象是int类型。

所以这就是指针变量。

而取地址&就是之前漏掉没讲的一个单目操作符

指针的作用?

指针给地址,迟早是要用的。

int main()
{
    int a = 0;
   
   int * pa = &a;
     
    *pa = 20;
    
    return 0;
}

这里出现一个新的表达式*pa。 *是一个解引用操作。就是通过pa里边的地址,找到a。
这个时候再打印a,就会变成20,因为这是一个把a重新赋值的过程。把a改掉不一定要直接改a,也可以通过地址来解引用的方式来改。这个操作符 * 也是之前没讲的。

指针的作用弹幕里还有一种说法:比方说一个函数只能返回一个值,但是指针可以返回字符或者数组的地址,从而达到返回多个值的目的。

再用一句话精辟总结:指针就是地址

指针的大小是相同的。
为什么?
指针就是地址,
指针需要多大的空间,取决于地址的存储需要多大的空间
32位的电脑 32bit作为一个地址 32个bit就是4个byte(字节)
64位的电脑 64bit作为一个地址 也就是8个byte(字节)

结构体

结构体是C语言中特别重要的知识点,结构体使得C语言有能力描述复杂类型。比如描学生,学上包涵:名字+年龄+成绩。
这就要用结构体

struct stu
{
    char name[20];
    int age;
    float grade;
};


结构体可以让c语言创建新的类型出来。以上就是用struct创建出来的学生stu的类型。同样的道理可以创建很多的复杂类型。当类型创建出来之后,怎么去用呢?
结构体有一个初始化的过程:

 struct Stu s = {"张三",20,85.5};
 printf("%s %d &lf\n",s.name, s.age, s.grade);//结构体类型的名称.成员变量。

假如我要取s的地址, 用指针的方法也能打印出来,以下第一个printf和第二个printf打印的结果是一样的。

int main()
{
    struct stu s = {"张三",20,85.5};//姓名 年龄 成绩
    printf("1:%s %d %lf\n",s.name, s.age, s.grade);
    struct stu * ps = &s;
    printf("2:%s %d %lf\n", (*ps).name, (*ps).age, (*ps).grade);
    
    return 0;
}

为什么要用第二种打印方法?因为有的时候你手里拿的并不是某个结构体本身,而是它的指针罢了。
我甚至还有第三种打印方法

 printf("3:%s %d %lf\n", ps->name, ps->age, ps->grade);

这个小箭头就是之前没讲的操作符,这个箭头也叫做结构体的指针。剪头左边是结构体的位置,箭头右边是这个结构体的成员变量名。

到此为止,初识C语言的部分就已经告一段落了。

我入门了??

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值