C基础
目录
数据类型说明
数据类型 | 16位平台 | 32位平台 | 64位平台 |
---|---|---|---|
char | 1字节 | 1字节 | 1字节 |
pointer | 2字节 | 4字节 | 8字节 |
short | 2字节 | 2字节 | 2字节 |
int | 2字节 | 4字节 | 4字节 |
float | 4字节 | 4字节 | 4字节 |
double | 8字节 | 8字节 | 8字节 |
long | 4字节 | 4字节 | 8字节 |
long long | 8字节 | 8字节 | 8字节 |
volatile关键字
变量是随时可能变换的,为了防止出现意外的取值(例如从cash,寄存器等中取值),每次使用它的时候必须从变量的地址中取值(从内存中取值),使用volatile关键字后编译器生成的汇编代码会重新从变量的地址中读取数据。
使用场合:
- 并行设备的硬件寄存器
- 一个中断服务子程序中会访问到的非自动变量,可以使用关键区保护
- 多线程应用中被几个任务共享的变量,可以关闭系统调度
指针
函数指针
int (*fun)(int *a)
函数指针数组
int (*fun[10])(int *data,int size);
使用方法
int (*sort_fun[5])(int *data, int size) = {
QuickSort, /* 快速排序 */
InsertSort, /* 插入排序 */
BubblSort, /* 冒泡排序 */
ShellSort, /* 希尔排序 */
SelectSort /* 选择排序 */
};
// 或者
SortFun[0]=QuickSort;
SortFun[1]=InsertSort;
指针数组
int *a[10];
数组指针
int (*a)[10];
/*
a为指向含10个元素的一维数组的指针变量,
()优先级高,说明a是一个指针,指向一个包含10个整型的一维数组.
a+1时,a要跨过10个整型数据的长度
*/
二级指针
int **a;
main函数的返回值
- 0表示程序正常退出
- 负数表示程序异常退出
const关键字
const T
定义一个常量,声明的同时必须进行初始化。一旦声明,这个值将无法更改
const int ConstInt=10; //正确
//constInt=20 ; //错误,常量值无法更改
const int ConstInt1; //错误。常量声明时必须进行初始化
const T*
指向常量的指针,不能用于改变其指向的对象的值
const int i = 5;
const int i2 = 10;
const int* pInt = &i; //正确,指向一个const int对象,即i的地址
//*pInt = 10; //错误,不能改变其所指向的对象的值
pInt = &i1; //正确,可以改变pInt指针本身的值,此时pInt指向的是i1的地址
//int* pInt = &i; //错误,i是const int类型,类型不匹配,不能将const int * 初始化为int *
int Value = 15;
const int * pConstInt = &Value; //正确,可以把int *赋给const int *,但是不可以通过pConstInt改变其所指向对象的值,即Value
//*pConstInt = 40; //错误,不能改变其所指向对象的值
const int *与int *const的区别
两者都为指针变量,其区别在于const关键字修饰的对象
简单来说如果const在指针符号*之前时,const修饰的为int ,不可以改变指针本身的值,但是可以通过该指针修改其指向的对象的值,称为常量指针
如果const在指针符号之后时,const修饰的为指针指向的对象的值,不可以通过该指针修改其指向的对象的值,但是可以改变指针本身的值,称为指针常量
int Value = 10;
int* const p = &Value;
int *const p2 = &Value;
//const int* 指针指向的对象不可以改变,但指针本身的值可以改变;int* const 指针本身的值不可改变,但其指向的对象可以改变。
int Value1 = 10;
int Value2 = 20;
int* const constPoint = &Value1;
//constPoint = & Value2; //错误,不能改变constPoint本身的值
*constPoint = 40; //正确,可以改变constPoint所指向的对象,此时Value1 = 40
const int ConstValue1 = 5;
const int ConstValue2 = 15;
const int* Point = &ConstValue1;
//*Point = 55; //错误,不能改变Point所指向对象的值
Point = &ConstValue2; //正确,可以改变Point指针本身的值,此时Point邦定的是ConstValue2对象,即Point为ConstValue2的地址
const int* const 是一个指向常量对象的常量指针,即不可以改变指针本身的值,也不可以改变指针指向的对象。
浮点数存储方式
- float占4个字节,32bits
|符号位|指数位|尾数部分
-------- | -----|-----|-----
1bits| 8bits|23bits
2.double占8字节,64bits
|符号位|指数位|尾数部分
-------- | -----|-----|-----
1bits| 11bits|52bits
C题目总结
printf返回值
#include <stdio.h>
int main()
{
int i = 43;
printf("%d\n", printf("%d", printf("%d", i)));
return 0;
}
输出:4321
printf返回值是输出字符的个数(不包括字符串结尾的\0)
enum枚举类型
#include <stdio.h>
int main()
{
enum color{
RED,
BLUE,
GREEN=-2,
YELLOW,
PINK
};
printf("%d %d\n", BLUE, PINK);
return 0;
}
输出:1,0
enum默认是从0开始的,所以RED=0,BLUE=1,GREEN=-2,YELLOW=-1,PINK=0;
可变参函数
#include "stdarg.h"
char buf[512]={0};
int func(const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
vsprintf(buf, fmt, args);
va_end(args);
}
大小端判断
#include <stdio.h>
int main(int argc, const char *argv[])
{
union s
{
int a;
char b;
};
union s s1;
s1.a=1;
if(s1.b=1)
{
printf("is small end\n");
}
else
{
printf("is big end\n");
}
return 0;
}
链表
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef int DataType;
typedef struct node
{
DataType data;
struct node *pNext;
}LinkNode;
typedef struct list
{
LinkNode *pHead;
int cLen;
}LinkList;
int IsEmptyLink(LinkList *pList)
{
return pList->pHead==NULL?1:0;
}
LinkList *createLinkList()
{
LinkList *pList=malloc(sizeof(LinkList));
if(NULL==pList)
{
perror("fail to malloc");
return NULL;
}
pList->pHead=NULL;
pList->cLen=0;
return pList;
}
int insertHeadLinkList(LinkList *pList,DataType data)
{
LinkNode *pInsertNode=malloc(sizeof(LinkNode));
if(NULL==pInsertNode)
{
perror("fail to malloc");
return -1;
}
pInsertNode->data=data;
pInsertNode->pNext=pList->pHead;
pList->pHead=pInsertNode;
pList->cLen++;
return 0;
}
int insertTailLinkList(LinkList *pList,DataType data)
{
if(IsEmptyLink(pList))
{
insertHeadLinkList(pList,data);
return 0;
}
LinkNode *pTmpNode=pList->pHead;
while(pTmpNode->pNext)
{
pTmpNode=pTmpNode->pNext;
}
LinkNode *pInsertNode=malloc(sizeof(LinkNode));
if(NULL==pInsertNode)
{
perror("fail to malloc");
return -1;
}
pInsertNode->data=data;
pInsertNode->pNext=NULL;
pTmpNode->pNext=pInsertNode;
pList->cLen++;
return 0;
}
int deleteHeadLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return 0;
}
LinkNode *pDeleteNode=pList->pHead;
pList->pHead=pDeleteNode->pNext;
pList->cLen--;
free(pDeleteNode);
return 0;
}
int deleteTailLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return 0;
}
LinkNode *pTmpNode=pList->pHead;
if(NULL==pTmpNode->pNext)
{
deleteHeadLinkList(pList);
}
else
{
while(pTmpNode->pNext->pNext)
{
pTmpNode=pTmpNode->pNext;
}
LinkNode *pDeleteNode=pTmpNode->pNext;
free(pDeleteNode);
pTmpNode->pNext=NULL;
pList->cLen--;
}
return 0;
}
LinkNode *findMidLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return NULL;
}
if(NULL==pList->pHead->pNext)
{
return pList->pHead;
}
LinkNode *pFastNode=pList->pHead;
LinkNode *pSlowNode=pFastNode;
while(pFastNode)
{
pFastNode=pFastNode->pNext;
if(NULL==pFastNode)
{
break;
}
pFastNode=pFastNode->pNext;
pSlowNode=pSlowNode->pNext;
}
return pSlowNode;
}
LinkNode *findLastKLinkNode(LinkList *pList,int K)
{
if(IsEmptyLink(pList))
{
return NULL;
}
LinkNode *pFastNode=pList->pHead;
LinkNode *pSlowNode=pFastNode;
for(int i=0;i<K;i++)
{
pFastNode=pFastNode->pNext;
if(NULL==pFastNode)
{
return NULL;
}
}
while(pFastNode)
{
pSlowNode=pSlowNode->pNext;
pFastNode=pFastNode->pNext;
}
return pSlowNode;
}
void reverseLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return;
}
LinkNode *pInsertNode=NULL;
LinkNode *pTmpNode=pList->pHead;
pList->pHead=NULL;
while(pTmpNode)
{
pInsertNode=pTmpNode;
pTmpNode=pTmpNode->pNext;
pInsertNode->pNext=pList->pHead;
pList->pHead=pInsertNode;
}
return;
}
void sortLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return;
}
LinkNode *pTmpNode1=NULL;
LinkNode *pInsertNode=NULL;
pTmpNode1=pList->pHead->pNext;
pList->pHead->pNext=NULL;
while(pTmpNode1)
{
pInsertNode=pTmpNode1;
pTmpNode1=pTmpNode1->pNext;
if((pList->pHead->data)>(pInsertNode->data))
{
pInsertNode->pNext=pList->pHead;
pList->pHead=pInsertNode;
}
else
{
LinkNode *pTmpNode2=pList->pHead;
while(pTmpNode2->pNext)
{
if((pTmpNode2->pNext->data)>(pInsertNode->data))
{
break;
}
pTmpNode2=pTmpNode2->pNext;
}
pInsertNode->pNext=pTmpNode2->pNext;
pTmpNode2->pNext=pInsertNode;
}
}
return;
}
void destroyLinkList(LinkList **ppList)
{
if(IsEmptyLink(*ppList))
{
*ppList=NULL;
return;
}
while((*ppList)->pHead)
{
deleteHeadLinkList(*ppList);
}
free(*ppList);
*ppList=NULL;
}
void showLinkList(LinkList *pList)
{
if(IsEmptyLink(pList))
{
return;
}
LinkNode *pTmpNode=pList->pHead;
while(pTmpNode)
{
printf("data:%d\t",pTmpNode->data);
pTmpNode=pTmpNode->pNext;
}
printf("\n");
return;
}
排序算法
冒泡排序
- 算法步骤
- 时间复杂度
平均: O(n2) 最好: O(n) 最坏:O(n2) - 空间复杂度
O(1)
void bubble_sort(int a[],ssize_t len)
{
ssize_t i=0,j=0;
int tmp=0;
for(j=0;j<len-1;++j)
{
for(i=0;i<len-j-1;++i)
{
if(a[i]>a[i+1])
{
tmp=a[i];
a[i]=a[i+1];
a[i+1]=tmp;
}
}
}
return;
}
选择排序
- 算法步骤
- 时间复杂度
平均: O(n2) 最好: O(n2) 最坏:O(n2) - 空间复杂度
O(1)
void select_sort(int a[],ssize_t len)
{
ssize_t i=0,j=0,min=0;
int tmp;
for(j=0;j<len-1;j++)
{
min=j;
for(i=j+1;i<len;i++)
{
if(a[i]<a[min])
{
min=i;
}
}
if(min!=j)
{
tmp=a[j];
a[j]=a[min];
a[min]=tmp;
}
}
return;
}
插入排序
- 算法步骤
- 时间复杂度
平均:O(n2) 最好:O(n) 最坏:O(n2) - 空间复杂度
O(1)
void insert_sort(int a[],ssize_t len)
{
int i=0,j=0;
int tmp=0;
for(j=0;j<len;++j)
{
tmp=a[j];
for(i=j;i>0&&tmp<a[i-1];--i)
{
a[i]=a[i-1];
}
a[i]=tmp;
}
return;
}
快速排序
-
算法步骤
-
时间复杂度
平均: O(nlogn) 最好: O(nlogn) 最坏:O(n2) -
空间复杂度
O(nlogn) 用于方法栈
void quick_sort(int a[],ssize_t head,ssize_t tail)
{
if(head>tail)
{
return;
}
int i=head,j=tail,key=a[i];
while(i<j)
{
while(i<j&&key<=a[j])
{
j--;
}
a[i]=a[j];
while(i<j&&key>=a[i])
{
i++;
}
a[j]=a[i];
}
a[i]=key;
quick_sort(a,head,i-1);
quick_sort(a,j+1,tail);
}