c语言指针

(转)涨姿势,关于类似*(uint32_t*)&GPIOx这样形式的讨论

心不动则不痛 提交于 2019-12-16 01:20:42
看了看下面大神的讨论,有些茅厕顿开的感觉,特此搬砖过来 void GPIO_DeInit ( GPIO_TypeDef * GPIOx ) { /* Check the parameters */ assert_param ( IS_GPIO_ALL_PERIPH ( GPIOx ) ) ; switch ( * ( uint32_t * ) & GPIOx ) { case GPIOA_BASE : RCC_APB2PeriphResetCmd ( RCC_APB2Periph_GPIOA , ENABLE ) ; RCC_APB2PeriphResetCmd ( RCC_APB2Periph_GPIOA , DISABLE ) ; break ; . . . . . //不明白switch行中GPIOx为什么要取址,GPIOx本来不就是地址么? # define GPIOA ((GPIO_TypeDef*)GPIOA_BASE) //求解释 首先,从 GPIOx 说起 这是ST库里的经典映射手法。 具体就是 和PC上的程序不一样,在STM32上,可以通过 * ( int * ) 0x08001000 = 34 ; 在地址为 0x80010000上写入 34 这个内容。 ——这里不考虑什么 FLASH RAM之类的问题。 所以,ST库映射寄存器的典型手法就是 比如说

C51学习笔记

筅森魡賤 提交于 2019-12-15 21:03:36
一, C51内存结构深度剖析 二, reg51.头文件剖析 三, 浅淡变量类型及其作用域 四, C51常用头文件 五, 浅谈中断 六, C51编译器的限制 七, 小淡C51指针 八, 预处理命令 一,C51内存结构深度剖析 在编写应用程序时,定义一个变量,一个数组,或是说一个固定表格,到底存储在什么地方; 当定义变量大小超过MCU的内存范围时怎么办; 如何控制变量定义不超过存储范围; 以及如何定义变量才能使得变量访问速度最快,写出的程序运行效率最高。以下将一一解答。 1 六类关键字(六类存储类型) data idata xdata pdata code bdata code: code memory (程序存储器也即只读存储器)用来保存常量或是程序。code memory 采用16位地址线编码,可以是在片内,或是片外,大小被限制在64KB 作用:定义常量,如八段数码表或是编程使用的常,在定义时加上code 或明确指明定义的常量保存到code memory(只读) 使用方法: char code table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90}; 此关键字的使用方法等同于const data data memory (数据存储区)只能用于声明变量,不能用来声明函数,该区域位于片内,采用8位地址线编码

Keil C51里关于堆栈指针的处理

假如想象 提交于 2019-12-15 20:44:59
Keil C是非常优秀的C51编译器,可能是最好的C51编译器,提供各种优化模式,对变量的优化和地址安排做得非常好。这是用C语言写代码的好处之一,如果用汇编写,得费一大番功夫给各个变量安排内存物理地址,还得时刻记住哪些地址的内存单元是已经分配了,新增加的变量就不能占用那些已经分配了的单元,以免产生内存交叠冲突和溢出。我一直非常信赖Keil C51的编译结果,在我的印象里,它对内存的分配是完美的,只要代码用它编译时没有报告任何warning和error,代码运行时不可能内存冲突或溢出的现象。 但,今天发生的事情证明我错了。 手头上有个产品的代码,代码量很大。程序跑起来的效果不大好,因此打算把代码优化一下。代码量越大,通常可优化的地方也越多。对8051来说,访问芯片内部的data区(0~7FH)内存速度是最快的,直接访问,一条指令就能读写,而idata区(80H~FFH)虽然还是内存区,但由于地址分配上跟特殊寄存器SFR重合,只能间接地址访问,两条指令才能读写,速度稍慢点,而外存xdata区(0~7FFFH)必须使用DPTR指针才能访问,速度是最慢的。很明显,优化的原则就是尽量把频繁读写的变量优先安排在data区,然后是idata区,最后才是xdata区。 当我做完变量手工优化工作后,把编译模式设为SMALL,这样C51编译器会自动把那些我没手工指定存放区的变量优先安排进data区

scandir函数

Deadly 提交于 2019-12-15 19:30:54
在C语言课程的后端,讲完指针和标准文件IO处理,我会做出一个难度较大练习,题目就是, 利用标准的目录处理函数 opendir/readdir/closedir实现类似于 scandir的功能。其中接口要scandir 函数一致 。 这个题目看起来简单,实现难度相当大,主要采用复杂指针的操作。我第一次拿出来测试,全班大约只一二名实现80%的功能,其余很多觉得无从下手。程序很容易就会出现段错误。基本上短时间内正确的做出来的人可以划归专业级的程度了。有兴趣的人可以先不看后面内容,自行实现一下 首先看一下man的scandir 接口定义 int scandir(const char *dir, struct dirent ***namelist, int(*filter)(const struct dirent *), int(*compar)(const struct dirent **, const struct dirent **)); ,从定义来看就不是一个简单的函数,形参里,出现一个三级指针,二个函数指针。它的功能是,扫描名字为dir的目录,把满足filter函数的过滤条件(即filter执行为非0值)的目录项加入到一维指针数组namelist.数组的总长度为返回值n,如果compar不为空,则最终输出结果还要调用qsort来对数组进行排序后再输出。 从scandir的演示代码

c语言字符串处理笔记【自用·长期更新】

萝らか妹 提交于 2019-12-15 03:20:32
字符数组和字符串的定义和使用 一维char数组 char str1 [ ] = "This is a string" ; char str2 [ ] = { 'a' , 'b' , 'c' , '\0' } ; char str3 [ 50 ] = "This is a string" ; char * str4 = "This is a string" ; char str5 [ ] [ ] 在C语言中,字符串总是以’\0’作为串的结束符。字符串会在末尾自动添加,而如果使用第二种初始化方式则需要在末尾添加’\0’。 str4是一个char型指针,指向字符串所占用内存区域的首位,这里指向字符’T’,由于它是一个指针类型所以可以改变其指向的位置。 ‘\0’:是ASCII码表中的第0个字符,用NUL表示,称为空字符。该字符既不能显示,也不是控制字符,输出该字符不会有任何效果,它在C语言中仅作为字符串的结束标志。 二维char数组 char str1 [ 2 ] [ 10 ] = { "hello" , "world" } ; char str2 [ ] [ 10 ] = { "hello" , "world" } ; char * str3 [ 10 ] { "hello" , "world" } ; char * s [ 10 ] = { str1 [ 0 ] } ; char (

c语言字符串处理函数

白昼怎懂夜的黑 提交于 2019-12-15 01:16:54
1)字符串操作 strcpy(p, p1) 复制字符串 strncpy(p, p1, n) 复制指定长度字符串 strcat(p, p1) 附加字符串 strncat(p, p1, n) 附加指定长度字符串 strlen§ 取字符串长度 strcmp(p, p1) 比较字符串 strcasecmp忽略大小写比较字符串 strncmp(p, p1, n) 比较指定长度字符串 strchr(p, c) 在字符串中查找指定字符 strrchr(p, c) 在字符串中反向查找 strstr(p, p1) 查找字符串 strpbrk(p, p1) 以目标字符串的所有字符作为集合,在当前字符串查找该集合的任一元素 strspn(p, p1) 以目标字符串的所有字符作为集合,在当前字符串查找不属于该集合的任一元素的偏移 strcspn(p, p1) 以目标字符串的所有字符作为集合,在当前字符串查找属于该集合的任一元素的偏移 具有指定长度的字符串处理函数在已处理的字符串之后填补零结尾符 2)字符串到数值类型的转换 strtod(p, ppend) 从字符串 p 中转换 double 类型数值,并将后续的字符串指针存储到 ppend 指向的 char* 类型存储。 strtol(p, ppend, base) 从字符串 p 中转换 long 类型整型数值,base 显式设置转换的整型进制,设置为 0

