常量:其值不能被改变的值
变量:运行过程中,可以改变的,对程序编译连接时由编译系统给每一个变量名分配对应的内存地址。从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据。先定义后使用
标识符:对变量、符号常量、函数、数组、类型等数据对象命名的有效字符序列;就是一个名字;只能由字母、数字和下划线3种字符组成,且第一个字符必须为字母或下划线。
数据类型
基本类型
整型
常量:十进制,八进制,以0开头,如0123,1*8的2次方+2*8的一次方+3,十六进制,以0x开头,如0x123,值是1*16的2次方+2*16的一次方+3。
变量:数据在内存中以二进制存放。以补码的形式表示,正数的补码和该数相同,负数的补码是该数的绝对值按照位取反再加1。通常以一个机器字(word)存放一个int数据,通常把long定为32位,把short定为16位,而int可以是16位也可以是32位。注意取值范围,溢出不会报错,只会影响结果。
字符型
常量:用单撇号括起来的字符如‘a’和转义字符
变量:只能放一个字符,在所有的编译系统中都规定以一个字节存放一个字符,以该字符对应的ASCII码存放在内存单元中。如‘a’的ASCII码为十进制97,在内存中以二进制形式存放的,与整数存储形式类似,这样使字符型数据和整型数据之间可以通用。一个字符型数据既可以以字符形式输出,也可以以整数形式输出。有些系统将字符变量定义为signed char,其存储单元最高位为符号位,如果不想按有符号处理,可以在程序中将字符变量定义为unsigned char类,与unsigned int 相仿,但是只有一个字节。
字符串
常量:以双撇号括起来的字符序列。‘\0’:字符串结束标志,是一个ASCII码为0的字符,空操作字符,它不引起任何控制操作,也不是一个可显示的字符。所以“a”在内存中占两个字节。
变量:没有专门的字符串变量,必须使用字符数组,数组中每一个元素存放一个字符。
浮点型
常量:有两种表示方式:十进制小数形式(必须有小数点);指数形式,e前面要有数字,e后面为整数。如1.234e2是规范写法,表示123.4。一般在内存中占4个字节,32位,按照指数形式存储的。在4个字节中,多少位存小数部分,多少位存指数部分,没有具体规定,由编译系统来定。
单精度型
双精度型
数组类型
一维数组的定义:类型说明符数组名【常量表达式】
一维数组元素的引用:数组名【下标】
一维数组的初始化:全部元素赋初始值,如int a[5]={1,2,3,4,5} int
a[5]={0,0,0,0,0} int a[5]={0} int a[]={1,2,3,4,5}。部分元素赋初始值inta[5]={1,2,3}后面补0
二维数组的定义:类型说明符 数组名【常量表达式】【常量表达式】
二维数组元素的引用:数组名【下标】【下标】
二维数组的初始化:全部元素赋初始值int a[3][4]={{1,2,3,4}{5,6,7,8}{9,10,11,12}}
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12} int a[][4]= {{1,2,3,4}{5,6,7,8}{9,10,11,12}}int a[][4]={1,2,3,4,5,6,7,8,9,10,11,12}。部分元素赋初始值 inta[3][4]={{1}{5}{0 9} int a[3][4]={{1}{0 5}} int a[][4]={{0 0 3}{}{5}} 其余的都补0。
字符串数组初始化:char a[]={“china”} char a[]={‘c’,’h’,’i’,’n’,’a’,’\0’}printf(“%s”,a) 按照数组名a找到数组起始地址,然后逐个输出直到遇到\0。printf(“%c”,a[0]) scanf(“%s”,a)
结构体类型
将不同类型的数据组合成一个有机的整体。
定义结构体类型变量:
1 先声明结构体类型再定义变量名
struct 结构体名
{成员列表}; 成员列表:类型名 成员名
struct 结构体名 结构体变量名
struct student{
int num;
char sex;
};
Struct student stu1 stu2;
2 在声明类型的同时定义变量定义变量
Struct student{
int num;
char sex;
}stu1,stu2;
3 直接定义结构体类型变量
Struct {
int num;
char sex;
}stu1,stu2;
结构体变量名.成员名
stu1.num &stu.num
&stu1:stu1的首地址
结构体变量的初始化
结构体变量的初始化
struct student
{
int num;
char sex;
}a={1,'M'};
结构体数组
struct student stu[3]={{1,'M'},{2,'M'},{3,'W'}};
指向结构体类型数据的指针
struct student stu1;
struct student *p;
p =&stu1;
stu.num等价于(*p).num等价于p->num
用结构体变量和指向结构体的指针作函数参数
#define FORMAT "%d"
{
struct student stu;
print(stu);
print1(&stu);
}
void print(struct student stu)
{
printf(FORMAT,stu.num);
}
void print1(struct student *p)
{
printf(FORMAT,p->num);
}
用指针处理链表
因为数组必须事先定义固定的长度,但是比如有的班级100人,有的班级30人,固定100人就有点浪费内存,用链表就没有这种缺点,它根据需要开辟内存单元,动态地进行存储分配。链表有一个"头指针"变量,存放一个地址,该地址指向一个元素,链表中每一个元素称为结点,每一个结点都应该包括两个部分:用户需要用的实际数据和下一个结点的地址。定义struct student类型时并不实际分配存储空间,只有定义了变量才分配内存单元。
eg:所有结点都是在程序中定义的,不是临时开辟的,也不能用完后释放,这种链表叫静态链表
#include <stdio.h>
#define NULL 0
struct student {
int num;
char sex;
struct student *next;
};
void main()
{
struct a,b,c,*head,*p;
a.num=1;
a.sex='M';
b.num=2;
b.sex='M';
c.num=3;
c.sex='W';
head=&a;
a.next=&b;
b.next=&c
c.next=NULL;
p=head;
do{
printf("%d,%c",p->num,p->sex);
p=p->next;
}while(p!=NULL);
动态分配存储:
void *malloc(unsigned int size);在内存的动态存储区中分配一个长度为size的连续空间,此函数的值(即返回值)是一个指向分配域起始地址的指针(类型为void),如果分配不成功则返回空指针。
void *calloc(unsigned n,unsigned size);在内存的动态存储区分配n个长度为size的连续空间,可以用来为一位数组开辟动态存储空间,n为数组元素个数,每个元素长度为size
void free(void *p);释放由p指向的内存区,使这部分内存区能被其他变量使用。
动态建立链表
#define LEN sizeof(struct student)
#define NULL 0
struct student {
int num;
char sex;
struct student *next;
};
struct student *creat(void)
{
struct student *head;
struct student *p1,p2;
p1=p2=(struct student *)malloc(LEN);
head = NULL;
scanf("%d,%c",&p1->num,&p1->sex);
while(p->num!=0)
{
n = n+1;
if(n==1) head=p1;
else p2->next=p1;
p2 = p1;
p1 = (struct student*)malloc(LEN);
scanf("%d,%c",&p1->num,&p1->sex);
}
p2->next=NULL;
return (head);
}
void main
{
creat();
}
共用体类型:几种不同类型的变量存放到同一段内存单元中。
枚举类型:如果变量只有几种可能的值,将变量的值一一列举出来
声明enum weekday{sun,mon,tue,wed,thu,fri,sat};
定义 enum weekday workday,week_end;
用typedef定义类型
用typedef声明新的类型名来代替已有的类型名
typedef int COUNT;COUNT i,j;
typedef long COUNT;便于移植
typedef struct {
int month;
int day
}DATE;
DATE birthday;
位运算
位段:C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为位段或者位域(bit field)eg:
struct packed_data{
unsigned a:2;
unsigned b:4;
unsigned c:6;
unsigned d:2;
int i;
}data;
其中a,b,c,d分别占2位,4位,6位,2位。i为整数,共占4个字节
struct packed_data data;
data.a = 2;注意位段可以赋的最大值,为2位最大值是3,所以data.a=8是错误的
data.b=7;
注意:
位段成员的类型必须指定为unsigned或int类型
指针:地址
变量的指针:变量的地址
指针变量:存放地址的变量
定义指针:基类型 *指针变量名 在定义指针变量时必须指定基类型,一个指针变量只能指向同一个类型的变量。
Eg:
voidswap(int *p1,int *p2)
{
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp
}
void main()
{
int a,b;
int *pointer_1,*pointer_2;//定义
icanf(“%d,%d”,&a,&b);
pointer_1 = &a;pointer_2=&b;//赋地址
if(a<b) swap(pointer_1,pointer_2);
printf(“%d,%d\r\n”,a,b);
}
数组与指针:
Eg:
void sort(int x[],int n) 或者void sort(int*x,int n)
void main(){int *p,a[10]; p =a ;sort(p,10);}
字符串与指针:
char a[]=”l love china”;
char *a = “I love china”;
char a[10]; char *p=a;
指向函数的指针变量:数据类型(*指针变量名)(函数参数列表):每一个函数都占用一段内存单元,他们有一个起始地址。函数名代表该函数入口。
int add (int x,int y)
void process(int a,inty,int(*fun)(int,int))
{
int result = (*fun)(x,y);
}
void main()
{
int a,b;
scanf(“%d,%d”,&a,&b);
process(a,b,add);
}
返回指针值的函数
类型名 *函数名(参数列表)
int *a(int x,int y);
eg:
float *search(float (*pointer)[4])
{
int i;
foat *pt;
pt = *(pointer + 1):
for (i=0;i<4;i++)
{
if(*(*pointer + i)<60) pt = *pointer;
return (pt);
}
}
void main()
{
float score[][4]={{60,70,80,90},{56,89,67,88},{34,78,90,66}};
float *search(float (* pointer)[4]);
float *p;
int I,j;
for(i=0;i<3;i++)
{
p =search(score+i);
if(p == *(score+i))
{
printf(“No.%d scores:”,i);
for (j=0;j<4;j++)
Printf(“%5.2f”,*(p+j));
}
}
}
指针数组和指向指针的指针
指针数组:其元素是指针类型数据,每一个元素相当于一个指针变量
类型名 *数组名[数组长度]
char *name[]={“follow”,”success”,”great”};
指向指针的指针:指向指针数据的指针变量
char **p
char *name[]={“follow”,”success”,”great”};
p=name+i;
指针数组做main函数的形参
void main(int argc,char*argv[])
main函数由操作系统调用的,argc指命令行中参数的个数,argv是一个指向字符串的指针数组。Main函数的形参不一定命名为argc和argv,可以是任意的名字,只是人们习惯了argc和argv。argc指命令行中参数的个数
echo命令实现:
echo.c:
#include <stdio.h>
void main (int argc,char *argv[])
{
while(--argc>0)
printf(“%s%c”,*++argv,(argc>1)?’’:’\n’);
}
echo computer and c language
输出 computer and c language
argc为5, arcgv[0]:echo ,argv[1]:computer
void main()
{
char *p;
scanf("%s",p);
}
没有对p赋值就引用它是错误的,应该改为:
void main()
{
char *p,c[20];
p=c;
scanf("%s",p);
}
void main()
{
char c[20];
printf("%c",c++); 错误c是数组名,是首地址,是固定的。应该用指针char *p=c;p++;
}
