首页 > 其他分享 >初识C语言

初识C语言

时间:2023-06-10 11:37:53浏览次数:44  
标签:10 return 变量 int C语言 初识 printf main

      通过对C语言的基础知识的简单介绍,对C语言有大概的了解

1.什么是C语言

       首先我们常说的语言是人与人交流的方式,而C语言是人与计算机交流的一种计算机语言

人----------------------人               人------------------计算机

   汉语,英语,法语...                     C/C++、Java、python...

       操作系统之上称为上层软件,操作系统及以下称为下层/底层,C语言擅长于底层开发(也可以写应用软件)。

初识C语言_C语言

                                                    图1 电脑的构成 

计算机语言的发展:低级----------------->高级

二进制指令-->汇编指令(助记符)-->B语言-->C语言

1000110010010001        ADD                          高级语言                                


统一C语言

C语言的国际标准:ANSI C           C89/C90国际标准(用的多)  C99 C11(不流行) 


常用编译器

Clang, GCC, WIN-TC, MSVC, Turbo C

(编译:源文件通过编译链接变成可执行文件的处理过程   编译器:用来编译C代码的工具)


2.第一个C语言程序

软件  Visual Studio       官网下载链接

1.创建项目

(视图—>解决方案资源管理器)

初识C语言_C语言_02

初识C语言_C语言_03

初识C语言_C语言_04

2.创建源文件

(.c 源文件 .h 头文件)

后缀名:.cpp 编译器会按照c++语法来编译代码   

             .c编译器会按照C的语法编译代码

初识C语言_C语言_05

初识C语言_C语言_06

3.写代码

      C语言代码中必须包含主函数(main函数),main函数是程序的入口,有且只有一个main函数。

标准的主函数写法

int main()           //int 整型类型,表示main函数   
{
    return 0;       //返回0,0是整数与前面int呼应
                    // C语言中约定习惯:
                    //程序正常运行,返回0,程序异常中止,返回1
}

古老的主函数写法(不流行不推荐用)

void main()
{
    return 0;
}

第一个C语言程序

#include <stdio.h> //std标准 i输入 o输出 
                   //stdio.h包含了用于输入和输出的函数
                   //printf和scanf函数都是在stdio.h头文件中声明的
 
int main()
{
    printf("hello world\n");//print fouction 
                            //输出函数(库函数,调用得声明)
    return 0;               
}

4.运行

快捷键:Ctrl+F5/Fn+Ctrl+F5 

3.数据类型

数据类型

名称

占内存大小

能存储数据个数

char

字符型

1byte

28

short

短整型

2byte

216

int 

整型

4byte

232

long

长整型

4/8byte

232/264

long long

更长的整型

8byte

264

float

单精度浮点型

4byte

232

double

双精度浮点型

8byte

264

注意:

  1. 浮点即小数,单精度和双精度是浮点数的表示方法,主要区别在于它们所占用的存储空间和可以表示的数值范围。
  2. sizeof(char)返回一个字符型数据在内存中所占空间大小,sizeof 是 C 语言中的操作符,用于获取变量或数据类型所占用的内存字节数,输出结果最好使用 %zu 。 
  3. bit 比特位 存放一个二进制数(0/1)  byte 字节    1byte=8bit
  4. byte  KB  MB GB TB  PB 
  5. 1KB=1024byte 1MB=1024KB 1GB=1024MB 1TB=1024GB 1PB=1024TB
  6. C语言规定:sizeof(long)>=sizeof(int)
  7. 精度要求高用double
  8. 数据类型通过给名字去创建变量,创建变量的本质就是向内存申请空间(存放数据)

4.变量和常量

变量

描述变化的量,创建变量后就会占内存空间。

变量的分类

全局变量:定义在代码块({ })之外的变量。

局部变量:定义在代码块({ })内部定义的变量。

#include <stdio.h>
int a = 100;                   //全局变量
int main()
{
    int a = 10;               //局部变量
    printf("a=%d\n", a);
    return 0;
}

注意:

  1. 当局部变量和全局变量的名字相同下,局部变量优先。
  2. 建议局部变量和全局变量名字不要相同。

变量的使用

// 计算2个整数的和
#include <stdio.h>                    
int main()
{
    int num1 = 0;
    int num2 = 0;         
    int sum = 0;                  //初始化(不初始化,默认放随机值)
    scanf("%d %d", &num1, &num2); //scanf输入函数 &取地址
    printf("sum=%d\n", num1 + num2);
    return 0;
}

注意:在VS中变量定义不在最前面时,会报错,此处可在程序第一行放上:

#define _CRT_SECURE_NO_WARNINGS

此处一劳永逸的做法是:

      找到 newc++file.cpp文件,直接将那句话放进去。可以复制粘贴文件到桌面,改完之后直接替换掉原文件。

变量的作用域和生命周期

变量

作用域(哪里可用)

生命周期

全局变量

整个工程

整个程序

局部变量

变量所在局部范围

进作用域开始,出作用域则结束

变量的作用域

局部变量:

#include <stdio.h>

int main()
{

    {
        int a = 10;
        printf("a=%d\n", a); //局部变量的作用域
                             //可简单理解为将局部变量包含起来
                             //最近的两个{}的范围
    }
//    printf("a=%d\n", a);  //此处未注释掉会出现a未定义的报错
                            //即不在局部变量的作用域内
    return 0;               //出了作用域a已经被销毁(即生命周期结束)
    
  
}
#include <stdio.h>

