C语言基础复习

news2024/11/17 3:54:30

目录

数组

一维数组

完全初始化int a[5]={1,2,3,4,5};

不完全初始化int a[5]={1,2}

完全不初始化”,int a[5]

二维数组

完全初始化

不完全初始化

指针

变量的访问方式:

指针变量的定义:

指针变量的赋值:

指针变量的运算

指针与数组

多级指针

函数指针

函数指针的定义方式:

常用库函数

sizeof

printf与scanf

输出控制符

转义符

scanf缓冲

预处理指令

宏定义: #define

# include 

五、函数

六、递归

七、变量的作用域、存储方式、修饰符

(1)变量按作用域可分为

(2)按存储方式可分为

(3)const

const int *p=&a;

int * const p=&a;

const int * const p=&a;


数组

一维数组

int a[5]
数组名a除了表示该数组之外,还表示该数组的首地址
方括号中的常量表达式可以是“数字常量表达式”,也可以是“符号常量表达式”。但不管是什么表达式,必须是常量,绝对不能是变量。


完全初始化int a[5]={1,2,3,4,5};

只有在定义数组的同时才可以整体赋值,其他情况下都不能整体赋值
此时可以不指定数组的长度

不完全初始化int a[5]={1,2}

只给前面两个元素a[0]、a[1]初始化,没有被初始化的元素自动为0
大括号中什么都不写,那就是极其严重的语法错误。大括号中最少要写一个数

完全不初始化”,int a[5]

不初始化,那么各个元素的值就不是0了,所有元素中都是垃圾值-858993460。

二维数组

完全初始化

int a[2][3]={{1,2,3},{4,5,6}};
int a[2][3]={{1,2,3,4,5,6}};
此时可以不指定第一维的数组的长度,但第二维的长度不能省

不完全初始化

int [2][3]={{1,2,},{4}};

指针

变量的访问方式:

  • 直接访问:程序中一般是通过变量名来对内存单元进行存取操作的。其实程序经过编译以后已经将变量名转换为变量的地址,地址就是内存单元的编号,对变量值的存取都是通过地址进行的。这种按变量地址存取变量的方式称为直接访问方式。
  • 间接访问:变量中存放的是另一个变量的地址。一个变量的地址就称为该变量的指针,指针就是地址,一个变量专门用来存放另一个变量的地址,那么就称它为“指针变量”。通过指针变量访问变量称为间接访问方式

指针变量的定义:

基类型 *指针变量名;
int *i
i变量的数据类型是int *型,即存放int变量地址的类型。int和*加起来才是变量i的类型

指针变量的赋值:

j = &i;

&是取地址运算符:与scanf中的&是一样的概念;因为j是定义成指针型变量,所以j中只能存放变量的地址,所以变量i前一定要加&。指针变量中只能存放地址,不要将一个整数或任何其他非地址类型的数据赋给一个指针变量。

*为指针运算符:功能是取其内部所存变量地址所指向变量中的内容。当指定j指向变量i之后,*j就完全等同于i,可以相互替换。使用时注意不要引用未初始化或null指针

定义指针变量时的*j和程序中用到的*j含义的不同。定义指针变量时的*j只是一个声明,此时的*仅表示该变量是一个指针变量,并没有其他含义。

指针变量的运算

两个指针变量相减的结果是这两个地址之间元素的个数,而不是地址的个数

所以只有同类型的指针能相减

指针与数组

数组名表示的是数组第一个元素的起始地址,
如果指针变量p已经指向一维数组的第一个元素,那么p+1就表示指向该数组的第二个元素
p指向的是第一个元素的地址,那么*p表示的就是第一个元素的内容。同样,p+i表示的是第i+1个元素的地址,那么*(p+i)就表示第i+1个元素的内容。即p+i就是指向元素a[i]的指针,*(p+i)就等价于a[i]。数组名a是一个常量,表示的是数组的首地址,那么元素a[i]的地址也可以用a+i表示。
a[i]写成*(a+i)的形式,程序的执行效率会更高、速度会更快。因为在执行程序的时候数组是先计算地址,然后转化成指针。而直接写成指针*(a+i)的形式就省去了这些重复计算地址的步骤。
指针还能用关系运算符比较大小,使用关系运算符来比较两个指针的值的前提是两个指针具有相同的类型

多级指针

