Gary的一些C语言知识点快速补充

C语言知识点补充

文章目录

C库函数 void *memset(void *s, int ch, size_t n)

将s中当前位置后面的n个字节用 ch 替换并返回 s 。size_t n一般用sizeof()确定多少个字节。ch是赋给buffer的值。


C库函数 void mencpy(void *str1, const void *str2, size_t n)

从存储区str2复制n个字节到存储区str1。一般参数n用sizeof(str2)表示


C库函数 void *malloc(size_t size) 动态内存分配

返回值是一个指针,指向已经分配大小的内存,如果请求失败则返回NULL。


C库函数 void free(void *ptr) 释放内存

ptr–指针指向一个要释放内存的内存块


C运算符 sizeof() 判断变量或数据类型的字节大小。单位(byte)


C库函数 strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符

返回字符串的长度


C库函数 fflush() 刷新流 stream 的输出缓冲区



C库函数 scanf, 从标准输入stdin读取格式化输入.

类型说明符

类型合格输入参数的类型
%a %A读入一个浮点值float *
%c单个字符:读取一个字符char *
%d十进制整数:数字前面的 + 或 - 号是可选的。int *

C库函数 printf, 发送格式化输出到标准输出 stdout.

格式字符
格式字符意义
d以十进制形式输出带符号整数(正数不输出符号)
s输出字符串
x,X以十六进制形式输出无符号整数
转义字符
转义字符意义
\b退格(BS), 将当前位置移到前一列
\f换页(FF), 将当前位置移到下页开头
\n换行(LF), 将当前位置移到下一行开头
\r回车(CR), 将当前位置移到本行开头
\t水平制表(HT)
\v垂直制表(VT)
?输出? .用于书写连续多个问号时使用
printf("请输入三个字符:");
scanf("%c%c%c",&a,&b,&c);
printf("%d,%d,%d\n",a,b,c);

C库函数 char *strtok(char s[], const char *delim);将字符串分割成一个个片段。

参数s指向欲分割的字符串,参数delim则为分割字符串中包含的所有字符。当strtok()在参数s的字符串中发现参数delim中包含的分割字符时,则会将该字符改为\0 字符。在第一次调用时,strtok()必需给予参数s字符串,往后的调用则将参数s设置成NULL。每次调用成功则返回指向被分割出片段的指针。

#include <string.h>
#include <stdio.h>
int main () {
   char str[80] = "This is - www.runoob.com - website";
   const char s[2] = "-";
   char *token;
   
   token = strtok(str, s);//返回串中第一个s前的字符串
    
   /* 继续获取其他的子字符串 */
   while( token != NULL ) {
      printf( "%s\n", token );
      token = strtok(NULL, s);//结果返回分割依据后面的字串
      //如果,s为空值NULL,则函数保存的指针SAVE_PTR在下一次调用中将作为起始位
   }   
   return(0);
}

C库函数 int strncmp(const char *str1, const char *str2, size_t n)字符串比较函数

str1和str2比较,n为要比较的最大字符数。返回值< 0,str1 < str2; 返回值> 0,str1 > str2; 返回值= 0,str1 = str2 。


C库函数 unsigned long int strtoul(const char *str, char **endptr, int base)把输入的字符串转换成数字

str:字符串的起始地址。endptr: 返回字符串有效数字的结尾地址(例1234fe56则返回f的地址)。base:转化基数 (2~36|0),用来代表str采用多少base进制。


C库函数 double floor(double arg)向下取整;double ceil(double arg)向上取整


?:条件表达式. 如果条件为真?则值为X:否则值为Y


break跳出当前循环(在switch中是结束掉switch循环)。

continue跳过循环体中剩余的语句而强行执行下一次循环。

return返回主调函数。


关键字static

  • 修饰静态局部变量 存储于静态内存中的变量在程序的整个执行过程中将一直保留它们的值。
  • 限制函数和数据定义的作用域 抽象数据类型(abstract data type)这个技巧也被称为黑盒.