int main()
{
    int a = 10;            //此处局部变量的作用域为外面{}的范围
                           //两个都能正常输出
    {
        printf("a=%d\n", a);
    }
    printf("a=%d\n", a);
    return 0;
}

全局变量

初识C语言_C语言_07

     此处用extern声明引用另外一个源文件的全局变量a,可以正常输出三个a,充分说明全局变量是整个工程可用的。

常量

描述不变的量,在程序中不允许修改,常量未使用前不占内存空间

常量种类:

字面常量     eg:30 3.14 'q' "adf"

const修饰的常变量    const int n=10 

注意:在C语言中,const修饰的n本质是变量,但是不能被修改,有了常量的属性。

#include <stdio.h>
//const修饰的常变量本质还是变量,定义数组时[]内需要一个常量
//运行后此程序在VS中跑不起来,提示代码出错
//充分说明了const修饰的常变量还是变量
int main()
{
    const int n = 10;
    int arr[n] = {0};
    return 0;
}

#define定义的标识符常量

#include <stdio.h>
#define MAX 100
#define STR "abcdef"//#define定义的常量类型不定,可以是整型,字符串型...
int main()
{
    printf("%d\n", MAX);     //直接打印显示
    int a = MAX;             //拿来做赋值使用       
    printf("%d\n", a);      
    printf("%s\n", STR);
    MAX = 20; //不注释这一行会报错,即#define定义的标识符常量不可修改
    return 0;
}


枚举常量:一一列举的常量,不能修改

#include <stdio.h>
//颜色
enum Color
{
    //枚举常量
    RED,
    GREEN,
    BLUE
};
//性别
enum Sex
{
    //枚举常量
    MALE,
    FEMALE,
    SECRET
};

int main()
{
    int num = 10;
    enum Color c = RED;
    RED = 20;
    MALE = 10;
    return 0;
}

注意:一般#define定义的符号常量和枚举常量都会大写。

小结:创建变量就开辟一块空间,常量可以存进变量的空间里,const修饰的常变量是被限定了不能修改常量值的一块空间,本质还是变量。

5.字符串+转义字符+注释

字符:双引号引起来的一串字符(即字符串字面值),结束标志为\0

       我们敲出来的字符: #qwers  ,在C语言中可以用char(字符类型)来描述字符,用单引号描述字符常量(eg 'a'),我们还可以创建一个字符变量将字符常量存起来char ch = 'w'。

      字符串(双引号引起来的一串字符)eg “abcdef” 由于C语言中没有字符串类型,所以存储字符串要通过定义字符型数组。eg char arr[ ]=“abcdef”

 注意:

  1. 不知道后面多少字符[]可以不写数字只填写字符串内容,会根据字符串内容自动确定需要多大空间
  2. 要在[]中填入数字一定要保证足够后面的字符存入

 如何看数组里面实际存放的内容?

       运行后按住F10调试,再打开调试窗口观察数组的内容

初识C语言_C语言_08

初识C语言_C语言_09

注意:发现数组里面多了一个我们没有写的字符 \0(字符串结束标志),字符串末尾隐藏放一个\0,初始化数组时,“abcdef” 6个字符需要7个字符空间存储。

#include <stdio.h>
#include <string.h>
int main()
{
    char arr1[] = "abcdef";                      //形式上的差异
    char arr2[] = {'a', 'b', 'c', 'd', 'e', 'f'};//arr2中从下图
                                                 //可以看出没有\0
                           //\0的重要些                      
    printf("%s\n", arr1);  //从下图可以看出arr2与arr1的使用上的差异
    printf("%s\n", arr2);  //打印字符串时遇到字符串结束标志(\0)才结束
                           //由于arr2中没有\0(结束标志)
                           //他会持续往后在内存中找
                           //直到在内存某位置找到\0才能停下来
                           //当在arr2中主动放一个\0
                           //就可以实现arr1的打印效果
    
    int len = strlen("abc"); //求字符串长度的库函数string length 
                             //要加上头文件string.h声明
                             //使用:strlen(arr1) 
                             //定义一个int变量接收函数返回值
                              
    printf("%d\n", len);      //3  strlen在数字符串长度时也看\0
                              //   数到\0就不数了,数出字符个数不包括\0
                              //   \0只是结束标志,数字符串长度不包含它
                              
    printf("%d\n", strlen(arr1)); //6 计算字符串长度时不数\0   
    printf("%d\n", strlen(arr2)); //随机值(eg:22)没有\0一直往后数
                                  //直到找到\0,计数结束
                                  //如果在arr2中放入\0,输出就是6
    return 0;
}

初识C语言_C语言_10

初识C语言_C语言_11

注意:

  1. 求字符串长度时:找\0 前出现有多少个字符。
  2. 遇到\0不能打印后面内容,后面即使有字符也不打印了,遇到字符串结束标志就认为字符串打印结束了。
  3. 充分理解\0的重要性。
  4. 0 数字0 数值是0 ; '0' 字符0 ASCII值是48 ; '\0' 字符(结束标志) ASCII值是0;
  5. EOF 文件的结束标志(end of file)值是-1(右击鼠标速览定义查看)

转义字符

转变原来字符的意思(不会打印出来)

\n 换行(从普通字符n变成换行的意思)

初识C语言_C语言_12

\0 字符串结束标志(从普通数字0变成字符串结束标志)

初识C语言_C语言_13

    

注意:转义字符不是什么都能转义,C语言规定了一些转义字符

初识C语言_C语言_14

注意:

