您的位置:首页 > 其它

C 语言基础

2016-01-13 18:11 323 查看

前言

C语言写的程序,无处不在,大到计算机操作系统,windows,Unix,linux,各种嵌入式设备等等,小到计算器;C语言作为在各种设备上大量运行的程序的编程语言,在设计之初就大放异彩,并被很多大学作为计算机科学与技术专业甚至是一些非计算机专业,做为计算机编程基础课程;C语言由于其设计的灵活、靠近硬件,能 解决很多基础问题,被程序员们所喜爱。在Android 开发中,ndk开发作为一种让程序员更好控制硬件和计算资源,在google在Android开发的早期阶段都已经支持,市面上很多Android 应用,处于某些考虑,均大量有使用这种开发模式。C语言作为ndk开发的语言,学习好C,自然是必要的了;

知识预备

1.ASCII码



2.各种进制

.二进制,八进制,十进制,十六进制及转化

计算机系统使用的基本上是二进制系统。数字以 ,二进制表示,

比如 9;其二进制,就是 111 ;

计算方法:

9/2=4 余数:1

4/2=2 余数:0

2/2=1 余数 :0

1/2 =0 余数:1;

直到商为0,将余数逆向排列,即得到 其二进制;

得到 9的二进制 1001;

将小数转化成二进制

十进制小数转换成二进制小数采用"乘2取整,顺序排列"法。具体做法是:用2乘十进制小数,可以得到积,将积的整数部分取出,再用2乘余下的小数部分,又得到一个积,再将积的整数部分取出,
如此进行,直到积中的小数部分为零,此时0或1为二进制的最后一位。或者达到所要求的精度为止。
比如:0.5 其二进制,就是:(0.1)B
0.5*2=1,取出整数1;
比如:0.25 其二进制 ,就是:(0.01)B
0.25 *2=0.5;取出整数  0;
0.5*2=1; 取出整数 1;


3.源码、反码、补码的概念及相关

整数的补码是其二进制,比如:+9,的补码0000 1001;(前面的 0000,是符号位)
0.3.2负数的补码
将其对应正数二进制表示所有位取反(包括符号位,0变1,1变0)后加1;
比如:-9,源码:0000 0111,->反码:1111 1000,->补码:1111 1001;
比如:-5,源码:0000 0101,->反码:1111  1010,->补码:11111 1011;
0.3.3已知一个补码,求其源码;
已知一个数的补码,求原码的操作其实就是对该补码再求补码:
如果补码的符号位为“0”,表示是一个正数,其原码就是补码。
如果补码的符号位为“1”,表示是一个负数,那么求给定的这个补码的补码就是要求的原码。

比如,已知补码:1111 1001。求其源码:
知其符号位为"1",为负数 ,求其补码:0000 0110  再加1;0000 0111,知道为数字 9,带上符号为:-9;
在比如,已知补码:11111 1011。求其源码;
知道符号位为“1”,负数, 0000 0100 在加1;0000  0101 知道为数字 5,带上符号 :-5;


基本语法

数据类型

基本类型
1.正型  short  ,int long
2.浮点型 float  double
3.字符型 char
4.void
5.指针型 **
6.结构体和联合
1.1.正型根绝修饰符的不同,可是分为有符号和无符号的一下类型(短整型和长整形);
signed  short int  ;//可以简单的写成:short 或  int ;取值范围为:-32768~2767;十六位两个字节
signed  long  int ;//可以简单的 :long  ;取值范围为:-2147483648~2147483647;三十二位四个字节
unsigned  short int ;// unsigned int;  取值范围0~65535 十六位两个字节
unsigned  long  int ;// unsigned  long  ; 取值范围:0~4294967295  十六位两个字节

