C 语言基础
来源:互联网 发布:编制软件 编辑:程序博客网 时间:2024/05/16 08:17
前言
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)B0.5*2=1,取出整数1;比如:0.25 其二进制 ,就是:(0.01)B0.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 long2.浮点型 float double3.字符型 char4.void5.指针型 **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 void5.1指针类型 根据实际类型,可分为: int *; float *; char *; struct *;结构体指针; union * 联合体指针;
变量的类型
根据变量的定义位置分为:
全局变量:定义在main函数外,如果没有初始化,数字类型变量默认值为:0,字符型和指针型默认为:NULL;
局部变量:定义在函数内部,如何没有初始化,默认为随机赋值;
参数变变量:定义在函数参数列表;
三,函数的定义
在c语言中定义一个函数,一般是写在main函数之前;在函数使用之前,需要在全局声明
关键字与标识符定义
关键字:auto double int struct break elselong switch case enum register typedefchar extern return union const floatshort unsigned continue for signed voiddefault goto sizeof volatile do ifwhile 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 循环gotobread;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标准函数库
- c语言基础--编程基础
- C语言基础-基础语法
- C语言基础 上
- c语言基础
- C语言基础
- C语言基础
- C 语言基础
- c语言基础解析
- c语言 指针基础
- 3 C语言基础
- C语言基础
- C语言基础
- C语言基础
- C语言基础1
- C语言基础
- c语言基础
- c语言基础 2
- C语言程序基础
- windows下grinder压力测试
- Android:在eclipse中的快捷键
- 简单谈谈select, iocp, epoll,kqueue及各种I/O复用机制
- Android static 内存优化
- 域名cname
- C 语言基础
- git 常用命令
- 小知识点7
- RxJava:Schedulers选择 newThread vs io
- 二、创建型模式——工厂模式
- rhel6 rhel7 fedora ubuntu windows 共存 使用grub2 os-probe 启动 使用grub的老系统 bootloader
- Android RecyclerView中实现自定义GridView的方式(实现不同item)
- JS常用方法总结(来自网络整理)
- Spring与Hibernate整合时的核心类LocalSessionFactoryBean详解