1.C语言中三字母词:??)-->  ]    ??(-->  [  防止被解析为三字母词?前加个\ 

eg   printf("%s\n","(are you ok\?\?)"); 

//  如果?前不加\一些支持三字母词的编译器会输出   (are you ok]

2.%d -打印整型    %c -打印字符   %s -打印字符串   %f -打印float类型的数据

%lf -打印double类型的数据    %zu  打印sizeof的返回值

eg printf("%c\n",'');  //err  打印单引号字符不能直接放进单引号中,因为前面那个单引号会和中间那个单引号形成一对,最后那个单引号落单了。' 前面加\ 后就可以正常打印输出(双引号同理)

3.字符串打印:

printf("%s\n","abcdef");

printf("abcdef");  //打印字符串的简写形式(只有字符串可以这样简写,整型是不可以这样打印)

printf("A");   //此处A变成一个字符串,有结束标志,与字符A不同。字符A占1个字符空间,而字符串A占2个字符空间。

4.\\

printf(“abcd\0ef”);    //输出:abcd  (\0 被编译器认为是结束标志)但是我想打印出普通字符\和0,而不是当做结束标志用

printf(“abcd\\0ef”);    //输出:abcd\0ef (在\前加上\,转变\意思,让\与0不能组成转义字符,让\从转义字符中\变成普通\

5.\t

printf("c:\test\test.c");  //在\前加上\,让\从制表符中的\变成普通字符\

初识C语言_C语言_15

6.\n换行 \r回车

7.\ddd 八进制数

printf("%c\n",'\130');  //   \130为一个字符  意思是将八进制130转换成十进制的数字作为ASCII码值代表的字符     十进制:1*82+3*81+0*80=88  ASCII码代表的字符:X     输出:X

ASCII编码:字符难以存入(不好存为二进制),给字符编号,将编号存进去即可(用编号将字符用二进制形式储存)

初识C语言_C语言_16

8.\xdd 十六进制数

printf("%c\n",'\x60'); // x60为一个字符,意思是将十六进制x60转变成十进制数作为ASCII值代表的字符   十进制:6*161+0*160=96      ASCII码代表的字符:‘      输出:‘

转换出的十进制保证在0-127 不能超出范围,否则没有意义

\x063编译器也是支持的 与\x63等价 两位三位都可以,但是转换成十进制不能超出ASCII码值范围(0-127)

9.转义字符整体是一个字符

例题:

printf("%d\n",strlen("qwer t")); //输出  6  (数\0之前的所有字符,空格也是一个字符)

printf("%d\n",strlen("c:\test\628\test.c"));//输出  14

     转义字符整体看为一个字符,其中的\62可以整体看为一个转义字符,而不是\628,因为八进制数字是由0~7组成。要注意的是\t的效果是水平空四个格子,但是数字符串长度不是看输出的效果,就看当前字符串即可。根据下面的分析,\628看成十六进制超出ASCII码值范围,没有意义,不再是转义字符,只有看成八进制才可以看作转义字符。

根据ASCII码值范围0~127

对应的八进制范围是000~177           1*82+7*81+7*80=127   

对应的十六进制范围是00~7F               7*161+F*160=127

初识C语言_C语言_17

整数部分进制转换

十进制转换为N进制方法:除以N,反向取余数,直到商为0终止

N进制转换为十进制方法:按权相加                (注意此处不考虑小数部分)

注释:注解解释(注释不要的代码,解释代码)

C语言的注释风格:/*...*/   

  • 一次可以多行注释       
  • 缺陷:不支持嵌套注释,更建议用C++的注释风格

C++的注释风格://       

  • 手动注释需要一行一行注释,单行注释   
  • VS中快捷键可以快速选中多行注释 Ctrl+K+C
  • 取消多行注释 Ctrl+K+U

注释的好处:

  1. 梳理思路
  2. 对复杂的代码进行解释,容易上手,代码可读性高

注意:补充一个快捷键知识点:shift+方向键(上下左右)可以选中某区块

6.选择语句

C语言实现选择/分支:

  if else        Switch

#include <stdio.h>

int main()
{
    int input = 0;
    printf("要好好学习吗(1/0)?\n");
    scanf("%d\n", &input);
    if (input == 1)         //表达式为真执行
    {
        printf("好offer\n");
    }

    else                   //表达式为假执行
    {
        printf("卖红薯\n"); 
    }

    return 0;
}

7.循环语句

三种形式:while      for      do...while

#include <stdio.h>           
int main(void)
{
    int i = 1;
    int sum = 0;
    while (i <= 100)
    {
        sum = sum + i;
        ++i;
    }
    printf("sum = %d\n", sum);
    return 0;
}

C语言是结构化的程序设计语言

三种结构:顺序结构      选择结构       循坏结构


8.函数

简化代码,代码复用(函数有输入有输出)

#include <stdio.h>  
int Add(int x, int y)  // add函数名   x,y函数参数   int返回类型
{
    int z = 0;        //函数体({ }中)
    z = x + y;         
    return z;        //return (x+y);函数体中就写这一行即可,简化代码
}                    
int main()         
{
    int n1 = 0;
    int n2 = 0;
    scanf("%d %d", &n1, &n2);
    int sum = Add(n1, n2); //函数写好之后可以反复调用
    printf("%d\n", sum);   
    return 0;
}

9.数组

存单个数据:int a=1;(创建变量存储单个数字)(存放一个整型向内存申请4bytes)  

存储一组数据(创建数组  数组:一组相同类型的元素的集合):int arr[10]={10,11,12,13,14,15,16,17,18,19};(多个元素用{ },存放10个整型向内存申请40bytes,数组在内存中都有一个序号,即数组的下标)

数组的下标:下标是从0开始的,通过下标访问元素  eg arr[8]=18

数组的使用:通过下标来访问元素

#include <stdio.h>
int main()
{
    int arr[10] = {10, 11, 12, 13, 14, 15, 16, 17, 18, 19};
    printf("%d\n", arr[8]); //打印输出一个数字
    int i = 0;
    while (i < 10) //打印输出整个数组(循坏方式产生下标)
    {
        printf("%d\n", arr[i]);
        i++;
    }
    return 0;
}

注意:

  1. 数组初始化:int arr[10];    //10个元素,不给数组初始化必须指定数组大小  int arr[]={1,2,3}; //3个元素,不指定数组大小必须初始化,根据初始化内容确定数组大小。
  2. 例题:printf(“%d\n”,strlen("c:\test\121"));   //  7
  3. char arr[]={'b','i','t'}; printf("%d\n",strlen(arr)); //输出结果为随机值,数组只放了三个字符,strlen函数数到\0就不数了,数出字符个数不包括\0,但是此数组中没有\0,所以strlen会一直在内存中找,直到找到\0为止因此输出结果为随机数。改进方案:char arr[4]={'b','i','t'};//输出结果为3 ,数组能放4个元素,初始化时却只放了三个元素,剩下的一个空间默认初始化为0(不完全初始化,剩余部分默认初始化为0),/0的ASCII值为0,数字0的数值为0(ASCII值为0),数字0和\0本质上没有区别,放0会被解析为\0,所以有了\0,就能输出3
  4. int arr[10]={0};

初识C语言_C语言_18

int arr[10]={1};

初识C语言_C语言_19

  1. 数组创建错误示例:int n=10; int arr[n]={0}; //err 在不支持C99编译器下,[]内需要常量,而n即使初始化也还是变量;即使在能支持C99的编译器下,也不能对数组初始化,所以怎么看都是错的。 C99标准之前的数组大小都是用常量或者常量表达式来指定的。 eg int arr[10]={0};  int arr[4+6]={1,2,3,4}; C99标准之后,支持了变长数组,允许数组大小是变量,但是这种指定方式的数组不能初始化 eg int m=100; int arr[m];(支持C99的编译器也不能在后面初始化)      VS对C99一些语法支持不是很好,不支持变长数组       
  2. 字符串数组要算上\0所占内存空间,因此数组分配空间是字符串所占空间加上\0所占的空间。


10.操作符

C语言提供了非常丰富的操作符,使用比较灵活

算数操作符:+ -  *  /  %(取模)                                                                  注意:                                                                                                  1.  /除号得到的是商,不关心余数   %取模得到的是余数,不关注商                2. 除号的两端是整数时,执行整数除法;两端只要有一个浮点数就执行浮点数除法。eg printf("%d\n",7/2);//输出3    printf("%.1f\n",7/2.0);//输出3.5 (%.1f 小数点后保留1位,%f小数点后保留6位)                                                3. 取模操作符的两个操作数只能是整数,不能是其他数字                                                                                                                                              移位操作符:>>向右移位符   <<向左移位符(涉及二进制运算)

位操作符:&与   ^异或    |或

赋值操作符:= 赋值  +=  -=   *=   /=    &=  ^=  |=   >>=     <<=            注意:                                                                                                    1. int  a=0;  //初始化(在创建变量的同时给它一个值)a=20;//赋值(已经有变量之后给它一个值)                                                                              2.a=a+3;  //简化:a+=3     a=a-3;  //简化:a-=3                                     

单目操作符(只有一个操作数的操作符):!- +  &  sizeof     ~    --    ++      *     (类型)                                                                                         注意:                                                                                                          1.C语言中,0表示假,非0表示真                                                                2.!逻辑反操作(真变成假,假变成真)-负号 +正号 &取地址                      3.sizeof是单目操作符,不是函数         

#include <stdio.h>
int main()                        //sizeof计算变量大小
{ 
    int a = 10;
    printf("%d\n", sizeof(a));   //输出都是4
    printf("%d\n", sizeof(int)); // sizeof可以直接跟变量
                                 //或者这个变量对应的类型
    printf("%d\n", sizeof a);    //输出为4,sizeof不是函数
                                 //可以不加括号,函数()不能省
    printf("%d\n", sizeof int);  // err 虽然sizeof是操作符
                                 //但是语法不支持int不加()
                                 //对于类型来说,还是得加上()
    return 0;
}

#include <stdio.h>
int main()
{
    int arr[10] = {0};
    printf("%d\n", sizeof(arr)); // sizeof计算数组大小
                                 //输出值为40,计算的是整个数组的大小
                                 //单位是字节(这里是整型数组不要考虑\0)
    printf("%d\n", sizeof(arr[0])); //输出值为4,计算一个元素大小
                                    //一个int大小
    printf("%d\n", sizeof(arr) / sizeof(arr[0])); //输出值是10 
                                                  //数组的元素个数
    return 0;
}
  1. ++ --
#include <stdio.h>
int main()
{
    int a = 10;
    int b = a++;       //后置++,先使用后++
                       // int b=a; a=a+1;
    printf("%d\n", b); // 10
    printf("%d\n", a); // 11
    
    int c = 10;
    int d = ++c;       //前置++,先++后使用
                       // c=c+1; int d=c;
    printf("%d\n", d); // 11
    printf("%d\n", c); // 11

    return 0;
}

 5. (类型) 强制类型转换 

#include<stdio.h>
int main()
{
int a=(int)3.14;//3.14 字面浮点数,编译器默认为double型
                //在前面加(int),将3.14强制类型转换为整型,只要整数部分
printf("%d\n",a);//输出3
return 0;
}

                                                         

关系操作符 : >  >=  <  <=  !=(判断不相等)  ==(判断相等)       

#include <stdio.h>
int main()
{
    int a = 10;
    if (a = 3)    //a=3是赋值不是判断 修改为a==3 才不打印输出
    {
        printf("hehe\n");
    }

    return 0;
}

逻辑操作符:&&逻辑与   并且              ||    逻辑或   或者

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    if (a && b) // a和b都为真执行语句打印输出hehe
                // a=0(假) b=20(真);a=10 b=0;a=b=0
                //以上三种都不执行语句
    {
        printf("hehe\n");
    }
    if (a || b) // a或者b其中一个为真执行语句
                // a=b=0不执行语句
    {
        printf("lala\n");
    }
    return 0;
}

条件操作符:exp1 ? exp2:exp3  三目操作符(有三个操作数)操作数:exp1   exp2  exp3  操作符:?: exp1为真,只计算exp2,整个表达式结果是exp2 的结果;exp1为假,只计算exp3,整个表达式结果是exp3 的结果

#include <stdio.h>
int main()
{ //求出a,b间较大值
    int a = 10;
    int b = 20;
    int r = a > b ? a : b;
    printf("%d\n", r); //输出:20
    return 0;
}

逗号表达式 exp1,exp2,exp3,...expN 由逗号隔开的一串表达式 特点:从左到右依次计算,整个表达式结果是最后一个exp的结果

#include <stdio.h>
int main()
{
    int a = 10;
    int b = 20;
    int c = 0;
    int d = (c = a - 2, a = b + c, c - 3); // c=8 a=28 c-3=5
                                           //表达式结果为
                                          //最后一个exp结果:5
    printf("%d\n", d);// 5
    return 0;
}

下标引用、函数调用和结构成员操作符

下标引用操作符[ ] 访问数组元素时必须用下标

#include <stdio.h>
int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};//这里的[]不是下标引用操作符
                                                  //定义数组的一种形式,而不是操作符
                                                  //定义数组时在不支持C99的编译器下
                                                  //[]中不能有变量
    printf("%d\n", arr[3]);//访问第四个元素
                           //这里的[]就是下标引用操作符
                           //内部放的是下标
                           //arr和3就是[]的操作数
    int n = 4;             //当[]作为下标引用符访问元素时可以有变量
    printf("%d\n", arr[n]);
    return 0;
}