int ****a; ”表示指针变量a只能存放int ***型变量的地址。
多级指针的目的是为了跨函数使用动态内存
“跨函数使用动态内存”也可以不用多级指针

函数指针

如果在程序中定义了一个函数,那么在编译时系统就会为这个函数代码分配一段存储空间,这段存储空间的首地址称为这个函数的地址。而且函数名表示的就是这个地址  

函数指针的定义方式:

函数返回值类型 (* 指针变量名) (函数参数列表);
int(*p)(int, int);

这个语句就定义了一个指向函数的指针变量p。首先它是一个指针变量,所以要有一个“*”,即(*p);
其次前面的int表示这个指针变量可以指向返回值类型为int型的函数;后面括号中的两个int表示这个指针变量可以指向有两个参数且都是int型的函数。函数指针的定义就是将“函数声明”中的“函数名”改成“(* 指针变量名)”。
这里需要注意的是:(* 指针变量名)两端的括号不能省略,
通过函数指针调用函数

# include <stdio.h>
int Max(int, int);  //函数声明
int main(void)
{
    int(*p)(int, int);  //定义一个函数指针
    int a, b, c;
    p = Max;  //把函数Max赋给指针变量p,使p指向Max函数
    printf("please enter a and b:");
    scanf("%d%d", &a, &b);
    c = (*p)(a, b);  //通过函数指针调用Max函数
    return 0;
}
int Max(int x, int y)  //定义Max函数
{
    int z;
    if (x > y)
    {
            z = x;
    }
    else
    {
            z = y;
    }
    return z;
}

常用库函数

sizeof

获得数据类型或变量在内存中所占的字节数,也可以获得整个数组在内存中所占的字节数

printf与scanf

输出控制符

  • %d:按十进制整型数据的实际长度输出。

        %ld:输出长整型数据。
        %md:m为指定的输出字段的宽度。如果数据的位数小于m,则左端补以空格,若大于m,则按实际位数输出。

  • %u:输出无符号整型(unsigned)。输出无符号整型时也可以用%d,这时是将无符号转换成有符号数,然后输出。但编程的时候最好不要这么写,因为这样要进行一次转换,使CPU多做一次无用功。
  • %c:用来输出一个字符。
  • %f:用来输出实数,包括单精度和双精度,以小数形式输出。不指定字段宽度,由系统自动指定,整数部分全部输出,小数部分输出6位,超过6位的四舍五入。
  • %.mf:输出实数时小数点后保留m位,注意m前面有个点。
  • %o:以八进制整数形式输出,这个就用得很少了,了解一下就行了。
  • %s:用来输出字符串。用%s输出字符串同前面直接输出字符串是一样的。但是此时要先定义字符数组或字符指针存储或指向字符串,这个稍后再讲。
  • %x(或%X或%#x或%#X):以十六进制形式输出整数,小写的x,输出的字母就是小写的,大写的X输出的字母就是大写的;如果加一个“#”,就以标准的十六进制形式输出。最好是加一个“#”,否则如果输出的十六进制数正好没有字母的话会误认为是一个十进制数

转义符

输出“%d”只需在前面再加上一个“%”;要输出“\”只需在前面再加上一个“\”;要输出双引号也只需在前面加上一个“\”

scanf缓冲

scanf是缓冲输入的,也就是说从键盘输入的数据都会先存放在内存中的一个缓冲区。只有按回车键后scanf才会进入这个缓冲区和取数据,所取数据的个数取决于scanf中“输入参数”的个数。所以上述程序中scanf只有一个输入参数,因此按回车键后scanf只会取一个数据。所以变量ch有数据,而变量i没有数据,没有数据就是没有初始化,输出就是-858993460。

如果scanf中“输入参数”的个数为n,那么就从排在最前面的开始,依次往后取n个数据输出给scanf。没取完的仍旧放在缓冲区中,直到取用完毕为止。如果缓冲区中的数据全被取完了,但还有scanf要取数据,那就要再从键盘输入数据。
对于%d,在缓冲区中,空格、回车、Tab键都只是分隔符,不会被scanf当成数据取用。%d遇到它们就跳过,取下一个数据,这些被跳过去的空白符都被释放了。但是如果是%c,那么空格、回车、Tab键都会被当成数据输出给scanf取用,如果前面的有分隔符遗留在缓冲区可以用getchar()吸收,或者用fflush(stdin)清空缓冲区(并不是所有的编译器都支持fflush,比如gcc就不支持)

预处理指令

宏定义: #define

#define定义一个标识符来表示一个常量。其特点是:定义的标识符不占内存,只是一个临时的符号,预编译后这个符号就不存在了。预编译又叫预处理。预编译不是编译,而是编译前的处理,预编译所执行的操作就是简单的“文本”替换。对宏定义而言,预编译的时候会将程序中所有出现“标识符”的地方全部用这个“常量”替换,称为“宏替换”或“宏展开”。替换完了之后再进行正式的编译

#define的作用域为自#define那一行起到源程序结束。如果要终止其作用域可以使用#undef命令

# include 

include <stdio.h>也是这样的,即在预处理的时候先单纯地用头文件stdio.h中所有的“文本”内容替换程序中# include <stdio.h>这一行,然后再进行正式编译。

五、函数

C语言中,所有函数的定义,包括主函数main在内,都是“平行”的。也就是说,在一个函数的函数体内,不能再定义另一个函数,即不能嵌套定义

1)首先被调函数必须是已经存在的函数,要么是库函数,要么是自己定义的函数。如果是库函数,那么必须在程序开头用# include命令将该库函数所在的头文件包含进来。C语言中每一个库函数都有一个头文件,头文件包含了调用该库函数时所需要用到的信息,包括对库函数的函数声明。所以只要包含了某个库函数的头文件,就可以直接对该库函数进行调用,无需再进行声明