关于数组还有指针那些事情

蓝咒 提交于 2019-12-15 01:05:37
目前Pproject 遇到一些问题,是把所有点的xyz坐标,用循环的方式读取,形成一个二维数组,然后将该二维数组转化为一维数组。运算中的矩阵是三行N列的,第一行是所有点的X坐标,第二行是所有点的Y坐标,第三行是所有点的Z坐标。 在这里先补充一点指针的知识: 二维数组和指针⑴ 用指针表示二维数组元素。要用指针处理二维数组,首先要解决从存储的角度对二维数组的认识问题。我们知道,一个二维数组在计算机中存储时,是按照先行后列的顺序依次存储的,当把每一行看作一个整体,即视为一个大的数组元素时,这个存储的二维数组也就变成了一个一维数组了。而每个大数组元素对应二维数组的一行,我们就称之为行数组元素,显然每个行数组元素都是一个一维数组。 下面我们讨论指针和二维数组元素的对应关系,清楚了二者之间的关系,就能用指针处理二维数组了。 设p是指向二维数组a[m][n]的指针变量,则有:int* p=a[0]; 此时P是指向一维数组的指针。P++后,p指向 a[0][1]。如果定义int (*p1)[n];p1=a;p1++后,p1指向a[1][0]; 则p+j将指向a[0]数组中的元素a[0][j]。由于a[0]、a[1]┅a[M-1]等各个行数组依次连续存储,则对于a数组中的任一元素a[i][j],指针的一般形式如下:p+i N+j 相应的如果用p1来表示,则为 (p1+i)+j 元素a[i][j

数组指针和指针数组

走远了吗. 提交于 2019-12-13 16:17:01
数组指针(也称行指针) 定义 int (*p)[n]; ()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。 如要将二维数组赋给一指针,应这样赋值: int a[3][4]; int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。 p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0] p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][] 所以数组指针也称指向一维数组的指针,亦称行指针。 指针数组 定义 int *p[n]; []优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1时,则p指向下一个数组元素,这样赋值是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。 如要将二维数组赋给一指针数组: int *p[3]; int a[3][4]; p++; //该语句表示p数组指向下一个数组元素。注:此数组每一个元素都是一个指针 for(i=0;i<3;i++) p[i]=a