关键字const

  1. 修饰变量,声明变量为只读特性,保护变量值以防被修改。此外还可以节约空间的目的,此变量保存到符号表中,无需读写内存,程序执行效率也会提高。

    const int I = 5;//== int const I = 5通常建议采用第一种声明

  2. 修饰数组。

  3. 修饰指针,修饰指针有两种形式,一种是用来限定指向的值不能被修改,另一种是限定指针不可更改。

    /*记忆窍门 
    	const在'*p'前,意思是修饰'*p'这个值,而这个'*p'的意思是指向的值
    	const在'p'前,意思是修饰'p'这个值,而这个'p'的意思是指针
    */
    const int *p1 = &i;//限定指向的值不可改变。
    int *const p2 = &j;//限定指针不可改变。
    
  4. 修饰函数参数,const形参防止被函数内部修改。


关键字struct 结构体

结构体成员的.->
  1. 结构体成员的直接访问, 通过(.)操作符. 左操作数就是结构体变量的名字, 右操作数就是需要访问的成员的名字.
  2. 结构体成员的直接访问, 通过(->)操作符. 左操作数必须是一个指向结构的指针, 右操作数就是需要访问的成员的名字.

struct COMPLEX *cp;
通过(*cp).f调用里面的f成员. 但是很麻烦,所以C语言提供了(->)操作符, 所以变成了cp->f

结构体传递时注意点

尽量或者必须做到,传递一个指向结构体的指针而不是一个结构体


函数指针 int(*pFunc)(int, int)

指向函数的指针变量,在C编译时,每一个函数都有一个入口地址,那么指向这个函数的函数指针便是指向这个地址。函数指针主要有两个作用:用作调用函数和做函数的参数。

使用案例:

typedef int(*pFunc)(int,int);
pFunc pv(int,int);//pv 是一个函数指针

int AddTwoNumb(int a,int b){return a+b;}

int main()

{

pv = AddTwoNumb;//pv存放AddTwoNumb函数的地址

int a,b;

sum = (*pv)(a,b);//sum = 函数AddTwoNumb return的值,若是不带参数的的函数则调用一次函数(调用方式:sum = (*pv)😉

}


指针函数 int *sub(int a, int b)

其返回值是一个 int 类型的指针,是一个地址。


数组指针int (*pArr)[10]

下标引用的优先级是高于间接访问,但由于括号的优先级要高,所以先执行间接访问。

pArr是一个指向拥有10个整形元素的数组的指针。

使用案例:可以实现对一个多维数组进行逐行移动。

指针数组 int *ArrP[10]

下标引用的优先级是高于间接访问。

使用案例:使用指针数组设计一个存放字符串的表。PS:一般在数组末尾加上一个NULL元素,来判断数组是否到了结尾。

# 把宏参数变为一个字符串.

#define dprint(expr) printf(#expr"=%d\n",expr);
...
int a=10,b=10;
dprint(a/b);
===============打印结果==================
a/b=1 

## 为宏提供一种连接实际参数的手段.

#define cat(x,y) x##y
cat(var,3)将生成var123
实际运用 思路:用单独一个OSD2Image_Table.h文件封装起来,供客户等添加图片信息. (优点: 便捷、隔离)
\fliename:OSD2Image_Table.h
//!         Index 	SF Address   Pos X   Pos Y
OSD2IMGPOOL(OSD2IMAGE, 		0,     0,     0)
OSD2IMGPOOL(PU_STSICON, 	0x3000,   10,     0)
OSD2IMGPOOL(CAM1_STSICON,	0x3000,  430,  	  0)
#undef OSD2IMGPOOL//?好像加不加这个#undef也没什么影响
\flienname:UI.h
typedef enum
{
#define OSD2IMGPOOL(idx,addr,posx,posy)  OSD2IMG_##idx,
#include "OSD2Image_Table.h"
	OSD2IMG_MAX
}UI_OSD2ImagePool_t;
\Application Program
//调用
tOSD_GetOsdImgInfor(OSD2IMG_CAM1_STSICON);