如果被调函数是用户自己定义的函数,而该函数的位置又在调用它的函数即主调函数的后面(在同一个文件中),那么就必须要在主调函数中,在调用位置之前对被调函数进行声明
如果被调函数的定义是在主调函数之前,那就可以不用对Max函数进行声明
在函数声明时也可以不写形参名,只写形参的类型。


六、递归

也是一种函数调用,只不过是函数自己调用自己,是一种特殊的函数调用
缺点也很明显:递归的优点是简化程序设计,结构简洁清晰,容易编程,可读性强,容易理解
速度慢,运行效率低,对存储空间的占用比循环多。
递归也带来了大量的函数调用,这也有许多额外的时间开销。函数调用要发送实参,要为被调函数分配存储空间,还要保存返回的值,又要释放空间并将值返回给主调函数,这些都太浪费空间和时间了!


七、变量的作用域、存储方式、修饰符

(1)变量按作用域可分为

局部变量”:定义在函数内部的变量,只有在本函数内才能使用,函数调用完后,系统为该函数中的局部变量分配的内存空间就会被释放掉。在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,离开本复合语句就无效,且内存单元随即被释放。所谓复合语句就是用大括号“{}”括起来的多个语句。所以局部变量的作用范围准确地说不是以函数来限定的,而是以大括号“{}”来限定的。
全局变量”:定义在函数外部的变量,可以被整个C程序中所有的函数所共用。它的作用范围是从定义的位置开始一直到整个C程序结束。
全局变量未初始化,那么系统会自动将其初始化为0。它们的这个区别主要源自于它们存储空间的不同。局部变量是在栈中分配的,而全局变量是在静态存储区中分配的。只要是在静态存储区中分配的,如果未初始化则系统都会自动将其初始化为0。

外部变量(extern )”。
一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾结束,在一个文件内扩展全局变量的作用域,将外部变量的作用域扩展到其他文件

(2)按存储方式可分为

“自动变量(auto)”、局部变量其实都是auto型
静态变量(static)”、statci修饰过的局部变量称为静态局部变量,定义成static之后就存储在静态存储区了。前面说过,存储在静态存储区中的变量如果未初始化,系统会自动将其初始化为0,静态存储区主要用于存放静态数据和全局数据。但它不是全局变量,
静态局部变量仍然是局部变量,仍然不能在它的作用范围之外使用。
静态局部变量仅在第一次函数调用时定义并初始化,以后再次调用时不再重新定义和初始化,而是保留上一次函数调用结束后的值。
用static修饰全局变量时,会限定全局变量的作用范围,使它的作用域仅限于本文件中。这个是使用static修饰全局变量的主要目的。如果不用static进行修饰,那么其他文件只需要用extern对该全局变量进行一下声明,就可以将该全局变量的作用范围扩展到该文件中。而且如果一个项目的多个.c文件中存在同名的全局变量,那么在编译的时候就会报错,报错的内容是“同一个变量被多次定义”。但是如果在这些全局变量前面都加上static,那么编译的时候就不会报错