c语言中对类似于int *ptr;int **ptr;int(*ptr)[];int *(*ptr)[];几种指针的理解

安稳与你 提交于 2019-12-13 09:30:18
举一些常见的考试或者面试中会遇到的指针类型 (1) int *ptr; (2) char *ptr; (3) int **ptr; (4) int (*ptr)[3]; (5) int *(*ptr)[4]; 这几种类型的指针怎么理解呢? 应分为以下 2个方面 来理解指针 指针的类型 指针所指向的类型 1、指针的类型 (1) int *ptr; 指针类型 int * (2) char *ptr; 指针类型 char * (3) int **ptr; 指针类型 int ** (4) int (*ptr)[3]; 指针类型 int (*)[3]; (5) int *(*ptr)[4]; 指针类型 int *(*)[4]; 规律: 去掉变量名,余下的即为指针类型 2、指针指向的类型 (1) int *ptr; 指针指向的类型 int (2) char *ptr; 指针指向的类型 char (3) int **ptr; 指针指向的类型 int * (4) int (*ptr)[3]; 指针指向的类型 int ()[3]; (5) int *(*ptr)[4]; 指针指向的类型 int *()[4]; 规律: 去掉*和变量名,余下的即为指针指向的类型 来源: CSDN 作者: Andy_Real 链接: https://blog.csdn.net/Andy1814/article

c语言string函数详解

旧城冷巷雨未停 提交于 2019-12-12 22:24:32
文章转自:https://blog.csdn.net/yukadimun/article/details/81388977 @函数原型: char *strdup(const char *s) 函数功能: 字符串拷贝,目的空间由该函数分配 函数返回: 指向拷贝后的字符串指针 参数说明: src-待拷贝的源字符串 所属文件: <string.h> [cpp] view plain copy #include <stdio.h> #include <string.h> #include <alloc.h> int main() { char *dup_str, *string=“abcde”; dup_str=strdup(string); printf("%s", dup_str); free(dup_str); return 0; } @函数名称: strcpy 函数原型: char* strcpy(char* str1,char* str2); 函数功能: 把str2指向的字符串拷贝到str1中去 函数返回: 返回str1,即指向str1的指针 参数说明: 所属文件: <string.h> [cpp] view plain copy #include <stdio.h> #include <string.h> int main() { char string[10]; char