2.1浮点型,根据精度分为:单精度浮点型和双精度浮点型;
float  32为 4个字节,数值的取值范围是:3.4x10-38E~3.4x10+38E;
double  64 为 8个字节,数值的取值范围是:1.7x10-308E~1.7x10+308E;
单精度浮点数的精度为:6位;
双精度浮点数的精度为:7位
计算的时候,单精度有精度损失,一般采用,双精度,但是双精度,
计算的时候,因为位数比较长,比较消耗计算资源;
3.1字符型
8位,一个字节,
根据有无符号,分为:  signed  char  ,unsigned  char;
取值范围分别为:-128~127,0~255;
4.1 void
5.1指针类型
根据实际类型,可分为:
int *;
float  *;
char  *;
struct *;结构体指针;
union * 联合体指针;


变量的类型

根据变量的定义位置分为:

全局变量:定义在main函数外,如果没有初始化,数字类型变量默认值为:0,字符型和指针型默认为:NULL;

局部变量:定义在函数内部,如何没有初始化,默认为随机赋值;

参数变变量:定义在函数参数列表;

三,函数的定义

在c语言中定义一个函数,一般是写在main函数之前;在函数使用之前,需要在全局声明

关键字与标识符定义

关键字:auto double int struct break else
long switch case enum register typedef
char extern return union const float
short unsigned continue for signed void
default goto sizeof volatile do if
while static
表示含义:
auto :声明自动变量
break:跳出当前循环
case:开关语句分支
char :声明字符型变量或函数返回值类型
const :声明只读变量
continue:结束当前循环,开始下一轮循环
default:开关语句中的“其它”分支
do :循环语句的循环体
double :声明双精度浮点型变量或函数返回值类型
else :条件语句否定分支(与 if 连用)
enum :声明枚举类型
extern:声明变量或函数是在其它文件或本文件的其他位置定义
float:声明浮点型变量或函数返回值类型
for:一种循环语句
goto:无条件跳转语句
if:条件语句
int: 声明整型变量或函数
long :声明长整型变量或函数返回值类型
register:声明寄存器变量
return :子程序返回语句(可以带参数,也可不带参数)
short :声明短整型变量或函数
signed:声明有符号类型变量或函数
sizeof:计算数据类型或变量长度(即所占字节数)
static :声明静态变量
struct:声明结构体类型
switch :用于开关语句
typedef:用以给数据类型取别名
unsigned:声明无符号类型变量或函数
union:声明共用体类型
void :声明函数无返回值或无参数,声明无类型指针
volatile:说明变量在程序执行中可被隐含地改变
while :循环语句的循环条件


标识符定义规则:

和Java一样,C 的标识符定义也是这样的规则:

1标识符的开头必须是以字母、下划线,不能使用特殊字符和数字开头;

2标识符有大小写字母和数字组成区分大小写

3标识符只有钱32位有效

4标识符不能使用关键字;

基本语句

for 循环
whlie 循环
do  whlie 循环
goto
bread;
continue;
case;
default;
switch;


注意:和java 不一样的,循环变量的初始化放在循环体外面;

指针

指针的概念:所谓变量的指针,实际上指变量的地址。
指针变量:向这要定义一个指向变量地址的一个变量,叫做指针变量;
1指针变量的地址;
比如,我们定义一个变量 :
int  a ,b,*a1=&a;

a=10;
b=*p;
那么我们打印一下a1=?  b?其意义是这样的:定义变量,a,和指针变量a1,将a的地址赋值给指针变量a1;
打印出来的结果是一个地址,可以知道,指针变量是保存的一个地址,而不是数值,所以:
a1=20;
这样的赋值给 a1,是会报错的;
在看打印出来  b=?
打印结果:b=20;
我们可以得出结论:
1.1可以将指针变量复制给普通变量,表示将该指针指向的数字赋值给该普通变量;
1.2.将普通变量复制给指针变量 ,会标错,进一步明确,指针变量,这能赋值给指针变量;

2地址运算:
2.1指针的比较
满足两个指针变量可比较的条件是,他们指向同一个变量;比如:int  a,*a1,*a2;a1=&a;a2=&a; int res=(a1==a2?1;0);
测试结果:1;
2.2指针的算符运算
前面我们已经测试,知道,指针指向一个变量,可用指针来和普通变量混合参与运算。下面我们写一个函数来测试结论;