(3)const

const   int   a = 10;   与   int   const   a = 10;    两者语义一致
用const定义的变量的值是不允许改变的,即不允许给它重新赋值。所以说它定义的是只读变量必须在定义的时候就给它赋初值。如果定义的时候未初始化,对于未初始化的局部变量,程序在执行的时候会自动把一个很小的负数存放进去。

修饰谁,谁的内容就不可变,其他的都可变
当用const进行修饰时,根据const位置的不同有三种效果。原则是:修饰谁,谁的内容就不可变,其他的都可变

const int *p=&a;

当把const放最前面的时候,它修饰的就是*p,那么*p就不可变。*p表示的是指针变量p所指向的内存单元里面的内容,此时这个内容不可变。其他的都可变,如p中存放的是指向的内存单元的地址,这个地址可变,即p的指向可变。但指向谁,谁的内容就不可变,但它只能“禁止指针通过指针变量p修改”

int * const p=&a;

此时const修饰的是p,所以p中存放的内存单元的地址不可变,而内存单元中的内容可变。即p的指向不可变,p所指向的内存单元的内容可变

const int * const p=&a;

此时*p和p都被修饰了,那么p中存放的内存单元的地址和内存单元中的内容都不可变。

用const修饰的变量,无论是全局变量还是局部变量,生存周期都是程序运行的整个过程。而使用const修饰过的局部变量就有了静态特性,它的生存周期也是程序运行的整个过程。我们知道全局变量是静态的,静态的生存周期就是程序运行的整个过程。局部变量存储在栈中,静态变量存储在静态存储区中,而经过const修饰过的变量存储在内存中的“只读数据段”中。只读数据段中存放着常量和只读变量等不可修改的量。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/195642.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Spring-Security入门

简介 Security 是 Spring 家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。 ​ 一般来说中大型的项目都是使用SpringSecurity 来做安全框架。小项目有Shiro的比较多,因为相比与Spring…

ChatGPT - InstructGPT 论文简读

发表于NLP会议:NeurlPS,EMNLP EMNLP: Empirical Methods in Natural Language Processing,自然语言处理中的经验方法NeurlPS: Neural Information Processing Systems,神经信息处理系统ChatGPT: Optimizing Language Models for Dialogue,优化对话的语言模型 ChatGPT:htt…

一文了解编程领域的模版

文章目录模版含义代码模版泛型模版引擎小结🍊在编程领域,模板是一种代码片段,它可以被重复使用,并允许您在保持代码的基本结构不变的情况下,根据需要调整其中的内容。模板通常在构建大型程序或开发一类相关程序时非常有…

Arthas的学习与使用

一、简介 Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时&#xff0c…

Maven知识点-反应堆

前言 在一个多模块的Maven项目中,反应堆(Reactor)是指所有模块组成的一个构建结构。对于单模块的项目,反应堆就是该模块本身;但是对于多模块项目来说,反应堆就包含了各模块之间继承和依赖的关系&#xff0…

一篇带你MySQL入门

文章目录1. MySQL概述1.1 数据库相关概念1.2 MySQL数据库1.2.1 版本1.2.2 下载1.2.3 数据模型2. SQL2.1 SQL通用语法2.2 SQL分类2.3 DDL2.3.1 数据库操作2.3.2 表操作2.4 图形化界面工具2.4.1 安装2.4.2 使用2.5 DML2.5.1 添加数据2.5.2 修改数据2.5.3 删除数据2.6 DQL2.6.1 基…

每天一道大厂SQL题【Day04】大数据排序统计

每天一道大厂SQL题【Day04】大数据排序统计 大家好,我是Maynor。相信大家和我一样,都有一个大厂梦,作为一名资深大数据选手,深知SQL重要性,接下来我准备用100天时间,基于大数据岗面试中的经典SQL题&#x…

酒店管理|基于Springboot+Vue前后端分离实现酒店管理系统

作者主页:编程指南针 作者简介:Java领域优质创作者、CSDN博客专家 、掘金特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容:Java项目、毕业设计、简历模板、学习资料、面试题库、技术互助 收藏点赞不迷路 关注作者有好处 文末获取源…

webpack5从入门到精通