函数调用操作符( )

#include <stdio.h>
int add(int x, int y)
{
   return (x+y);
}
int main()
{
    int sum = add(2, 3);//这里的()就是函数调用操作符
                        //操作数:add,2,3
    printf("%d\n", sum);
    return 0;
}

注意:()不能省略掉

结构成员操作符:.  ->

结构体变量访问结构体成员用.操作符;指针变量访问指针所指向结构体成员用->操作符。


11.常见关键字

C语言本身内置的,关键字不是自己创建的,也不能自己创建

auto 自动  一般省略 所有局部变量前面都有auto                                          eg auto int a=10 (a变量进作用域自动创建,出自动销毁,属于自动变量,本质上定义局部变量前都有一个auto,实际上所有的局部变量都是auto类型的,所以将auto省略)自动变量 

break  跳出循坏 

常见关键字

循环关键字

分支关键字

类型关键字

未分类关键字

for

switch case 

default

char

const 修饰变量              常属性

while

if else

short int long

longlong

extern声明外部符号

do while

goto实现跳转与分支很像

float double

register 寄存器

限制变量存在寄存器

break


signed 有符号的

unsigned 无符号的

static静态的

修饰函数和变量

限制变量存在静态区

continue


sizeof计算大小(与类型有关)

volatile



自定义类型