数组

1.C 语言中数组的定义:
int  arr[10];
char  arr1[15];
long arr3[15];
float arr4[20];
double arr5[15];
int * arr6[10];
注意:  int (*p)[5];这个是数组指针,不是指针数组;

2数组的使用;
2.1一维数组的初始化;
这样:
int  arr[5]={1,2,,3,4,5};
or  like this:
int  arr[]={1,2,3};
2.2多为数组:
多维数组的定义使用和一维数组没有什么区别;
2.3数组与指针:
可以说,任何一个数组都可是都可以用指针来表示,但是他们绝对不是一个概念;
设想一下:
一般我们定义了一个数组变量,那么,计算机就在,内存给我们分配一块连续的区域;
指针也代表了一段内存位置中的一个节点,so,
如果我们将这个节点指向数组的头节点,然后依次移动指针,就可以获得数组中的元素;
这样说还是有些抽象,下面我们来下个代码测试;

2.4一些概念的区别:
指针数组和数组指针?
区别老大了;


结构体和联合体

8.1结构体

结构体的定义:使用关键字 struct做形似如下的代码块,我们称之为结构体,类似于java中的类;

struct 结构名
{
类型 变量名;
类型 变量名;
...
} 结构变量;
比如:
struct Person{
char[] *name;
int sex;
double grade;
}
struct Person  yang,li,zhang,wang;


这里有两种声明方式:

8.1.1声明结构体的同时,指定变量名称;

形如:

struct Person{
char[] *name;
int sex;
double grade;
} li;


8.1.2单单只声明结构体,然后在使用时再 分别指定变量名称;

形如:

struct Person{
char name;
int sex;
double grade;
}
struct  Person  yang,li,zhang;


8.2结构体变量的使用

下面我们来写代码测试结构体的使用;

8.2.1结构体内部变量的访问

例如:

yang.name='y';
yang.sex=1;
yang.grade=100;


8.3结构数组和结构指针

结构体数组和普通数组一样,只时类型是结构体类型的了;

我们来重点说说,结构体指针

8.3.1结构体指针

定义:结构指针是指向结构的指针。

形如:

struct Person{
char name[10];
int  gender;
int age
}* person


结构体指针的赋值:

原本写法:

strcp((*person).name,"yangliang");
(*person).age=18;


简写:

strcp(person->name,"yangliang");//注意这个数组赋值函数;
person->age=18;


8.3.2位结构

typeDef  struct{
int a;
....
}  oBject;


8.4联合体与枚举

8.4.1和结构体的区别是

1:联合体所有变量保存在一段内存地址中.

2:这段内存内存地址的 长度 是由联合中占用内存最大的变量类型决定的;

3.修改联合体中的变量的某一个,则其他的变量值会被擦除;

8.4.2枚举

enum string
{
x1,
x2=0,
x3=50,
x4,
}x;
则x1=0, x2=0, x3=50, x4=51


注意:

1.枚举中每个成员(标识符)结束符是”,”,不是”;”,最后一个成员可省略”,”。

2.初始化时可以赋负数,以后的标识符仍依次加1。

3.枚举变量只能取枚举说明结构中的某个标识符常量。

这样就可以直接定义结构数组和指针数组oBject;

预处理命令

由ANSI的标准规定,预处理指令主要包括:

#define
#error
#if
#else
#elif
#endif
#ifdef
#ifndef
#undef
#line
#pragma


define 是宏定义指令;

它的定义范式是这样的: #define 要替换的数值 替换成的数值

注意:宏定义的定义语句,结构是没有“;”

函数

输出和输入语句
printf("请输入一个整数");
输出数据的格式化
printf("name=%s,age=%d,grade=%f,levele=%c");
输出:字符串,整数,小数,字符;
scantf("a=%d",&a);