前言 webpack是什么? 摘自官网的一段话:webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每…

[oeasy]python0072_修改字体前景颜色_foreground_color_font

修改颜色 回忆上次内容 m 可以改变字体样式 0-9 之间设置的都是字体效果0 重置为默认1 变亮2 变暗3 斜体4 下划线5 慢闪6 快闪7 前景背景互换8 隐藏9 中划线 叠加效果 \33[1;3moeasy;分割 取消效果 21 取消 122 取消 223 取消 3一直到 290 是全部取消,回到默认 最…

静态链接库与动态链接库

静态链接库与动态链接库的区别 静态链接库:在项目中引用了库函数,编译时链接器会将引用的函数代码或变量,链接到可执行文件里,和可执行程序组装在一起 动态链接库:在编译阶段不参与链接,不会和可执行文件…

【Unity】流式播放远端音频:WAV格式音频篇(一)

先了解一下wav的格式: 参考1:【音频】WAV 格式详解_tyustli的博客-CSDN博客_wav文件格式详解wav 文件支持多种不同的比特率、采样率、多声道音频。WAV 文件格式是 Microsoft 的 RIFF 规范的一个子集,用于存储多媒体文件。RIFF(res…

git-secret:在 Git 存储库中加密和存储密钥(上)

目前市面上已经存在许多较为成熟的密钥管理产品,比如 HashiCorp Vault,AWS Secrets Manager 以及 GCP Secret Manager。由于这些产品需要集成和维护等服务,因此在项目中引入会增加一定成本和开销。阅读本文,将带你了解如何在 Dock…

numpy数值差分

文章目录diffediff1ddiff diff是numpy中用于求差分的函数&#xff0c;函数定义为 diff(a, n1, axis-1, prepend<no value>, append<no value>)其中a为数组&#xff0c;n为差分的阶数&#xff0c;axis为求导对应的坐标轴&#xff0c;默认-1表示最后一个轴。 例如…

提分必练,中创教育PMP全真模拟题分享

湖南中创教育每日五题分享来啦&#xff0c;“日日行&#xff0c;不怕千万里&#xff1b;常常做&#xff0c;不怕千万事。”&#xff0c;每日五题我们练起来&#xff01; 1、一个建筑项目所在的地区即将进入台风季节&#xff0c;恶劣的天气会严重影响项目的进度。高层管理者要求…

Java poi之word文本替换

目录结构前言文档准备引入Maven依赖代码块替换结果验证孤勇者替换结果对比青鸟替换结果对比前言 应公司需求&#xff0c;需实现以下功能 word文本内容的替换&#xff1b;word文本内容的提取&#xff1b;word文档中图片的提取存放 此文章将使用Apache POI实现Word文档中文本内…

【C++】揭开“引用”的庐山真面目

目录 一、引用的概念 二、引用的应用 1.特性 2.使用场景 2.1 引用作为函数参数 2.2 引用作为函数返回值 三、引用的权限问题 四、引用和指针的区别 一、引用的概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟…

【数据结构之二叉树简介·顺序存储·应用:堆·堆排序·TOPK问题】

​ &#x1f57a;作者&#xff1a; 迷茫的启明星 &#x1f618;欢迎关注&#xff1a;&#x1f44d;点赞&#x1f64c;收藏✍️留言 &#x1f383;相关文章 【数据结构从0到1之树的初识】 &#x1f3c7;家人们&#xff0c;码字不易&#xff0c;你的&#x1f44d;点赞&#x1f64…

Kotlin SharedFlowStateFlow 热流到底有多热?

前言 协程系列文章&#xff1a; 一个小故事讲明白进程、线程、Kotlin 协程到底啥关系&#xff1f;少年&#xff0c;你可知 Kotlin 协程最初的样子&#xff1f;讲真&#xff0c;Kotlin 协程的挂起/恢复没那么神秘(故事篇)讲真&#xff0c;Kotlin 协程的挂起/恢复没那么神秘(原理…

50条必背JAVA知识点(二)

16.强制类型转换&#xff1a;将容量大的数据类型转换为容量小的数据类型&#xff0c;但可能造成精度降低或溢出。 17.字符串不能直接转换为基本类型&#xff0c;但通过基本类型对应的包装类则可以实现把字符串转换成基本类型。 18.计算机底层都以二进制补码的方式来存储数据。…