enum枚举

struct结构体

union联合体(共用体)

return函数返回值



typedef类型重命名




void无(函数的返回类型,函数参数类型)


注意:

  1. 变量名命名(有意义  字母数字下划线组成不能有特殊字符,不能以数字开头)
  2. 变量的名字不能是关键字(定义变量名不能与关键词冲突)

关键词typedef和static

typedef 类型定义(类型重命名),为类型重定义

#include <stdio.h>
typedef unsigned int uint; //简化复杂类型名,重新命名uint

/*struct Node
{
   int data;
   struct Node* next;
};                    //结构体类型  */
typedef struct Node
{
    int data;
    struct Node *next;
} Node; //结构体类型

int main()
{
    unsigned int num = 0; //使用类型时不方便
    uint num2 = 1;        //创建变量的类型与上面的类型一致
                          // unsigned int与uint两者等价
    // struct Node n;     //创建结构体类型变量不方便
    Node n2; //简化后
    return 0;
}

static  静态的  作用:修饰变量和修饰函数

修饰变量(静态变量)

局部变量 

#include <stdio.h>
void test()
{
    int a = 1;          //普通局部变量
    a++;                //进作用域创建,出作用域销毁
    printf("%d\n", a);  //函数调用完a就销毁了
}                       //第二次进入test函数a重新创建并赋值1
                        //每次调用test时变量a都重新创建,不会相互影响
int main()
{
    int i = 0;
    while (i < 10)       //循环10次输出10个2
    {                    
        test();   
        i++;
    }
    return 0;
}
#include <stdio.h>
void test()
{
    static int a = 1; //static修饰的变量a出作用域不会销毁
                      //此时称为静态变量(放在静态区)
    a++;
    printf("%d\n", a);
}
int main()
{
    int i = 0;
    while (i < 10)   //循环10次,输出2~11
    {
        test();
        i++;
    }
    return 0;
}

