精华内容
下载资源
问答
  • c语言程序输出所有不重复八卦排列组合.txt
  • 如何将多个C语言模块组合成一个程序.pdf C++箴言:必须返回对象时别返回引用.pdf C++文本模式模仿磁盘扫描外观.pdf C++通过覆盖__atexit进行缓冲区溢出攻击.pdf C++通过并行机制处理鼠标和键盘.pdf
  • 如何将多个C 语言模块组合成一个程序 C 语言的基本组成单元是函数各个函数之间可以相互引用在学到静态函数有时又将为内 部函数和外部函数即分别用static 和extern说明的函数时有不少人感到很迷惑外部 和内部到底是...
  • c语言排列组合

    2012-03-05 23:48:54
    小小wintc程序 计算排列组合代吗 用递归写的 呵呵
  • C语言程序设计

    2019-08-11 15:54:57
    C语言程序设计 数据类型 基本类型和枚举类型变量的值都是数值,统称为算术类型。算术类型和指针类型统称为纯量类型,因为其变量的值是以数字来表示的。 数组类型和结构体类型统称为组合类型,共用体类型不属于...

    C语言程序设计

    数据类型

    在这里插入图片描述

    基本类型和枚举类型变量的值都是数值,统称为算术类型。算术类型和指针类型统称为纯量类型,因为其变量的值是以数字来表示的。

    数组类型和结构体类型统称为组合类型,共用体类型不属于组合类型,因为在同一时间内只有一个成员具有值。函数类型用来定义函数,描述一个函数的接口,包括函数返回值的数据类型和参数的类型。

    整型数据

    整型数据的分类

    基本整型(int 型)

    数据存储方式:用整数的补码(二进制整数补码规则:正数的补码是自身,负数的补码是将其绝对值的各位按位取反再加1)形式存放,第一个二进制为代表符号(0-整数 1-负数)。假设占用空间为N字节,则表示范围为:-2^N ~ 2^N-1

    各类型占用空间如下:

    类型 占用空间 表示范围
    int 2字节/4字节
    short int 2字节
    long int 8字节
    long long int 8字节

    占用空间规则:
    sizeof(short)<=sizeof(int)<=sizeof(long)<=sizeof(longlong)sizeof(short)<=sizeof(int)<=sizeof(long)<=sizeof(long long)

    因为各个系统相同数据类型占用空间不同,所以在进行迁移时,需要注意。

    可以将只有正值的数据定义为无符号类型(unsigned int,unsigned short等),为了充分利用变量数据类型的存储范围,可以将变量定义为无符号类型。只有整数数据存在无符号类型(可以使用unsigned修饰符修饰),实型数据没有无符号数。

    字符型数据

    字符是按其在字符集中的代码(整数)形式存储的,所以把字符型数据也作为整数类型的一种。

    ASCII 字符集使用一个字节表示所有字符,所有字符编码第一位均置0,后面7位作为编码存储位。如’a’的ASCII 代码是十进制数97,二进制形式为1100001,所以’a’在内存中表示为:01100001

    由于127个字符不够用,所以启用ASCII中置0的第一个二进制为,将字符集扩展为255个。

    浮点型数据

    实数是以指数形式存放在存储单元中的。一个实数可以使用多种指数形式表示,将小数部分中小数点前的数字为0、小数点后第一位数字不为0的表示形式成为规范化的指数形式,一个实数只有一个规范化的指数形式,在程序以指数形式输出一个实数时,必然以规范化的指数形式输出。

    float型

    单精度浮点型,占用空间4字节。数值以规范化的二进制指数形式存放在存储单元中。能得到6位有效数字。

    双精度浮点型,占用空间8字节。可得到15位有效数字。在C语言中进行浮点数的算数运算时,将float型都自动转换为double型,然后计算。

    长双精度。

    常量类型

    整型常量:
    - 整数即为整型常量。但是也会根据其范围确定一个合适的类型。
    - 在一个整数末尾加上L/l,表示它是长整型。

    浮点型常量:
    - 凡以小数形式或指数形式出现的实数,是浮点型常量,在内存中以指数形式存储。系统默认把浮点型常量都按双精度处理。
    - 在常量末尾加上F/f,强制指定常量类型为单精度。
    - 在实型常量后加L/l,则常量为long double型。

    运算符

    基本运算符:

    • 两个实数相除的结果是双精度实数,两个整数相除的结果为整数。
    • 如果除数或者被除数中有一个负值,则舍入方向根据系统的不同而不同。

    不同类型数据间的混合运算:若一个运算符两侧的数据类型不同,则会自动进行类型转换使二者具有同一数据类型,然后再进行运算。所以整型、实型、字符型数据间可以进行混合元素,规则为:

    • +、-、*、/运算中有一个数为float或double类型,则结果是double型。- 若int型与float型或double型进行运算,先把int型和float型转换为double型,然后进行计算,结果是double型。
    • 字符型与int型计算同java.

    ASCII字符集中,同一字母,小写字符代码比大写字符代码大32.

    强制类型转换运算符:在强制类型转换时,得到一个所需类型的中间数据,而原来变量的类型不会发生变化。

    C运算符

    运算符 举例
    算数运算符
    关系运算符
    逻辑运算符 ! &&
    位运算符 << >> ~
    赋值运算符 =及其扩展
    条件运算符 ?:
    逗号运算符 ,
    指针运算符 * 和 &
    求字节数运算符 sizeof
    强制类型转换运算符 (类型)
    成员运算符 . ->
    下标运算符 []
    其他 函数调用运算符()

    赋值过程中的类型转换

    • 如果赋值运算符两侧的类型不一致,但都是算术类型时,在赋值时要进行类型转换。转换规则如下:
      • 将浮点型数据(包括单、双精度)赋给整型变量时,先对浮点数取整,然后赋予整型变量。
      • 将整型数据赋给单、双精度变量时,数值不变,但以浮点数形式存储到变量中。
      • 将double型数据赋给float变量时,先将双精度转化为单精度,然后存储到float变量的4个字节中。双精度数值的大小不能超出float型变量的数值范围。
      • 将一个占字节多的整型数据赋给一个占字节少的整型变量或字符变量,只会将其低字节送到赋值的变量。

    总结:整型数据之间的赋值,按存储单元中的存储形式直接传送。实型数据之间以及整型与实型之间的赋值,先进行类型转换,然后再赋值。

    注:在不同数据类型之间进行赋值,如果数据出现失真,系统不会给出出错提示。

    一个表达中可以包含另一个表达式。所以赋值表达式可以出现在其他表达式之中。

    一般变量初始化不是在编译阶段完成的(只有在静态存储变量和外部变量的初始化时再编译阶段完成的),而是在程序运行时执行本函数时赋予初始值的。

    输入输出

    C语言本身不提供输入输出,输入输出操作是由C标准函数库中的函数来实现的。

    预处理指令的两种形式:

    • #include <stdio.h>

    编译系统从存放C编译系统的子目录中去找所要包含的文件,此为标准方式。

    • #include “c:\temp\test.h”

    编译系统先在用户的当前目录中寻找要包含的文件,如果未找到,则按标准方式查找。

    疑问:C编译系统在使用函数和变量前,需要首先定义函数。使用预处理指令引入头文件后,编译系统使用标准方式和非标准方式查找头文件引入到当前文件中;如果一个文件内引入了两个头文件,而这两个头文件内声明了两个完全一致的函数,在程序链接时,会使用哪个函数实现?这种情况是不是合法?

    printf函数

    格式字符:

    • d 用于输出有符号十进制数
    • c 用于输出一个字符串
    • s 用于输出一个字符串
    • f 用于输出实数(包括单、双、长双精度)
      • 基本型 %f 不指定输出数据长度,由系统自动决定数据所占列数,一般做法:实数中的整数部分全部输出,小数部分输出6位。
      • 指定数据宽度和小数位数 %m.nf——一共占m列,n位小数 小数部分采用四舍五入处理,小数位数指定需要注意实数有效位数(单精度6位,双精度15位)
      • 输出数据向左对齐 %-m.nf
    • e格式符 %e 以指数形式输出实数,若不指定输出数据所占宽度和数字部分的小数位数,默认数字部分的小数位数为6位,指数部分占5列。
      • %m.ne格式
    • i格式符 作用域%d相同
    • o格式符 以八进制整数形式输出,输出值不带符号。
    • x 格式符 以十六进制数形式输出整数
    • u 格式符 用于输出无符号型数据,以十进制整数形式输出
    • g 格式符 用来输出浮点数,系统自动选用f格式或e格式输出,选择其中长度较短的输出。

    scanf函数

    在用%c格式声明输入字符时,空格字符和转义字符中的字符都作为有效字符输入。

    scanf()在读取输入缓冲区时没有限制读取字节数,所以VisualStudio推出了可以限制读取字节数的方法scanf_s().

    多个scanf连用时,会出现后一个scanf读取到前一次输入的回车符号,导致后续输入没有被scanf获取到,可以通过在两个scanf中间加入getchar()方法读取缓冲区的回车符的方式解决。

    在输入多个数字时,需要使用空格分隔。在输入多个字符时,可不用其他字符分隔。

    在输入数值时,遇到非数字时,认为该数据结束。

    字符输入输出

    除使用printf和scanf输入和输出字符外,还可以用如下函数进行字符的输入和输出:

    • putchar 输出一个字符
    • getchar 从输入设备中获取一个字符

    选择结构程序设计

    逻辑型变量:C99新增的数据类型。可以将关系运算和逻辑运算的结果存入一个逻辑型变量中。可在使用时引入头文件:stdbool.h

    C语言中三目运算符:表达式1 ? 表达式2 : 表达式3 执行过程:先计算表达式1的值,若表达式1的值为真(非0),则计算表达式2的值作为结果;否则计算表达式3的值作为结果。

    switch 后括号内的表达式,其值类型应为整数类型(包括字符型)

    for循环:for(表达式1;表达式2;表达式3) 表达式1和表达式3可以是任意一个或者多个表达式;表达式2可以是关系表达式或逻辑表达式或者数值表达式或者字符表达式,只要其值为非0,循环体就会被执行。

    break continue 在多重嵌套循环的情况下,对当前循环有效。

    数组

    C语言不允许对数组的大小作动态定义。但是如果在被调用函数(不包括主函数)中定义数组,其长度可以是变量或非常量表达式。如果指定数组为静态存储方式,则不能用“可变长数组”。

    若定义数值型数组时,制定了数组的长度并对其进行初始化,未指定初始化值的元素会被自动初始化为0;如果是指针型数组,则初始化为NULL,即为空指针。

    二维数组称为矩阵。

    字符型数组

    C语言中没有字符串,字符串时存放在字符型数组中的,将字符串作为字符数组来处理,字符串的实际长度与数组长度相等。C语言规定了一个字符串结束标志——’\0’.C系统在用字符数组存储字符串常量时会自动加一个’\0’作为结束符。

    字符串处理函数:

    • puts 将一个字符串(以\0结尾的字符序列)输出到终端。
    • gets 从终端输入一个字符串到字符数组,并得到一个函数值,该函数值是字符数组的起始地址。
    • strcat 字符串连接函数 结果存放在字符串数组1中,函数返回值是字符数组1的地址。
    • strcpy 将字符串数组2(也可以是字符串常量)复制到字符串数组1中去,不能用赋值语句将一个字符串常量或字符数组直接给一个字符数组,只能使用strcpy函数将一个字符串复制到另一个字符数组中去。用赋值语句只能将一个字符赋给一个字符型变量或字符数组元素。
    • strncpy 将字符串2中前N个字符复制到字符数组1中去。
    • strcmp 字符串比较函数——将两个字符串自左至右逐个字符比较(按ASCII码值大小比较),直到出现不同的字符或遇到\0为止,返回值0-相等,正整数-字符串1>字符串2,负整数-字符串1<字符串2
    • strlen 测试字符串长度(不包括\0)
    • strlwr 转换为小写的函数
    • strupr 转换为大写的函数

    用函数实现模块化程序设计

    C语言中要求,在程序中用到的所有函数,必须先定义后使用。当被调用函数的实现在调用位置的后面时,需要在调用位置之前(函数开头或函数之前)对被调用函数进行生命。

    在调用函数过程中,系统会把实参的值传递给被调用函数的形参——形参从实参得到一个值,如果形参值发生变化,实参值不会发生改变。

    函数中可以不要return语句。如果return语句中返回值类型与函数类型不一致,则会自动发生类型转换,最终以函数类型为准。

    对于不返回值的函数,应当将其定义为void类型。

    C语言使用函数原型作函数声明。

    数组作为函数参数

    数组作为函数参数:数组名可以作为实参和形参,传递的是数组第一个元素的地址;数组元素可以作为函数的实参,其用法与变量相同,向形参传递数组元素的值。

    数组元素只能用作实参,不能作为形参。

    用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名作函数实参时,向形参(数组名或指针变量)传递的是首元素的地址。在函数形参中指定数组大小无效,可不指定大小。在编译时把形参数组名处理为一个指针变量,用来接收一个地址。在函数调用过程中,实参和形参数组指向同一块内存区域,所以改变形参数组元素时,实参数组元素值也会发生改变。

    高维数组名可以作为函数的实参和形参,在被调用函数中对形参数组定义时可以指定每一维的大小,也可以省略第一维的大小说明,但是不能把第2维以及其他高维的大小说明省略(定义 int array[][] 不合法)。

    局部变量和全局变量

    在函数外定义的变量是全局变量,全局变量可以在本文件中其他所有函数内使用,它的有效范围为从定义变量的位置开始到本源文件结束。

    习惯:将全局变量名的第一个字母用大写表示。建议不在必要时不要使用全局变量,原因如下:

    • 全局变量在程序的全部执行过程中都占用内存,而不仅在需要时才占用内存。
    • 在函数内使用全局变量使函数通用性变低。
    • 过多全局变量会降低程序的可读性和清晰性。

    变量的存储方式和生存期

    变量的存储有两种不同的方式:静态存储方式和动态存储方式。静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式,而动态存储方式则是在程序运行期间根据需要进行动态的分配存储空间的方式。

    供用户使用的存储空间可以分为三个部分:

    • 程序区
    • 静态存储区
    • 动态存储区

    数据分别存放在静态存储区和动态存储区中。全局变量全部存放在静态存储区中,在程序开始执行时给全局变量分配存储区(占用固定的存储单元而不是动态分配和释放),程序执行完毕就释放。

    动态存储区存放以下数据:

    • 函数形式参数 在调用函数时给形参分配存储空间
    • 函数中定义的没有用关键字static声明的变量,即自动变量
    • 函数调用时的现场保护和返回地址等

    动态存储区的数据动态分配和释放。

    每个变量和函数都有两个属性:数据类型和数据的存储类别。存储类别指数据在内存中的存储方式(动态存储和静态存储)。

    C语言存储类别如下:

    • 自动的(auto)

    数据存储在动态存储区中,函数形参和函数内局部变量(包括复核语句内局部变量)都属于此类,用关键字auto作储存类别声明,auto可以省略,默认隐含指定为此类。
    自动变量在每次函数运行时都会初始化,若没有指定初始化值,则初值不确定。

    • 静态的(statis)

    静态局部变量:若需要函数中的局部变量的值在函数调用结束后继续保留原值,在函数下次调用时,该变量值仍然存在,就看指定局部变量为静态局部变量,用static声明。
    静态局部变量只在编译时初始化一次,若没有赋初值,则系统默认赋为0或’\0’.
    尽管局部静态量在函数调用结束后仍然存在,但是除了再次调用当前函数外其他函数无法使用它。

    • 寄存器的(register)

    一般情况下,变量(静态存储方式和动态存储方式)的值是存放在内存中的。对一些频繁使用的变量,允许将局部变量值存放在CPU中的寄存器中,需要时直接从寄存器中取出参加运算而不必到内存中去取,以提高程序执行效率,这种变量称为寄存器变量,用关键字register声明。

    • 外部的(extern)

    一般情况下,外部变量是在函数的外部定义的全局变量,它们存储在静态存储区中,它们的作用域是从变量的定义处开始到本程序文件的结尾,在此范围内,全局变量为各函数共用。

    在一个文件内扩展外部变量的作用域

    若外部变量未在文件头部定义,则其有效的作用范围只限于定义处到文件结束。变量定义前的函数无法使用此外部变量。为了在变量定义前的函数中使用其后定义的外部变量,可以在此函数内使用extern对该变量作外部变量声明,表示把该外部变量的作用域扩展到此位置,然后就可以在此函数中使用此外部变量。

    将外部变量的作用域扩展到其他文件

    若在多个文件中需要使用同一个变量,可在任一文件中定义外部变量,而在另一文件中用extern对此变量作“外部变量声明”。

    extern:在编译过程遇到extern时,现在本文件中找外部变量的定义,如果找到,就在本文件中扩展作用域;若找不到,就在连接时从其他文件中找外部变量的定义,如果找到就将作用域扩展到本文件。如果找不到,出错。

    将外部变量的作用域限制在本文件中

    在定义外部变量时加static声明,则此外部变量只限于被本文件引用,而不能被其他文件引用。这种外部变量称为静态外部变量。使用此种方式可以避免多个文件间变量互相干扰,提高程序模块化、通用性。

    变量的声明和定义

    函数声明和定义:

    函数声明是对函数的标志符(变量、函数、结构体、共用体等)的属性进行声明,它是函数的原型,而函数定义时对函数功能的定义。

    变量声明和定义

    声明:

    • 定义性声明/定义 int a
    • 引用性声明 extern a
      一般把建立存储空间的声明称为定义,把不需要建立存储空间的声明称为声明。变量初始化只发生在定义时,而不是声明时。声明仅仅是用于扩展变量作用域。

    内部函数和外部函数

    函数本质上是全局的,若不加声明,一个文件中的函数可以被本文件中其他函数调用,也可以被其他文件中的函数调用。根据函数能否被其他源文件调用,将函数分为内部函数和外部函数。

    • 内部函数

    只能被本文件中其他函数调用的函数称为内部函数。在函数名和函数类型前加static即可。

    • 外部函数

    若定义函数时再首部最左端加关键字extern,则此函数可供其他文件调用,称为外部函数。可以省略,函数默认是外部函数。

    函数原型:用函数原型能够把函数的作用域扩展到定义该函数的文件之外(不必使用extern).只要在使用该函数的每个文件中包含该函数的函数原型即可,函数原型告诉编译器该函数稍后会定义。

    指针

    将指向变量单元的地址称为指针,通过它能找到以它为地址的内存单元。

    • 直接访问 按变量名进行的访问
    • 间接方式 将变量的地址存放在另一变量中,然后通过该变量来找到变量的地址,从而访问变量。

    一个变量的地址称为该变量的指针,如果有一个变量专门用来存放另一个变量的地址(指针),则它被称为指针变量,指针变量的值就是地址。

    定义指针变量的一般形式为:
    类型名 * pointerVariableName;

    类型名:在定义指针变量时必须指定的"基类型",用来指定此指针变量可以指向的变量的类型。之所以需要指定此类型,是因为在使用指针变量操作变量时,操作的数据类型不同,需要改变的内存范围不同,所以需要在定义时明确。一个指针变量只能指向同一个类型的变量。

    *表示此变量为指针变量

    指针变量名为pointerVariableName,而不是*pointerVariableName.

    在使用指针变量时,*pointerVariableName 表示通过指针变量操作指针变量所指向的变量,为*pointerVariableName 赋值会改变指针变量所指向的变量值。pointerVariableName 表示指针变量,为pointerVariableName赋值,只改变指针变量的值——只改变指针变量所指向地址,而不会影响指针变量所指向变量的值。

    int i;
    int * i_pointer = &i;
    *i_pointer = 123;
    printf("变量值为:%d \n",*i_pointer);
    

    两种运算:

    • & 取地址运算符
    • * 指针运算符(间接访问运算符),*p 代表指针变量p指向的对象

    为了避免C语言中“值传递”方式,使得对形参的改变在实参可见,可以将实参的指针变量作为函数入参,在函数内部改变指针变量所指向的变量值,就可以达到改变实参所指向的变量值的目的;但是要注意,通过修改形参的值——指针变量的值(地址)是无法改变实参的值的。

    指针引用数组

    引用数组元素可以使用下标法(a[0]),也可以使用指针法,即通过指向数组元素的指针找到所需的元素。使用指针法能使目标程序占内存少,运行速度快。

    int a [] = {1,2,3};
    	int* p1 = &a[0],*p2=a,*p3=&a; //经测试,三种方式都可以把数组首元素地址赋给指针变量
    	printf("指针p1:%d, p2:%d, p3:%d",p1,p2,p3);
    	for (int i = 0; i < 3;i++) {
    		printf("数组第%d个元素:%d \n",i,*p1);
    		p1 ++;//地址从数组首元素地址偏移,获取其他元素,仅加1即可,毋须写成 p1 += sizeof(int); 指针会自动根据数据类型计算偏移量。
    	}
    	printf("另一种获取元素的方式:%d \n",*(a+2));
    	printf("指向同一数组内元素的指针可以做求差值运算:%d \n",p1-p2);
    

    在指针指向数组元素时,允许对指针进行以下计算:

    • 加一个整数 指针指向数组下一个元素
    • 减一个整数 指针指向数组上一个元素
    • 自加(减)运算
    • 两个指针相减(两个指针都指向同一数组中的元素时才有意义)

    遍历数组的三种方法:

    • 下标法 a[i]
    • 通过数组名计算数组元素地址,获取元素值 *(a+i)
    • 用指针变量指向数组元素 *p;p++;

    第一种方式和第二种方式执行效率相同,编译系统是将a[i]转换为*(a+i)处理的;第三种方法较前两种快,不必每次重新计算地址。

    指向数组的指针变量也可以使用 p[i]的方式获取数组元素。在编译时,会将p[i]处理成*(p+i)

    用数组名作为函数参数:如果形参数组中各元素的值发生变化,实参数组元素的值也随之变化。原因:实参数组名代表该数组首个元素的地址,而形参用于接收实参传递的数组首个元素地址。C编译将形参数组名作为指针变量来处理。

    fun(int arr[],intn) => fun(int * arr,int n)
    

    指针引用字符串

    展开全文
  • C语言程序的存储区域

    2018-02-26 10:58:41
    重点关注以下内容: C语言程序在内存中各个段的组成 C语言程序连接过程中的特性和常见错误 C语言程序的运行方式一:C语言程序的存储区域 由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-...

    重点关注以下内容: 
      C语言程序在内存中各个段的组成 
      C语言程序连接过程中的特性和常见错误 
      C语言程序的运行方式

    一:C语言程序的存储区域

      由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段。编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,连接过程则将各个源文件生成的二进制机器代码文件组合成一个文件。

      C语言编写的程序经过编译-连接后,将形成一个统一文件,它由几个部分组成。在程序运行时又会产生其他几个部分,各个部分代表了不同的存储区域: 
       
    1. 代码段(Code或Text) 
      代码段由程序中执行的机器代码组成。在C语言中,程序语句进行编译后,形成机器代码。在执行程序的过程中,CPU的程序计数器指向代码段的每一条机器代码,并由处理器依次运行。 
    2. 只读数据段(RO data) 
      只读数据段是程序使用的一些不会被更改的数据,使用这些数据的方式类似查表式的操作,由于这些变量不需要更改,因此只需要放置在只读存储器中即可。 
    3. 已初始化读写数据段(RW data) 
      已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并具有初值,以供程序运行时读写。 
    4. 未初始化数据段(BSS) 
      未初始化数据是在程序中声明,但是没有初始化的变量,这些变量在程序运行之前不需要占用存储器的空间。 
    5. 堆(heap) 
      堆内存只在程序运行时出现,一般由程序员分配和释放。在具有操作系统的情况下,如果程序没有释放,操作系统可能在程序(例如一个进程)结束后回收内存。 
    6. 栈(stack) 
      栈内存只在程序运行时出现,在函数内部使用的变量、函数的参数以及返回值将使用栈空间,栈空间由编译器自动分配和释放。

    C语言目标文件的内存布局

      看一个例子:

      int a = 0; //全局初始化区,。data段
      static int b=20; //全局初始化区,。data段
      char *p1; //全局未初始化区 .bss段
      const int A = 10; //.rodata段
      void main(void)
      {
          int b; //栈
          char s[] = "abc"; //栈
          char *p2; //栈
          static int c = 0; //全局(静态)初始化区 .data段
          char *p3 = "123456"; //123456\0在常量区,p3 在栈上。
          p1 = (char*) malloc(10);//分配得来的10和20个字节的区域就在堆区
          p2 = (char*) malloc(20);
          strcpy(p1, "123456"); //123456\0 在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方
      }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

      代码段、只读数据段、读写数据段、未初始化数据段属于静态区域,而堆和栈属于动态区域。代码段、只读数据段和读写数据段将在链接之后产生,未初始化数据段将在程序初始化的时候开辟,而堆和栈将在程序的运行中分配和释放。C语言程序分为映像和运行时两种状态。在编译-连接后形成的映像中,将只包含代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在程序运行之前,将动态生成未初始化数据段(BSS),在程序的运行时还将动态形成堆(Heap)区域和栈(Stack)区域。一般来说,在静态的映像文件中,各个部分称之为节(Section),而在运行时的各个部分称之为段(Segment)。如果不详细区分,可以统称为段。

      知识点:

      C语言在编译和连接后,将生成代码段(Text)、只读数据段(RO Data)和读写数据段(RW Data)。在运行时,除了以上三个区域外,还包括未初始化数据段(BSS)区域和堆(Heap)区域和栈(Stack)区域。

    二:C语言程序的段

    1.代码段(code或text)

      代码段由各个函数产生,函数的每一个语句将最终经过编绎和汇编生成二进制机器代码(具体生生哪种体系结构的机器代码由编译器决定)。

    2.只读数据段(RO Data)

      只读数据段由程序中所使用的数据产生,该部分数据的特点是在运行中不需要改变,因此编译器会将该数据段放入只读的部分中。C语言中的只读全局变量,只读局部变量,程序中使用的常量等会在编译时被放入到只读数据区。

      注意:定义全局变量const char a[100]={“ABCDEFG”};将生成大小为100个字节的只读数据区,并使用“ABCDEFG”初始化。如果定义为:const char a[ ]={“ABCDEFG”};则根据字符串长度生成8个字节的只读数据段(还有’\0’),所以在只读数据段中,一般都需要做完全的初始化。

    3.读写数据段(RW Data)

      读写数据段表示了在目标文件中一部分可以读也可以写的数据区,在某些场合它们又被称为已初始化数据段,这部分数据段和代码段,与只读数据段一样都属于程序中的静态区域,但具有可写性的特点。通常已初始化的全局变量和局部静态变量被放在了读写数据段,如: 在函数中定义static char b[ 100]={“ABCDEFG”};读写数据区的特点是必须在程序经过初始化,如果只定义,没初始值,则不会生成读写数据区,而会定位为未初始化数据区(BSS)。如果全局变量(函数外部定义的变量)加入static修饰,这表示只能在文件内使用,而不能被其他文件使用。

    4. 未初始化数据段(BSS)

      与读写数据段类似,它也属于静态数据区,但是该段中的数据没有经过初始化。因此它只会在目标文件中被标识,而不会真正称为目标文件中的一段,该段将会在运行时产生。未初始化数据段只在运行的初始化阶段才会产生,因此它的大小不会影响目标文件的大小。

      在C语言的程序中,对变量的使用还有以下几点需要注意:

      1.函数体中定义的变量通常是在栈上,不需要在程序中进行管理,由编绎器处理。 
      2.用malloc,calloc,realloc等分配内存的函数所分配的内存空间在堆上,程序必须保证在使用free释放,否则会发生内存泄漏。 
      3.所有函数体外定义的是全局变量,加了static后的变量不管是在函数内部或外部都放在全局区。 
      4.使用const定义的变量将放于程序的只读数据区。

    三:程序中段的使用

      下面用一个简单的例子来说明C语言中变量和段的对应关系。C语言程序中的全局区(静态区),实际对应着下述几个段:RO Data; RW Data ; BSS Data.

      一般来说,直接定义的全局变量在未初始化数据区,如果该变量有初始化则是在已初始化数据区(RW Data),加上const则将放在只读数据区。

    const char ro[ ] = {"this is read only data"}; //只读数据区
    static char rw_1[ ] ={"this is global read write data"}; //已初始化读写数据段
    char BSS_1[ 100]; //未初始化数据段
    const char *ptrconst ="constant data"; //字符串放在只读取数据段
    
    int main()
    {
      short b; //在栈上,占用2个字节
      char a[100]; //在栈上开辟100个字节, 它的值是其首地址
      char s[ ]="abcdefg"; //s在栈上,占用4个字节,"abcdefg"本身放置在只读数据存储区,占8个字节
      char *p1; //p1在栈上,占用4个字节
      char *p2="123456"; //p2 在栈上,p2指向的内容不能改,“123456”在只读数据区
      static char rw_2[ ]={"this is local read write data"};//局部已初始化读写数据段
      static char BSS_2[100]; //局部未初始化数据段
      static int c = 0; //全局(静态)初始化区
      p1=(char *)malloc(10 * sizeof(char ) ); //分配内存区域在堆区
      strcpy(p1,"xxxx"); //“XXXX”放在只读数据区,占5个字节
      free(p1); //使用free释放p1所指向的内存
      return 0;
    
    > 引用块内容
    
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

      读写数据段包含了忆初始化的全局变量 static char rw_1[ ]以及局部静态变量static rw_2[ ].其差别在于编绎时,是在函数内部使用的还是可以在整个文件中使用。对于rw_1[] 无论有无static 修饰,其都将被放置在读写数据区,只是能否被其它文件引用与否。对于后者就不一样了,它是局部静态变量,放置在读写数据区,如果没static修饰,其意义完全改变,它将会是开辟在栈空间的局部变量,而不是静态变量,在这里rw_1[],rw_2[]后没具体数值,表示静态区大小同后面字符串长度决定。

      对于未初始化数据区BSS_1[100]与BSS_2[100],其区别在于前者是全局变量,在所有文件中都可以使用;后者是局部变量,只在函数内部使用。未初始化数据段不设置后面的初始化数值,因此必须使用数值指定区域的大小,编绎器将根据大小设置BSS中需要增加的长度。

    栈空间主要用于以下3数据的存储: 
      1.函数内部的动态变量 
      2.函数的参数 
      3.函数的返回值

      栈空间是动态开辟与回收的。在函数调用过程中,如果函数调用的层次比较多,所需要的栈空间也逐渐加大,对于参数的传递和返回值,如果使用较大的结构体,在使用的栈空间也会比较大。

    展开全文
  • 适合职教高考计算机人员
  • C语言 排列组合问题

    2021-04-22 17:01:41
    编写程序,根据主函数内容,补充完成各函数定义,计算阶乘、组合数与排列数,并进行测试。 其中排列Pmn=m!/(m-n)!,组合Cmn=m!/(n!*(m-n)!)   #include "stdio.h&#...
  • 使用while(cin >> n),在devc++中无法输出结果 #include<iostream> using namespace std; int main(){ int N, n, sum; cin >> N; while(cin >> n){ sum += n * 11 *(N-1);......

    使用while(cin >> n),在devc++中无法输出结果

    #include<iostream>
    using namespace std;
    
    int main(){
        int N, n, sum;
        cin >> N;
        while(cin >> n){
            sum += n * 11 *(N-1);
        }
        cout << sum;
        return 0;
    }
    
    展开全文
  • C语言程序设计 目录

    2021-03-05 22:06:27
  • 课程的基本要求;如何学习C语言;...按照结构化程序设计的观点任何算法功能都可以通过由程序模块组成的三种基本程序结构的组合: 顺序结构选择结构和循环结构来实现 3种基本结构的特性 1)单入口 2)单出口 3)
  • 共用体及其应用C语言程序设计结构体C语言C语言程序设计 共用体及应用知识回顾结构体是一种构造数据类型用途把不同类型的数据组合成一个整体-------自定义数据类型结构体类型定义C语言C语言程序设计 共用体及应用问题...
  • C语言程序训练-1586-计算组合

    千次阅读 2018-11-01 18:37:12
    计算组合数。C(n,m),表示从n个数中选择m个的组合数。 计算公式如下: 若:m=0,C(n,m)=1 否则, 若 n=1,C(n,m)=1 否则,若m=n,C(n,m)=1 否则 C(n,m) = C(n-1,m-1) + C(n-1,m) Input 第一行是正整数N,表示有N组...
  • C语言组合数小程序

    2018-11-16 12:11:09
    //为组合数公式作准备 itema=cup(n); //以下同理,调用阶乘函数计算各个部分的阶乘 itemb=cup(m); itemc=cup(item1); item=itema*1.0/(itemb*itemc); //组合数公式的运用 printf("%f",item); return 0; } int...
  • C语言程序的内存布局

    2016-06-30 19:37:59
    由C语言代码(文本文件)形成可执行文件(二进制文件),需要经过编译(Compile)-汇编(Assembly)-链接(Link)3个阶段。编译器编译C代码生成汇编程序,汇编器把汇编程序...C语言程序和数据在内存中的存储通常分为5大部分:
  • c语言程序课程设计题目

    千次阅读 2019-07-18 11:43:00
    C语言程序设计》课程设计课题表 一、A类 1.职工信息管理系统设计 职工信息包括职工号、姓名、性别、年龄、学历、工资、住址、电话等(职工号不重复)。试设计一职工信息管理系统,使之能提供以下功能: 1、...
  • 在书写程序时,特别是对于While、for、do…while、if…elst、switch…case等语句或这些语句嵌套组合时,应采用“缩格”的书写形式, 2、标识符程序中使用的用户标识符除要遵循标识符的命名规则以外,一般不要用代数...
  • 华中科技大学计算机学院 C语言程序设计 第2章 数据类型运算符和表达式 C程序是一个字符序列字符序列先被分解为称之为记号token的词法元素再根据语法规则检查这些记号组合是否合法 本章首先介绍词法元素和语法规则的...
  • 编写一个递归函数f,计算组合Cnm。 (当m=n或n=0时,Cnm=1;否则,Cnm=m/(m—n)*Cnm-1)运行该程序,从键盘输入n和m,通过主函数调用f完成计算。
  • 一:C语言程序的存储区域 由C语言代码(文本文件)形成可执行程序(二进制文件),需要经过编译-汇编-连接三个阶段。编译过程把C语言文本文件生成汇编程序,汇编过程把汇编程序形成二进制机器代码,连接过程则将各个...
  • 程序中建立所需要结构体类型。例如: 指定了一个新的结构体类型struct student。 struct是声明结构体类型时所必须使用的关键字,不能省。 声明一个结构体类型的形式为: struct 结构体名 {成员表列}; 结构体类型...
  • 用这三种基本结构作为建筑单元通过组合和嵌套就能解决任何复杂的问题 即书上提到的多分支结构 * * * * * * * * 内存内存储器是微型计算机主机的组成部分用来存放当前正在使用的或随时要使用的程序或数据 CPU可以直接...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,375
精华内容 550
关键字:

c语言程序组合

c语言 订阅