什么是内存?
内存的基本概念
(地址的常用表示为十六进制表示法,即Ox+十六进制数)
由这个图可以清晰的发现对于每一段的内存中的数据,都有一个地址与之相对应,也真是因为有地址的存在,我们计算机中才可以轻易的去访问到其中数据。
什么是数据类型 ?
在 C 语言中,数据类型指的是用于声明不同类型的变量或函数的一个广泛的系统。变量的类型决定了变量存储占用的空间,以及如何解释存储的位模式。
“ C”提供了各种数据类型,使程序员可以轻松地根据应用程序的需求选择合适的数据类型。 以下是三种数据类型:
- 基本数据类型
- 构造(派生)数据类型
- 用户定义的数据类型
基本类型
最主要的特点是,其值不可以再分解为其它类型。也就是说,基本数据类型是自我说明的有五种主要的基本数据类型:
- int – 整数数据类型
- char – 字符数据类型
- float – 浮点数据类型
- double – 表示双精度浮点数据类型
- void – 没有可用价值
构造类型
构造数据类型是根据已定义的一个或多个数据类型用构造的方法来定义的。也就是说,一个构造类型的值可以分解成若干个“成员”或“元素”。每个“成员”都是一个基本数据类型或又是一个构造类型。在 C 语言中,构造类型有以下几种:
- 数组类型
- 结构体类型
- 共用体(联合)类型
指针类型
指针是一种特殊的,同时又是具有重要作用的数据类型。其值用来表示某个变量在内存储器中的地址。虽然指针变量的取值类似于整型量,但这是两个类型完全不同的量,因此不能混为一谈。
空类型
在调用函数值时,通常应向调用者返回一个函数值。这个返回的函数值是具有一定的数据类型的,应在函数定义及函数说明中给以说明,例如在例题中给出的 max函数定义中,函数头为:int max(int a,int b);其中“int ”类型说明符即表示该函数的返回值为整型量。又如在例题中,使用了库函数 sin,由于系统规定其函数返回值为双精度浮点型,因此在赋值语句 s=sin (x);中,s 也必须是双精度浮点型,以便与 sin 函数的返回值一致。所以在说明部分,把 s 说明为双精度浮点型。但是,也有一类函数,调用后并不需要向调用者返回函数值,这种函数可以定义为“空类型”。其类型说明符为 void。在后面函数中还要详细介绍。
什么是变量?
变量其实只不过是程序可操作的存储区的名称。C 中每个变量都有特定的类型,类型决定了变量存储的大小和布局,该范围内的值都可以存储在内存中,运算符可应用于变量上。变量定义必须放在变量使用之前。一般放在函数体的开头部分。要区分变量名和变量值是两个不同的概念。
变量的名称可以由字母、数字和下划线字符组成。它必须以字母或下划线开头。大写字母和小写字母是不同的,因为 C 是大小写敏感的。
单个变量可以在程序中的多个位置使用。 变量名必须有意义。 它应该代表变量的目的。
以下是创建变量时必须遵循的规则:
- 变量名称应仅包含字符,数字和下划线。
- 变量名不能以数字开头。
- 变量名称不应包含空格。
- 变量名不应包含关键字。
- “ C”是区分大小写的语言,表示名为“ age”和“ AGE”的变量是不同的。
下列变量名是无效的:
1height Hei$ght My name
在声明变量名之前,程序必须声明它的数据类型。一边计算机知道给它分配多大的存储单元。
当编译器读到char变量时,自动赋给它一个字节(8Bits)依次类推。
以下程序声明变量为整数,并赋值48.
int my_variable; //声明 my_variable = 48; //赋值
我们也可以把声明和赋值连在一起:
int my_variable = 48; //声明和赋值
“ C”语言提供了上述主要的基本数据类型的更多扩展版本。 每种数据类型的大小和范围都不同。
下表列出了关于标准整数类型的存储大小和值范围的细节:
整数类型
整形数据在内存中的存放形式:
1)基本型:类型说明符为 int,在内存中占 2 个字节。
2) 短整型:类型说明符为 short int 或 short。所占字节和取值范围均与基本型相同
3) 长整型:类型说明符为 long int 或 long,在内存中占 4 个字节
4)无符号型:类型说明符为 unsigned。
无符号型又可与上述三种类型匹配而构成
- 无符号基本型:类型说明符为 unsigned int 或 unsigned
- 无符号短整型:类型说明符为 unsigned short
- 无符号长整型:类型说明符为 unsigned long。
各种无符号类型量所占的内存空间字节数与相应的有符号类型量相同。但由于省去了符号位,故不能表示负数。
下表列出了关于标准整数类型的存储大小和值范围的细节:
类型 | 存储大小(占字节数) | 表示的数据范围 |
---|---|---|
char | 1 字节 | -128 到 127 |
unsigned char | 1 字节 | 0 到 255 |
signed char | 1 字节 | -128 到 127 |
int or signed int | 2 字节 | -32,768 到 32,767 |
short int or unsigned short int | 2 字节 | 0 到 255 |
signed short int | 2 字节 | -218 – 127 |
long int or Signed long int | 4 字节 | -2147483648 到 2147483647 |
unsigned long int | 4 字节 | 0 到 4294967295 |
float | 4 字节 | 3.4E-38 到 3.4E+38 |
double | 8 字节 | 1.7E-308 到 1.7E+308 |
long double | 10 字节 | 3.4E-4932 到 1.1E+4932 |
注意,C语言没有布林数据类型
为了得到某个类型或某个变量在特定平台上的准确大小,您可以使用 sizeof 运算符。表达式 sizeof(type) 得到对象或类型的存储字节大小。我们使用的CODE-BLOCKs编译平台是最新的编译器。数据存储范围就明显扩大了。
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main() { printf("size of int : %d\n",sizeof(int)); printf("size of char : %d\n",sizeof(char)); printf("size of signed char : %d\n",sizeof(signed char)); printf("size of unsigned char : %d\n",sizeof(unsigned char)); printf("size of short : %d\n",sizeof(short)); printf("size of short int : %d\n",sizeof(short int)); printf("size of signed short : %d\n",sizeof(signed short)); printf("size of signed short int : %d\n",sizeof(signed short int)); printf("size of long int : %d\n",sizeof( long int)); printf("size of float : %d\n",sizeof(float)); printf("size of double : %d\n",sizeof(double)); printf("size of long double : %d\n",sizeof(long double)); return 0; }
stdlib.h里面定义了五种类型、一些宏和通用工具函数。
下面给出的示例示范程序利用limits.h头文件中定义的不同常量,可以获取计算机上各种数据类型的大小-
#include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main(int argc, char** argv) { printf("CHAR_BIT : %d\n", CHAR_BIT); printf("CHAR_MAX : %d\n", CHAR_MAX); printf("CHAR_MIN : %d\n", CHAR_MIN); printf("INT_MAX : %d\n", INT_MAX); printf("INT_MIN : %d\n", INT_MIN); printf("LONG_MAX : %ld\n", (long) LONG_MAX); printf("LONG_MIN : %ld\n", (long) LONG_MIN); printf("SCHAR_MAX : %d\n", SCHAR_MAX); printf("SCHAR_MIN : %d\n", SCHAR_MIN); printf("SHRT_MAX : %d\n", SHRT_MAX); printf("SHRT_MIN : %d\n", SHRT_MIN); printf("UCHAR_MAX : %d\n", UCHAR_MAX); printf("UINT_MAX : %u\n", (unsigned int) UINT_MAX); printf("ULONG_MAX : %lu\n", (unsigned long) ULONG_MAX); printf("USHRT_MAX : %d\n", (unsigned short) USHRT_MAX); return 0; }
下面示例示范程序是如何储存char和整数的。
include <stdio.h> int main() { char a = 278; printf("%d", a); return 0; }
原因: 首先,编译器在内部将278从十进制数系统转换为二进制数系统(100010110),然后仅考虑该数字右边以二进制表示的前8位,并将此值存储在变量a中。 它还会发出溢出警告。(如何将十进制278转换为二进制(100010110),请看本页下面注释。
00010110对应的十进制数是22. (计算方法简单,该位置的值乘于对应位置的2次方相加)
再看一个例子:
#include <stdio.h> int main() { char a = -129; printf("%d", a); return 0; }
结果
首先,应该理解,负数以2的补码形式存储。 编译器在内部将129从十进制系统转换为二进制系统(10000001),然后将所有零都更改为1,将1全都更改为零(即做一个补码)(01111110),然后将1添加到一个补码中 通过二进制加法得到该数字的二进制补码(01111111)。 现在,将取两个补数的最右边的8位,并将其原样存储在变量a中。 它还会发出溢出警告。
整形变量的溢出
main() { int a, b; a=32767; b=a+1; printf("%d, %d\n",a,b); }
在code:block编译器内,整形变量不是赋值两节。我们试一下是否是四节:
main() { int a, b; a=2147483647; b=a+1; printf("%d, %d\n",a,b); }
原因是32个bits中有三十一个是一,加一后符号位是一,其余全是零。实际上是溢出了。
整数数据类型
整数就是整数。 整数数据类型的范围因计算机而异。 整数数据类型的标准范围是-32768到32767。(15个二相乘),第一位是符号。整数通常为2个字节,这意味着它在内存中总共消耗16位。 一个整数值占用2个字节的内存。但最新的编译器的整形变量已经分配了四个字节。
整数数据类型进一步分为其他数据类型,例如short int,int和long int。
每种数据类型都属于整数数据类型族,即使范围不同。 对于整数族的每种数据类型,大小可能不会更改。short int主要用于存储较小的数字,int用于存储平均大小的整数值,long int用于存储较大的整数值。
每当我们要使用整数数据类型时,我们都会在标识符前加 “int” 例如,
int age
age就是一个可以储存整数值的整数类型变量。
浮点(实型)数据类型
像整数一样,在“ C”程序中,我们也可以使用浮点数据类型。 ‘float’关键字用于表示浮点数据类型。 它可以保存浮点值,这意味着数字具有分数和小数点部分。 浮点值是包含小数点的实数。 整数数据类型不存储小数点部分。
它有二种形式:
- 十进制小数形式,
- 指数形式。
1)十进制数形式:由数码 0~ 9 和小数点组成。
2)指数形式:由十进制数,加阶码标志“e”或“E”以及阶码(只能为整数,可以带符号)组成。其一般形式为:
a E n(a 为十进制数,n 为十进制整数)(其值: a*10n)
-
- 2.1E5 (等于 2.1*105)
浮点数据类型在内存中的存放形式
实型数据一般占 4 个字节(32 位)内存空间。按指数形式存储。实数 3.14159 在内存中的存放形式如下:
- 小数部分占的位(bit)数愈多,数的有效数字愈多,精度愈高
- 指数部分占的位数愈多,则能表示的数值范围愈大。
使用浮点数时,必须在标识符之前放置关键字单精度(float) / 双精度(double) /长双精度 (long double)。
有效的例子是:
float division; double BankBalance;
浮点数的存储和浮点数有效数字及浮点数范围
下列图表给出浮点数的字节,范围大小和精度。
单精度型占 4 个字节(32 位)内存空间,其数值范围为 3.4E-38~3.4E+38,双精度型占 8 个字节(64 位)内存空间,其数值范围为 1.7E-308~1.7E+308,可提供 16 位有效数字。
float头文件 – C 标准库的 float.h 头文件包含了一组与浮点值相关的依赖于平台的常量。
Live Demo #include <stdio.h> #include <stdlib.h> #include <limits.h> #include <float.h> int main(int argc, char** argv) { printf("Storage size for float : %d \n", sizeof(float)); printf("FLT_MAX : %g\n", (float) FLT_MAX); printf("FLT_MIN : %g\n", (float) FLT_MIN); printf("-FLT_MAX : %g\n", (float) -FLT_MAX); printf("-FLT_MIN : %g\n", (float) -FLT_MIN); printf("DBL_MAX : %g\n", (double) DBL_MAX); printf("DBL_MIN : %g\n", (double) DBL_MIN); printf("-DBL_MAX : %g\n", (double) -DBL_MAX); printf("Precision value: %d\n", FLT_DIG ); return 0; }
在C语言中 int main (int argc, char *argv[])
argc指示程序启动时命令行参数的个数。
argv则包含具体的参数字符串。
例如:
如果有程序叫“hello.exe”,直接启动时,argc=1, argv[0]=hello.exe。
如果以“hello.exe readme.txt”的形式启动,argc=2, argv[0]=hello.exe, argv[1]=readme.txt
通过这两个参数,程序可以获知自身在启动时的命令行信息。
实型数据的舍入误差
由于实型变量是由有限的存储单元组成的,因此能提供的有效数字总是有限(7位)的。实型数据的舍入误差. 请看下例:
main() { float a,b; a=123456.789e5; b=a+100; printf("%f\n%f\n",a,b); }
字符数据类型
字符数据类型用于存储用单引号引起来的单个字符值。
字符数据类型最多占用1个字节的存储空间。
例,
Char letter;
VOID数据类型
void数据类型不包含或返回任何值。 它主要用于定义“ C”语言中的函数。
例,
void displayData()
实例:
int main() { int x, y; float salary = 13.48; char letter = 'K'; x = 25; y = 34; int z = x+y; printf("%d \n", z); printf("%f \n", salary); printf("%c \n", letter); return 0;}
%d,d 是 decimal 的缩写,意思是十进制数,%d 表示以十进制整数的形式输出
%d称为格式控制符,它指明了以何种形式输出数据。格式控制符均以%开头,后跟其他字符。
- %d 表示以十进制形式输出一个整数
- %c:输出一个字符。c 是 character 的简写
- %s:输出一个字符串。s 是 string 的简写
- %f:输出一个小数。f 是 float 的简写
常量
常量是固定值,在程序执行期间不会改变。这些固定的值,又叫做字面量。
常量可以是任何的基本数据类型,比如整数常量、浮点常量、字符常量,或字符串字面值。
常量就像是常规的变量,只不过常量的值在定义后不能进行修改。
整数常量
整型常量就是整常数。在C语言中,使用的整常数有八进制、十六进制和十进制三种。
一)十进制整常数:
十进制整常数没有前缀。其数码为 0~9。
以下各数是合法的十进制整常数:
237、-568、65535、1627;
以下各数不是合法的十进制整:
023 (不能有前导 0)、23D (含有非十进制数码)
二) 八进制整常数:
必须以 0 开头,即以 0 作为八进制数的前缀。数码取值为 0~7。
合法的八进制数:
015(十进制为 13)、0101(十进制为65)、0177777(十进制为 65535);
不合法的八进制数:
256(无前缀 0)、03A2(包含了非八进制数码)、-0127(出现了负号)。
三)十六进制的整常数
十六进制整常数的前缀为 0X 或 0x。其数码取值为 0~9, A~F,或a~f。
合法的十六进制整常数:
0X2A(十进制为 42)、0XA0(十进制为 160)、0XFFFF (十进制为 65535)
不合法的十六进制整常数:
5A (无前缀 0X)、0X3H (含有非十六进制数码)。
整型常数的后缀:在 16 位字长的机器上,基本整型数的范围也是有限定的。十进制无符号整常数的范围为 0~65535,有符号数为-32768~+32767。八进制无符号数的表示范围为 0~0177777。十六进制无符号数的表示范围为 0X0~0XFFFF 或 0x0~0xFFFF。如果使用的数超过了上述范围,就必须用长整型数来表示。长整型数是用后缀“L”或“l”来表示的。
八进制或十六进制的常量在C语言中很少使用,如果将来碰到,我们在进一步阐述。
浮点常量
浮点常量由整数部分、小数点、小数部分和指数部分组成。您可以使用小数形式或者指数形式来表示浮点常量。
当使用小数形式表示时,必须包含整数部分、小数部分,或同时包含两者。当使用指数形式表示时, 必须包含小数点、指数,或同时包含两者。带符号的指数是用 e 或 E 引入的。
字符常量
字符常量是括在单引号中,例如,’x’ 可以存储在 char 类型的简单变量中。我们还可以通过提供ASCII值来表示字符常量。
转义字符
字符常量可以是一个普通的字符(例如 ‘x’)、一个转义序列(例如 ‘\t’),或一个通用的字符(例如 ‘\u02C0’)。
在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。下表列出了一些这样的转义序列码:
在 C 中,有一些特定的字符,当它们前面有反斜杠时,它们就具有特殊的含义,被用来表示如换行符(\n)或制表符(\t)等。下表列出了一些这样的转义序列码:
下面的实例显示了一些转义序列字符:
转义字符
|
意义
|
ASCII码值(十进制)
|
\a
|
响铃(BEL)
|
007
|
\b
|
退格(BS) ,将当前位置移到前一列
|
008
|
\f
|
换页(FF),将当前位置移到下页开头
|
012
|
\n
|
换行(LF) ,将当前位置移到下一行开头
|
010
|
\r
|
回车(CR) ,将当前位置移到本行开头
|
013
|
\t
|
水平制表(HT) (跳到下一个TAB位置)
|
009
|
\v
|
垂直制表(VT)
|
011
|
\\
|
代表一个反斜线字符”\’
|
092
|
\’
|
代表一个单引号(撇号)字符
|
039
|
\”
|
代表一个双引号字符
|
034
|
\? | 代表一个问号 | 063 |
\0
|
空字符(NUL)
|
000
|
\ddd
|
1到3位八进制数所代表的任意字符
|
三位八进制
|
\xhh
|
十六进制所代表的任意字符
|
十六进制
|
#include <stdio.h> int main() { printf("Hello\tWorld\n\n"); return 0; }
字符串常量
字符串常量包含用双引号(“”)括起来的一系列字符。
例如, “Hello”, “Programming”
实数常量
整数常量总是包含一个整数值。 “ C”还提供了包含小数点或分数值的实常数。 实常数也称为浮点常数。 实常数包含小数点和小数值。
例如: 202.15, 300.00
定义常量
在 C 中,有两种简单的定义常量的方式:
- 使用 #define 预处理器
- 使用 const 关键字
1. 使用const 关键词:
#include <stdio.h> int main() { const double PI = 3.14; printf("%f", PI); //PI++; // 结果出现错误,因为常数无法修改 return 0;}
2. 使用 #define 预处理器
#include <stdio.h> #define PI 3.14 int main() { printf("%f", PI); return 0;}
其中#define 也是一条预处理命令(预处理命令都以”#”开头),称为宏定义命令(在后面预处理程序中将进一步介绍),其功能是把该标识符定义为其后的常量值。一经定义,以后在程序中所有出现该标识符的地方均代之以该常量值。
习惯上符号常量的标识符用大写字母,变量标识符用小写字母,以示区别。
用标识符代表一个常量,称为符号常量。
- 符号常量与变量不同,它的值在其作用域内不能改变,也不能再被赋值。
- 使用符号常量的好处是:
- 含义清楚;
- 能做到“一改全改”
C语言中%d, %o, %f, %e, %x的意义
格式说明由“%”和格式字符组成,如%d%f等。它的作用是将输出的数据转换为指定的格式输出。
格式说明总是由“%”字符开始的。不同类型的数据用不同的格式字符。
格式字符有d,o,x,u,c,s,f,e,g等。
如
- %d整型输出,%ld长整型输出,
- %o以八进制数形式输出整数,
- %x以十六进制数形式输出整数,
- %u以十进制数输出unsigned型数据(无符号数)。
- %c用来输出一个字符,
- %s用来输出一个字符串,
- %f用来输出实数,以小数形式输出,
- %e以指数形式输出实数,
- %g根据大小自动选f格式或e格式,且不输出无意义的零。
摘要:
- 常数是在程序执行期间值不会改变。
- 变量是用于存储值的标识符。
- 有四种常用的数据类型,例如int,float,char和void。
- 每种数据类型的大小和范围互不相同。
如何将十进制278转换为二进制(100010110)
在这里,我们将逐步向您展示如何将十进制数278转换为二进制数。
首先,请注意,十进制数字使用10位数字(0、1、2、3、4、5、6、7、8和9),而二进制数字仅使用2位数字(0和1)。
当我们解释将278转换为二进制的步骤时,重要的是要知道除法问题各部分的名称。在一个问题中,例如A除以B等于C,A是被除数,B是除数,C是商。
商有两个部分。整数部分和小数部分。小数部分也称为余数。
步骤1)将278除以2得到商。保留商的整数部分用于下一步,并将余数(0或1)放在最右边位置。
步骤2)将步骤1的商的整数部分除以2,整数部分再去除于二,把余数放在右边倒数第二位置。
步骤3)重复上述步骤2,直到“商”为0。
步骤4)以相反的顺序写下余数,以二进制的方式获得278的答案。
在这里,我们将展示我们的工作,以便您可以继续:
278/2 = 139,余数为0
139/2 = 69,剩余1个
69/2 = 34,剩余1个
34/2 = 17,余数为0
17/2 = 8,余下1
8/2 = 4,余数为0
4/2 = 2,余数为0
2/2 = 1,剩余0
1/2 = 0,剩余1
然后,当我们以相反的顺序将余数部分放在一起时,我们得到了答案。因此,转换为二进制的十进制数278为:
100010110