注意

  1. static修饰局部变量的时候,局部变量出了作用域,不销毁,本质上,修饰局部变量时,改变了变量的存储位置,影响了变量的生命周期,生命周期变长(和程序的生命周期一样)
  2. C中内存划分:栈区,堆区,静态区
  3. 栈区(存放局部变量...):进作用域创建,出作用域销毁(栈区数据特点)
  4. 静态区(静态变量):出作用域不销毁,程序生命周期结束时销毁(静态区数据特点)
  5. 用类型定义变量(创建变量)本质就是分配空间(变量在编译期间分配空间,不需要代码执行过程中重新开辟空间来创建它 eg:全局变量,静态变量),普通局部变量是放在栈区,出作用域就会销毁,所以每次都会重新分配一次空间,而用static修饰的局部变量是放在静态区,出作用域不销毁,所以不需要重新分配空间,所以即使每次进入循环时都会有重新定义的语句,但是并不会起作用,只会执行a++。
  6. void 不需要任何返回(无return语句)

全局变量

初识C语言_C语言_20

普通全局变量运行后结果为:2020

初识C语言_C语言_21

static修饰的全局变量运行报错

注意:

  1. 调用一个定义在其他文件的普通全局变量,要用extern进行声明外部符号,而且这两个文件必须在同一个项目下
  2. 全局变量具有外部链接属性(外部源文件的全局变量通过链接手段被其他源文件使用),static修饰全局变量的时候,这个全局变量的外部链接属性就变成了内部链接属性(只能在当前的源文件中使用),其他源文件(.c)就不能使用这个全局变量了。(全局变量存储位置也在静态区)
  3. 在使用时,感觉static修饰的全局变量作用域不再是整个工程而是当前源文件中。 作用域变小的本质是全局变量的外部链接属性变成了内部链接属性。

修饰函数

初识C语言_C语言_22

普通函数运行输出:30

初识C语言_C语言_23

static修饰的函数运行报错(链接属性导致的,static修饰使函数从外部链接属性变成了内部链接属性)

注意:

函数是具有外部链接属性,被static修饰时函数的外部链接属性变成了内部链接属性,其他源文件就无法使用了。

register   寄存器   

电脑存储设备:硬盘-->内存-->高速缓存(cache)-->寄存器(集成到CPU)           访问速度:慢———————————————>快                                     空间大造价低———————————————>空间小造价高

CPU处理速度特别快,内存的速度跟不上,为了提高处理效率,出现了高速缓存和寄存器。保证大部分数据在寄存器中,提高处理的速度。

#include <stdio.h>
int main()
{                         //寄存器变量
    register int num = 3; //建议3存放在寄存器中,决定不了
                          //最终还是编译器决定
    return 0;
}

寄存器访问速度快 但是只是建议编译器怎么做(寄存器空间太小了),一般编译器都会自己主动将常用数据放进去


12.#define定义常量和宏

定义标识符常量:赋值使用或者直接输出。

#include <stdio.h>
#define NUM 100
int main()
{
    printf("%d\n", NUM); //直接打印
    int n = NUM;
    printf("%d\n", NUM); //赋值使用再打印
    int arr[NUM] = {0};  //定义数组时
                         //用#define定义的常量确定数组大小
    return 0;
}

定义宏:有参数,宏是完成替换的

#include <stdio.h>
#define ADD(x, y) ((x) + (y)) // 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); //与函数用法相似 定义方法有差异
                       //宏调用是完成替换宏体
                       //((x)+(y)——>((a)+(b))
                       //编译器处理后:int c=((a)+(b))
    print("%d\n", c);
    return 0;
}

13.指针

内存:存储器,计算机的程序运行(内存是程序运行的环境和空间)都是在内存中完成的

如何有效管理和使用?

内存会划分为一个个小的内存单元(每个内存单元都是一个字节大小)每个内存单元都有一个编号  类比生活中将大空间划分一个个房间,给房间编号(编号相当于地址)

一个内存单元是一个字节,可以对应哪些关系呢?

32位电脑                                                   由下面分析计算可得最大内存4G

       电脑访问内存空间要生成地址(通过地址线生成地址),32位电脑有32根地址线,计算机中的信息是通过电信号形式传播,电信号只有两种状态,即开或关(高电平或低电平),也就是1或0,所以计算机中采用二进制,地址线的设计是基于二进制的,因此一根地址线只有0/1两种状态                                         32根地址线,根据0/1状态不同的排列,一共232种的32位二进制序列的状态,每个二进制序列对应一个数字(即编号),可以作为内存的编号存在。一个地址(编号)管理一个内存单元(1byte大小),232个地址序列最多可以管理232byte的空间,通过二进制换算成10进制位为4G。(为了方便书写可以将二进制换成16进制表示)

64位电脑                                                         最大内存8G 16G 32G

为什么一个内存单元不是一个比特位?    bit不合理  太精细化  没有必要         eg: char c;//创建一个变量c,需要一个字节(8个bit),如果最小内存单元设置为一个比特位,那么创建一个字符型变量c就需要占8bit(8个内存空间),每个空间都有一个地址,仅仅一个字符变量就有8个地址,浪费地址数,太精细化,没有必要。

为什么要讲内存?创建变量本质就是在内存申请空间