基础代码测试代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int com_num;
long com_num2;
float com_fnum;
double com_fnum2;
char com_c;
char *c0;
int testFunction(int,int );
void testBaseFunction(int );
void testGotoKeyWords(void);
void testPoint(void );
void testPointBj(void);
void testPointArithmeticOperation(void);
void testArraCommonUse(void);
void testArrayInnite(void);
void testArrayAndPointer(void);
void testPointMove(void);
void testStructDef(void);
void testStructVarUse(void);
void testStructUse(void);
void testUnionDef(void);
void testUnionPointer(void);
void testEnum(void);
#define MyMax(a,b) (a>b? a:b)
//测试宏定义
void testDefine(){
int result=MyMax(7,1);
printf("TEST DEFINE USE");
printf("result=%d",result);
}
enum week{
Monday=0,
Teusday=1,
Wensday=2,
Thursday=3,
Friday=4,
};

int testAdd(int a,int b){
// a,b分别是下面函数内部,的a和b;是外部的变量,传递到函数内部的通道;如果参数列表不写,就意思是:没有参数要传递到函数内部;
return a+b;
}
//测试枚举
void testEnum(){
enum week p;
//枚举在调用的时候,直接使用枚举的变量名;
printf("Monday=%d,Tuesday=%d,Wensday=%d,Thursday=%d,Friday=%d",Monday,Teusday,Wensday,Thursday,Friday);
}

//测试联合体的声明,使用
void testUnionDef(){
union String{
char c;
int num;
} str;
str.c='a';
str.num=0;
printf("c=%c,num=%d",str.c,str.num);

printf("\n*********************change start*************************\n");
str.c='b';
str.num=10;
printf("c=%c,num=%d",str.c,str.num);

}

//结构体指针的使用
void testStructUse(){

struct Person{
char name[10];
int gender;
int age;

} *per;
per=(struct Person*)malloc(sizeof (struct Person));//分配类存空间,似乎只有结构体指针才有
strcpy(per->name,"yangliang");
per->gender=1;
per->age=28;
printf("name=%s,gender=%d,age=%d",per->name,per->gender,per->age);//注意指针使用不当,造成数据出错
}

//测试 结构体变量的使用;
void testStructVarUse(){
}

//结构体的
void testStructDef(){
struct Person{
char name;
int sex;
double grade;
} ;
struct Person yang,li,zhang,wang;
yang.name='y'; yang.sex=1; yang.grade=100;

li.name='l';
li.sex=0;
li.grade=90;

zhang.name='z';
zhang.sex=1;
zhang.grade=90;

wang.name='w';
wang.sex=0;
wang.grade=86;
struct Person persons[4];
int i;
for(i=0;i<4;i++){
switch(i){
case 0:
persons[0]=yang;
break;
case 1:
persons[1]=li;
break;
case 2:
persons[2]=zhang;
break;
case 3:
persons[3]=wang;
break;
}
}
struct Person per,*p=&persons[0];
for(p;p<&persons[3];p++){
per=*p;
printf("name=%c,sex=%d,grade=%f",per.name,per.sex,per.grade);
printf("\n");
}
}

//测试指针移动
void testPointMove()
{
int arr[5]= {1,2,3,4,5};
char *p=arr;

//注意这里的p++;是移动一个指针存储单元,这个指针的类型有关系,如果是int移动两个字节,char 一个字节,等等;
for(p; p<&arr[4]; p++)
{
int num=*p;
printf("测试数组和指针");

printf("num=%d",num) ;
printf("\n");
}
}

//测试数组 和指针;
void testArrayAndPointer()
{
int arr[5]= {1,2,3,4,5};
int *p=arr;
//注意这里的p++;是移动一个指针存储单元,这个指针的类型有关系,如果是int移动两个字节,char 一个字节,等等;
for(p; p<&arr[4]; p++)
{
int num=*p;
printf("测试数组和指针");
printf("num=%d",num) ;
printf("\n");
}
}

// 测试数组的初始化
void testArrayInnite()
{
int arr[5]= {1,2,3,4,5};
int arr2[]= {1,2,3};
}