解释:1.导入的图片按照Index, addr, position的规则来存放和读取.

2.通过一个enum枚举和##来把table中的格式规则, 变为更简便的格式.

OSD2IMGPOOL(PU_STSICON,0x3000,10,0)变成OSD2IMG_CAM1_STSICON

3.通过简化过后的格式调用, 找到图片存放的地方.

OSD2IMG_CAM1_STSICON = 1


链表与数组的区别

链表是通过节点把离散的数据链接成一个表,通过对节点的插入和删除操作从而实现对数据的存取。而数组是通过开辟一段连续的内存来存储数据这是数组和链表最大的区别。

数组的每个成员对应链表的结点,成员和结点的数据类型可以是标准的C类型或者是用户自定义的结构体。数组有起始地址和结束地址,而链表是一个圈,没有头和尾之分,但是为了方便节点的插入和删除操作会人为的规定一个根节点。


关于几个debug用到的宏

__VA_ARGE__ 是一个可变参数的宏,在c99中新增的规范, 使用时在宏定义中参数列表的最后一个参数为省略号(…). ##__VA_ARGE__ ##起到的作用是把前面多余的, 去掉(ps:不管是几个参数都能正确打印).
__FILE__ 宏在预编译时会替换成当前的源文件名

__LINE__ 宏在预编译时会替换成当前的行号

__FUNCTION__ 宏在预编译时会替换成当前的函数名称


?操作符的结合性都是从右向左的


字符串的定义

char site[7] = {'R', 'U', 'N', 'O', 'O', 'B', '\0'};
char site[] = "RUNOOB";

???#pragma pack()

#pragma pack(n)

n称为对齐系数


函数的参数之形参与实参

函数名(实际参数);

类型 函数名(形式参数){代码块};

参数的传递

一般参数的传递分为两种.

一种是"传值调用"方式进行传递, 意味着函数将获得参数值的一份拷贝. 函数可以随意修改这个参数, 不必担心会修改到实参.

第二种是"传址调用"方式进行传递, 意味着函数将获得参数值的一个地址. 函数内通过改变传入形参地址的值从而去改变实参的值.

思考的例子
/*实现整数变换函数*/
/**无效变换**/
void swap(int x, int y)//"传值调用"
{
    int temp;
    temp = x;
    x = y;
    y = temp;
}
void main(void)
{
    int a == 100;
    int b == 200;
    swap(a,b);
}
/**有效变换**/
void swap(int *x, int *y)//"传址调用"
{
    int temp;
    temp = *x;
    *x = *y;
    *y = temp;
}
void main(void)
{
    int a == 100;
    int b == 200;
    swap(&a,&b);
}

过程类型的函数 有return的函数

把一个变量声明为过程类型,可以把一个过程或函数作为一个整体赋给这个变量或者把这个变量作为 参数传递给其它过程或函数。


存储类型与存储区关系

data->可寻址片内ram //定义的是芯片的内核RAM

bdata->可为寻址的片内ram

idata->可寻址片内ram,允许访问全部内部ram

pdata—>分页寻址片外ram (MOVX @R0) (256 BYTE/页)

xdata—>可寻址片外ram//定义的芯片内核外部的扩展RAM,包括芯片外扩展的RAM,和芯片内扩展的RAM.

code—>程序存储区 (64k 地址范围)

data是指存储在内部RAM中的数据,xdata是指存储在外部RAM中的数据,code是存储在ROM中的数据


__attribute__

section

在ARM编译器编译之后,代码被划分为不同的段,RO Section(ReadOnly)中存放代码段和常量,RW Section(ReadWrite)中存放可读写静态变量和全局变量,ZI Section(ZeroInit)是存放在RW段中初始化为0的变量。

__attribute__((section(“section_name”))),其作用是将作用的函数或数据放入指定名为"section_name"对应的段中


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值