#include <stdio.h>
int main()
{
    int a = 10; //向内存申请4个字节存储10
                // a的地址是这四个字节中第一个字节的地址
    &a;         //取地址操作符

    printf("%p\n", &a); //%p以地址格式打印数据,打印的就是地址
    return 0;           //0x0012ff48   
}

如何查看变量a的地址?

①先开始调试,再通过调试窗口的监视可以查看a的地址

初识C语言_C语言_24

②先开始调试才能在内存窗口查看a的地址

初识C语言_C语言_25

在内存窗口中输入&a回车

初识C语言_C语言_26

地址框中出现的就是变量a的地址

初识C语言_C语言_27

为了方便观察可以将列调整为4(每两个十六进制数为一个字节,4列共有4个字节,此处观察的整型变量a就是占4个字节)

初识C语言_C语言_28

地址   内存中的数据   内存数据的文本解析(不准确的)   (与上图对应区域说明)

a=10在内存中怎么存放的数据是00 00 00 0a而不是10?

10是十进制的     十六进制0~9 a~f     十进制10转换为十六进制数:a ,又因为10是存在整型变量中的,所以会像内存申请4个字节,4个字节就是32bit,所以10写到内存中要写32个比特位(二进制位0/1)如下:                             十进制10:10

 二进制10: 0000 0000 0000 0000 0000 0000 0000 1010(位数根据占内存空间确定)(每4个二进制位代表一个十六进制 因为4位二进制能表示16种状态)

十六进制10:0 0 0 0 0 0 0  a  (一个十六进制位代表4个bit,我们常常将两个十六进制位写在一起代表一个字节)

10的十六进制表示:0x 00 00 00 0a (存到内存时倒着看数据)

注意:

  1. 当变量占多个字节(每个字节都有编号/地址),该变量地址是第一个字节的地址。
  2. 这里的a是局部变量,每次运行程序时a都会重新创建,所以地址是变化的
  3. 二进制太长,不方便,用十六进制方便简洁
  4. 局部变量代码运行时指派地址,全局变量代码编译时就已经指派地址

取地址操作拿到的地址就是一个16进制数值,怎么存起来? 指针变量

#include <stdio.h>
int main()
{
    int a = 10;
    printf("%p\n", &a);
    int *p = &a; //&a要存起来,用int *类型创建一个变量p
                 // p就是指针变量
                 //内存单元的编号就是地址,地址也被称为指针
                 // p用来存地址(即指针)
                 //所以将存放指针(地址)的变量称为指针变量
    return 0;
}

当p是指针变量时该如何去理解?

初识C语言_C语言_29

int   a = 10; //向内存申请空间创建变量a,存放10,该内存空间的编号(地址)是首字节的编号(地址)(起始编号)

int   *   p = &a;  //创建用来存放的地址(编号)的p变量,p的类型:int *,*说明p是指针变量,int说明p指向的对象是int类型的(p指向的对象是a,即a的类型是int类型的)

注意:

  1. 指针:地址    指针变量:存放(指针)地址的变量    指针变量的创建 int*
  2. p 指针变量类型的解析:* 说明p是指针变量,int说明p指向的对象的是int类型,指针变量不是*p,而是p,int*是类型
  3. 指针变量的创建
#include <stdio.h>
int main()
{
    char ch = 'w';
    char* pc = &ch;   //创建指针变量pc
    printf("%p\n", pc);
    return 0;
}

存地址的意义:通过p中存放的地址(a的地址)找到p所指向的对象(a)

怎么找a?   

对指针变量p进行解引用就能找到指针所指向的对象a ,即*p。*是解引用操作符,*p意为通过p中存放的地址,找到p所指向的对象a,*p就是p指向的对象a。

#include <stdio.h>
int main()
{
    int a = 10;
    int* p = &a;
    *p = 20;
    printf("%d\n", a);//输出20
                      //*p通过p中存放的地址
                      //找到p所指向的对象a,修改a的值
    return 0;
}

注意:

  1. 单目操作符:*  解引用操作符(通过地址找到对象)<-->&取地址(取出对象的地址) 一对单目操作符(功能相反,可抵消)
  2. 地址不能随便改动,C 语言规定了通过指针修改内存地址的操作必须谨慎使用,必须遵守内存权限规则,否则会出现各种内存安全问题。
  3. &a 取的是第一个字节的地址,如下图所示,0x010ff808是第一个字节0a的地址,后面三个字节地址:09 0a 0b (在内存窗口可将列调整为1观看)

初识C语言_C语言_30

指针变量的大小

指针变量的大小取决于地址的大小

#include <stdio.h>
int main()
{

    printf("%zu\n", sizeof(char *)); //输出都是4/8
    printf("%zu\n", sizeof(short *));
    printf("%zu\n", sizeof(int *));
    printf("%zu\n", sizeof(float *));
    printf("%zu\n", sizeof(double *));
    return 0;
}

注意:

  1. 不管是什么类型的指针都是在创建指针变量,指针变量是用来存放地址的,一个指针变量的大小取决于一个地址存放需要多大空间                  
  2. 32位机器的机器:地址是32bit-------4byte所以指针变量大小是4个字节, 64位机器的机器:地址是64bit-------8byte所以指针变量大小是8个字节
  3. sizeof返回值最好用%zu打印
  4. 代码风格
#include <stdio.h>
int main()
{
    char* p;           //创建单个指针变量将*与类型放一起更好
    int* pc;
    int* p1, p2, p3;   //创建多个变量将*与类型放一起不好
                       //容易误解p1,p2,p3都是指针
                       //实际上只有p1是指针,p2,p3都是整型
    int *pc1, pc2, pc3;//创建多个变量,将*与变量放一起更好
                       //p1是指针,p2,p3都是整型
    int *p4,*p5,*p6;   //创建3个指针变量                 
    return 0;
}