//测试数组的一般使用
void testArraCommonUse()
{
int arr[10];
int flag=1;
int i=0;
while(flag)
{
if(i==10) //注意运算符和 赋值符号
{
flag=0;
}
arr[i]=i;
printf("数组赋值:");
printf("arr[%d]=%d",i,arr[i]);
printf("\n");
i++;
}
printf("\narray arr:");
int j;
for(j=0; j<10; j++)
{
printf("arr[%d]=%d",j,arr[j]);
printf(" ");
}
}

//测试指针参数算术运算
void testPointArithmeticOperation()
{
int num1,num2, r,r2,r3,r4,r5,*a=&num1,*b=&num2;
num1=10;
num2=20;
r=*a+*b;
r2=*a*(*b);
r3=*a-*b;
r4=*b/(*a);
r5=r4*(*a);
printf("\n");
printf("r=%d,r2=%d,r3=%d,r4=%d,r5=%d",r,r2,r3,r4,r5);

}

//测试指针运算
void testPointBj()
{
int a,r,*a1,*a2;
a=10;
a1=&a;
a2=&a;
if(a1==a2)
{
r=1;
}
else
{
r=3;
}
printf("r=%d",r);//打印结果,r=1;
}
void testPoint()
{
int a,b,*a1=&a;
a=20;
b=*a1;
printf("\n");
printf(a1);//打印出来是一个地址,不是20;由此可知道,指针变量保存的是一个地址;
printf("\n");
printf("b=%d",b);
}

//测试 goto关键字
void testGotoKeyWords()
{
int i=0;
loop:
for(i; i<10; i++)
{
printf("\n");
printf("TEST FUNCTION AND GOTO");
if(i==10)
{

printf("End FUNCTION AND GOTO");
}
}
printf("Start loop:");
goto loop;

}

// 定义一个函数
int testFunction(int a,int b)
{

return a+b;

}

// 测试基本语句;
void testBaseFunction(int a)
{
//测试for循环,注意C语言中,for 循环的变量是在loop外面定义的;

int i=0;
for(i=0; i<a; i++)
{
printf("***********test function execute for circlerunning******************\n");
printf("i=%d",i);
printf("\n");
if(i>10)
{
printf(" test function execute continue\n");
continue;
}
if(i==a)
{
printf("***********test function execute for circlerunning******************");

}
}
//测试wlie循环
int count=0;
while(a>0)
{
count++;
printf("\n***********test function execute wile circlerunning******************");
if(count>50)
{
printf("\n***********test function execute wile circlerunning******************");
break;
}
}
}

//执行入口
int main()
{
printf("Hello world!\n");
//正型
// unsigned short int num1;
// unsigned long int num2;
//signed short int num3;
// signed long int num4;
// printf("\n------- i 'm separating line-----------\n");
//浮点型
// float a=2.6;//单精度有精度损失,所以一般使用,double
//double a1=2.6;
// int size_a=sizeof(a);
// int size_a1=sizeof(a1);

// printf("size_a=%d,size_a1%d",size_a,size_a1);
// printf("\n------- i 'm separating line-----------\n");
// 字符型
// char c='c';
// char *c1="555";

// com_num=1;
// com_num2=2;
//com_fnum=1.0;
// com_fnum2=1.0;
// com_c='p';
// printf("c=%c",c);
// printf("com_num=%d,com_num1=%d,com_fnum=%f,com_fnum2=%f,com_c=%c",com_num,com_num2,com_fnum,com_fnum2,com_c);
// printf(c1);
// printf("\n");

// printf(c0);
// printf("\n");
// int num_test=testFunction(5,8);

// testBaseFunction(10);
//testGotoKeyWords();
// testPoint();
//testPointBj();
// testPointArithmeticOperation();
//testArraCommonUse();
// testArrayInnite();
// testArrayAndPointer();
// testPointMove();

//testStructVarUse();
//testStructDef();
//testStructUse();
//testUnionDef();
//testEnum();
testDefine();
return 0;
}


下一篇博文:C标准函数库

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: