初识C语言(2)

前言:

        本文章为初识C语言的第二节,初学者请先从第一节看起。这篇文章将简略介绍一些C语言相关知识,在后续的文章中将详细介绍相关内容。

目录

前言:

常见关键字:

#define 定义常量和宏

指针

结构体


常见关键字:

auto  break   case  char  const   continue  default  do   double else  enum
extern float  for   goto  if   int   long  register    return   short  signed
 sizeof   static struct  switch  typedef union  unsigned   void  volatile  while

        C语言中有如上诸多关键字,在本篇文章中介绍几个比较常见的。

        关键字 typedef:

                用来将类型重命名,减少代码的冗余。

//将unsigned int 重命名为uint_32, 所以uint_32也是一个类型名 
typedef unsigned int uint_32;

int main() 
{
    unsigned int num1 = 0;
    uint_32 num2 = 0;
    
    return 0;
}

                可以看到,在上述代码使用中,将unsigned int 重命名为unit_32,在后续使用中,两者        

                效果相同,num1和num2的数据类型是一样的。

        关键字static:

                ​​​​​​​1. 修饰局部变量-称为静态局部变量 

        

//代码1
#include <stdio.h> 
void test()
{
    int i = 0;
    i++;
    printf("%d ", i);
}
int main() 
{
    int i = 0;
    for(i=0; i<10; i++)
    {
        test(); 
    }
    
    return 0;
}
//代码2
#include <stdio.h> 
void test()
{
    //static修饰局部变量 
    static int i = 0;
    i++;
    printf("%d ", i);
}
int main() 
{
    int i = 0;
    for(i=0; i<10; i++)
    {
        test(); 
    }
    
    return 0; 
}

                由于局部变量是存储在栈区,因此当出了局部变量的作用范围,局部变量将自动销毁,        

                在代码一中,每次调用test函数,都和上一次调用没有任何关系,都相当于是第一次调        

                用,因此输出结果是十个一,而在代码二中,i用static进行了修饰,使i从栈区变成了静

                 态区,每一次函数结束时,i并不进行销毁,因此每一次调用test函数的效果可以进行叠

                加,输出结果是1,2,3,4,5,6,7,8,9,10。可以将这段代码理解为,代码1就

                是普通人,奇异博士将时间逆转后觉得这件事是第一次发生,因此每一次调用函数都觉

                得是第一次调用。而代码二是多玛姆,能力比普通人高,奇异博士每一次调用函数他都

                可以感知的到。

                结论:

                       static修饰局部变量改变了变量的生命周期 让静态局部变量出了作用域依然存在,

                程序结束,生命周期才结束

                2. 修饰全局变量

//代码1
//add.c
int g_val = 2018; 
//test.c
int main()
{
    printf("%d\n", g_val);

    return 0; 
}
//代码2
//add.c
static int g_val = 2018; 
//test.c
int main()
{
    printf("%d\n", g_val);

    return 0;
}

                add.c和test.c是指在编译器下创建的两个源文件,当在代码一中,add.c文件中定义        

                g_val,test.c中使用了g_val,编译器并不会报错。而代码二将会出现连接性错误。这是

                因为本来全局变量具有外部链接的属性,在别的文件中也可以调用这个变量,但是当                

                static对其进行了修饰后,切断了这种属性,从而无法在别的文件中使用。

                结论:

                        一个全局变量被static修饰,使得这个全局变量只能在本源文件内使用,不能在其

                他源文件内使用。

                3.修饰函数

//代码1
//add.c
int Add(int x, int y) 
{
    return c+y;
}
//test.c
int main()
{
    printf("%d\n", Add(2, 3));
    
    return 0;
}

//代码2
//add.c
static int Add(int x, int y) 
{
    return c+y; 
}
//test.c
int main() 
{
    printf("%d\n", Add(2, 3));
    
    return 0; 
}

                和修饰全局变量的性质相同,本来函数也具有外部链接属性,但是当static对其进行修

                饰后,切断了这种属性,因此代码二在运行过程中也会出现连接性错误。

                结论:

                        一个函数被static修饰,使得这个函数只能在本源文件内使用,不能在其他源文件                

                内使用。

#define 定义常量和宏

//define定义标识符常量 
#define MAX 1000

//define定义宏
#define ADD(x, y) ((x)+(y))

#include <stdio.h>
int main() 
{
    int sum = ADD(2, 3);
    printf("sum = %d\n", sum);
    sum = 10*ADD(2, 3);
    printf("sum = %d\n", sum);

    return 0; 
}

        #define定义的常量

                意味着,将MAX赋值成了1000,在今后的程序中但凡见到了MAX,将自

        动将其替换成1000进行使用,在编译阶段的预编译中也是直接将有MAX的地方直接替换成

        了1000。

        #define定义宏 

                和函数的使用方法相类似,main函数中调用的宏中的2,3将传到ADD宏中的x和y的位

                置,最后将宏后面的一系列运算完成后将值传回来。值得注意的是,由于x和y是直接传

                过来的,因此如果在主函数中调用的时候有操作符,可能与宏中的操作符的优先顺序相

                ,最后得到的结果并不是想要的,因此在宏的使用中要多加(),防止出现类似情

                况。 

指针

        内存

                ​​​​​​内存是电脑上特别重要的存储器,计算机中程序的运行都是在内存中进行的 。

       所以为了有效的使用内存,就把内存划分成一个个小的内存单元。

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

       单元的地址,由于这个数字很大,因此采用16进制进行存储

                类似于现实社会中,如果要找到一个人的住址,如果是按照单元楼去找,那么范围太

        大,如果是按照每个房间的每一平方米去找,那么范围太小,因此每个内存单元如果是比特

        的话将范围太小,mb的话范围太大,于是每个内存单元的大小是字节

                32位机器中,每一位可以是0或1,因此可以访问2的32次方字节,也就是4gb。

#include <stdio.h>
int main() 
{
    int num = 10;
    &num;
    //取出num的地址 
    //注:这里num的4个字节,每个字节都有地址,取出的是第一个字节的地址(较小的地址)         
    
    printf("%p\n", &num);
    //打印地址,%p是以地址的形式打印

    return 0;
}

             上述代码是用来查看一个变量的存储地址的。

             那么用什么变量来存储地址呢,因此C语言中引用了指针的概念。

#include <stdio.h>
int main() 
{
    int num = 10;
    int *p = &num;
    *p = 20;
    
    return 0;
}

        这里的p就是一个指针。在定义时用int*进行定义,如果是存储别的数据类型,那么就用别的

        数据类型加*进行定义,在使用这个地址时,运用*,这个符号名为解引用操作符,在指针前

        面加上这个操作符后,可以访问p存储的地址里面的内容,也就是*p相当于num。

#include <stdio.h>
int main() 
{
    char ch = 'w';
    char* pc = &ch;
    *pc = 'q';
    printf("%c\n", ch);
    
    return 0;
}

        上述代码是char类型的指针实例。

        指针变量的大小

#include <stdio.h>
//指针变量的大小取决于地址的大小 
//32位平台下地址是32个bit位(即4个字节) 
//64位平台下地址是64个bit位(即8个字节)
int main() 
{
    printf("%d\n", sizeof(char *));
    printf("%d\n", sizeof(short *));
    printf("%d\n", sizeof(int *));
    printf("%d\n", sizeof(double *));
    
    return 0;
}

                可以看到,指针的大小和其指向的数据类型并没有任何的关系,决定指针大小的是机器        

        的位数,32位机器下指针的大小是4个字节,64位机器下指针的大小是8个字节。

结构体

                当我们需要描述一个复杂对象时,如果需要的数据类型相同,我们可以用数组进行存

        储,如果需要不同的数据类型时,采用结构体进行定义。

struct Stu 
{
    char name[20];//名字 
    int age; //年龄 
    char sex[5]; //性别 
    char id[15]; //学号
};

        这里的struct,相当于int,float...是一个数据类型的关键字。

//打印结构体信息
struct Stu s = {"张三", 20, "男", "20180101"};
//.为结构成员访问操作符
printf("name = %s age = %d sex = %s id = %s\n", s.name, s.age, s.sex, s.id); 
//->操作符
struct Stu *ps = &s;
printf("name = %s age = %d sex = %s id = %s\n", ps->name, ps->age, ps->sex, ps- >id);

        在结构体中访问结构体内部成员时,利用.进行访问,采用下面这种形式

                结构体变量名.结构体内部变量名

        当我们使用结构体指针时如果采用(*s).name这种访问形式的话代码过于冗余,因此采用

        下面这种形式。

                结构体指针->结构体内部变量名

        初识c语言的章节就此告一段落,在这两篇文章中简略的讲了一些C语言的常见知识点,从下一篇文章开始,将持续更新C语言的一些详细的知识介绍。

  • 8
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值