14.结构体

常见的类型:char,int short,long,float,double 表示数字或者字符没有问题,但是不能表示复杂对象。eg:表示人 :姓名+年龄+性别+地址+电话,简单类型无法解决,C语言中就有了自定义类型,结构体(关键字:struct)是一种自定义类型

结构体是把一些单一类型组合在一起的做法

#include <stdio.h>
struct Stu //结构体类型
{
    char name[20]; //结构体成员变量
    int age;
    char sex[10];
    char tele[12]; //此时不占空间
    //只有使用结构体类型去创建变量时才会向内存申请空间
};

void print(struct Stu *ps)
{
  //printf("%s %d %s %s\n", (*ps).name, (*ps).age, (*ps).sex, (*ps).tele);
    printf("%s %d %s %s\n", ps->name, ps->age, ps->sex, ps->tele); 
    //简洁写法
    //->   结构体指针变量->成员名  (前提是知道地址)
}
int main()
{
    struct Stu s = {"zhangshan", 20, "nan", "15000952387"};
    //创建结构体类型变量并初始化
    printf("%s %d %s %s\n", s.name, s.age, s.sex, s.tele);//直接打印
    //结构体变量用.操作符访问结构体成员
    //结构体对象.成员名  (前提是知道结构体对象)
    print(&s);     //用取地址方式调用函数打印输出结构体变量中数据
    return 0;
}

注意:

  1. 创建一个新类型时不占空间,用类型去创建变量时才会向内存申请空间
  2. 访问成员:①结构体对象访问成员用 . (得到结构体对象用.);②用指针访问对象的成员用->(得到地址用->)
  3. define不是关键字, 是一个预处理指令


标签:10,return,变量,int,C语言,初识,printf,main
From: https://blog.51cto.com/u_16129148/6454144

相关文章

  • C语言编程—强制类型转换
    强制类型转换是把变量从一种类型转换为另一种数据类型。例如,如果您想存储一个long类型的值到一个简单的整型中,您需要把long类型强制转换为int类型。您可以使用强制类型转换运算符来把值显式地从一种类型转换为另一种类型,如下所示:(type_name)expression请看下面的实例,使用强......
  • C语言循环打印空心正方形代码实现
    #include<stdio.h>intmain(){intw,i,j;printf("输入正方形边长\n");scanf_s("%d",&w);if(w<=0){printf("正方形边长要大于0\n");return0;}//外层循环控制行数......
  • C语言学习一
    初识C在C中内存地址<==>指针地址intmain(){intnumber=100;//实际是number(int)=100,number是别名returnNULL;}main函数进栈,return出栈注意:&number读取内存地址*(&number)取出number地址对应的值:100intmain(){intnumber=100;//实际变量的声明int*in......
  • 前端学习C语言 - 开篇
    前端学习C语言-开篇前端学习C语言有很多理由:工作、兴趣或其他。C语言几个常见的使用场景:操作系统开发:Linux操作系统的内核就是主要由C语言编写的。其他操作系统也广泛使用C语言进行核心部分的开发。系统级开发和嵌入式编程:C语言具有强大的底层控制能力和高效的代码......
  • 初识Firebug 全文 — firebug的使用
    初识Firebug全文—firebug的使用什么是Firebug从事了数年的Web开发工作,越来越觉得现在对WEB开发有了更高的要求。要写出漂亮的HTML代码;要编写精致的CSS样式表展示每个页面模块;要调试javascript给页面增加一些更活泼的要素;要使用Ajax给用户带来更好的体验。一个优秀的WEB开发人......
  • 菜鸟攻略–C语言多文件编程初探(二):使用 gcc 手动编译多文件 C 程序
    step1:下载安装Dev-C++已经安装了Dev-C++或系统中的可以跳过这步。去官网下载Dev-C++。我昨天下载,发现有点慢,所以我把安装文件放到百度网盘了,供大家下载,下载链接为:http://pan.baidu.com/s/1pLPenDx。开始安装,记住安装位置。在安装时只能选择英文,安装完成后,第一次启动时可以选择......
  • C语言 #pragma指令
    简介#pragma指令对每个编译器给出了一个方法,在保持与C和C++语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的#pragma用于指示编译器完成一些特定的动作#pragma所定义的很多指示字是编译器特有的#pr......
  • 逍遥自在学C语言 | 枚举的那些事儿
    前言在C语言中,枚举是一种方便组织和表示一组相关常量的工具。枚举类型有助于提高代码的可读性和可维护性。本文将介绍C语言枚举的基本概念、语法和用法,以及一些高级技巧。一、人物简介第一位闪亮登场,有请今后会一直教我们C语言的老师——自在。第二位上场的是和我们一起......
  • C语言编程—头文件
    头文件是扩展名为.h的文件,包含了C函数声明和宏定义,被多个源文件中引用共享。有两种类型的头文件:程序员编写的头文件和编译器自带的头文件。在程序中要使用头文件,需要使用C预处理指令#include来引用它。前面我们已经看过stdio.h头文件,它是编译器自带的头文件。引用头文件......
  • c语言函数
    #include<iostream>floataverage();//主函数在前需要申明intmain(){floatx;x=average();printf("平均值为:%5.2f\n",x);return0;}floataverage(){floatx1,x2,x3,x4,x5;printf("请输入五个数:");scanf_s(&quo......