C语言编程基本案例

电脑杂谈  发布时间:2020-05-30 12:05:37  来源:网络整理

c语言入门实例_c语言初中生入门操作实例_c语言从入门到精通(实例版)

刚开始学习时,存在很多疑问,例如如何使用指针,如何匹配结构和指针,例如功能参数的要求,如何实时更新IO端口数据如果您重新学习C语言,则必须学习很长时间才能系统地理解它. 本文将简单地整理出难以记住的知识点.

1,#ifdef和#ifndef

#ifdef标识符A //如果定义了标识符A,则编译程序段1,否则编译程序段2

程序1

#else

程序2

#endif

#ifndef的功能与#ifdef的功能相反,后者在未定义标识符A时编译块1.

2. 全局定义

在软件选项中,有一列,上面填写的变量表示在所有文件中,上面的徽标均已定义.

#ifdef STM32F10X_HD

大容量芯片需要一些变量定义

#end

3. 外部变量声明

可以使用C语言将外部变量放在变量或函数的前面,以指示变量或函数的定义在另一个文件中. 当遇到此变量和函数时,它会提示编译器在其他模块中找到其定义. 这里应该注意,对于外部变量,可以多次声明该变量,但只能声明一次.

外部u16 USART_RX_STA;

此语句声明USART_RX_STA变量已在其他文件中定义,并在此处使用.

下面以一个示例来说明如何使用它.

在Main.c中定义的全局变量id在Main.c中初始化.

Main.c文件

u8 id; //定义只允许一次

main(){

id = 1; printf(“ d%”,id); // id = 1

test();

printf(“ d%”,id); // id = 2

}

但是我们希望在test.c

在changeId(无效)函数中使用变量id. 此时,我们需要声明变量id是在test.c中将无法到达其中的test.c文件.

在下面的test.c中查看代码:

外部u8 id; //声明变量id是在外部定义的,并且声明可以在许多文件中完成

无效测试(void){id = 2;}

声明变量id是在test.c中外部定义的,然后在test.c中使用变量id.

4. Typedef类型别名

Typedef用于为现有类型或类型别名创建新名称,以简化变量的定义. Typedef是MDK中最常用于定义类型别名和枚举结构的类型.

struct _GPIO {__IO uint32_t CRL; __IO uint32_t CRH;…};

定义了GPIO结构,因此我们定义变量的方式是:

struct _GPIO GPIOA; //定义结构变量GPIOA

但这很乏味. 在这里,我们可以为结构定义别名GPIO_TypeDef,以便我们可以通过别处的别名GPIO_TypeDef定义结构变量.

方法如下:

c语言初中生入门操作实例_c语言从入门到精通(实例版)_c语言入门实例

typedef struct {

__ IO uint32_t CRL; __IO uint32_t CRH;…} GPIO_TypeDef;

Typedef为结构定义别名GPIO_TypeDef,

这样,我们可以通过GPIO_TypeDef定义结构变量: GPIO_TypeDef _GPIOA,_GPIOB;

此处的GPIO_TypeDef等效于_GPIO结构.

5. 结构

声明结构类型: 结构结构名称{成员列表;}变量名称列表;例如:

结构U_TYPE {Int BaudRate Int WordLength;} usart1,usart2;

可以在声明结构时定义变量,也可以在声明之后定义变量. 方法是:

结构名称结构变量名;例如: struct U_TYPE usart1,usart2;

引用结构成员变量的方法是: 结构变量名称. 会员名

例如,引用usart1的成员BaudRate,方法是: usart1.BaudRate;

结构指针变量的定义也相同,与其他变量没有区别.

例如: struct U_TYPE * usart3; //定义结构指针变量usart1;

结构指针成员的变量引用方法是通过“->”符号实现的,

例如,要访问usart3结构的指针所指向的结构的成员变量BaudRate,方法是:

Usart3-> BaudRate;

在开发微控制器程序期间,我们经常遇到要初始化的设备,例如串行端口. 它的初始化状态由几个属性确定,例如序列号,波特率,极性和模式. 对于这种情况,当我们没有学习结构时,我们的一般方法是:

void USART_Init(u8 usartx,u32,u32 BaudRate,u8奇偶校验,u8模式);

此方法在某些情况下是有效且理想的. 但是请考虑一下,如果有一天我们想将另一个参数传递给该函数,那么我们必须修改此函数的定义并重新输入字长的输入参数. 但是,如果函数的输入参数随着开发的增加而增加,我们是否必须不断修改函数的定义?这会给我们带来很多开发上的麻烦吗?那么如何解决呢?

因此,如果使用结构,则可以解决此问题. 仅通过更改结构的成员变量,就可以实现更改输入参数而无需更改输入参数的上述目的.

我们可以通过定义结构来组合它们. 这是在MDK中定义的:

typedef struct {uint32_t USART_BaudRate;

uint16_t USART_WordLength;

uint16_t USART_StopBits;

uint16_t USART_Parity;

uint16_t USART_Mode;

uint16_t USART_HardwareFlowControl;} USART_InitTypeDef;

因此,当我们初始化串行端口时,入口参数可以是USART_InitTypeDef类型的变量或指针变量,这是在MDK中完成的: void

USART_Init(USART_TypeDef * USARTx,USART_InitTypeDef * USART_InitStruct);

通过这种方式,我们只需修改结构成员变量并将新的成员变量添加到结构中,而无需修改函数定义即可达到修改入口参数的相同目的.

6. 关于函数中结构的参数传递

在ST库函数中,结构的用法很多. 如第5点所述,使用结构进行封装有助于功能的传递.

以下是摘录的一些解释,很典型.

在ST结构参数传输中,有指针类型和结构地址类型.

(1)使用结构变量名称作为参数.

#include

#include

使用命名空间标准;

c语言从入门到精通(实例版)_c语言入门实例_c语言初中生入门操作实例

struct学生{

字符串名称;

int得分;

};

int main(){

学生一;

无效打印(学生一);

one.name =“千手”;

one.score = 99;

打印(一个);

cout <

cout <

返回0;

}

无效打印(学生一){

cout <

cout << ++ one.score <

}

此方法采用“值传递”方法,将结构变量占用的存储单元的所有存储依次传递给形式参数. 形式参数还在函数调用期间占用存储单元. 这种转移方法具有较大的空间和实际的开销. 如果结构的尺寸很大,则开销非常客观. 而且,由于采用了值传递方法,如果在函数执行过程中改变形式参数的值,则该值不能反映到调用函数中相应的实际参数上c语言入门实例,这往往不能满足使用要求. 因此,这种方法通常较少使用.

(2)使用指向结构变量的指针作为函数参数

#include

#include

使用命名空间标准;

struct学生{

字符串名称;

int得分;

};

int main(){

学生一;

无效打印(学生* p);

one.name =“千手”;

one.score = 99;

学生* p =&one;

打印(p);

cout <

cout <

返回0;

}

无效打印(学生* p){

c语言入门实例_c语言从入门到精通(实例版)_c语言初中生入门操作实例

cout

cout << ++ p->得分<

}

尽管此方法也是值传递的方法,但是这次传递的值是一个指针. 通过更改指针指向的结构变量的值,可以间接更改实际参数的值. 而且,在调用该函数期间,仅创建了一个指针变量,这大大减少了系统开销.

(3)将结构变量的参考变量用作函数参数

#include

#include

使用命名空间标准;

struct学生{

字符串名称;

int得分;

};

int main(){

学生一;

无效打印(学生和一名);

one.name =“千手”;

one.score = 99;

打印(一个);

cout <

cout <

返回0;

}

无效打印(学生和一名){

cout <

cout << ++ one.score <

}

实际参数是结构变量,形式参数是相应结构类型的引用,虚拟和实数组合时通过地址传递,因此执行效率较高. 而且,与作为函数参数的指针相比,它看起来更加直观和易于理解. 因此,将变量作为函数参数引用可以提高效率并保持程序可读性.

7. IMPORT指令

IMPORT指令用于通知编译器要使用的标签在其他源文件中定义,但是必须在当前源文件中引用该标签,并且无论当前源是否存在,标签都将添加到当前文件中文件是指标签源文件的符号表.

有两种构建ST项目的方法,一种是寄存器版本,另一种是固件库版本.

在新过程中,有些功能和文件不需要添加到寄存器版本中.

在注册版本的新项目之后,添加启动文件startup_stm32f10x_hd.s

(堆栈,PC初始化,向量异常地址条目初始化,调用MAIN函数),其中该教程需要注释掉以下几行(绿色部分):

Reset_Handler PROC

导出Reset_Handler [弱]

导入__main

;注册版本代码,因为未使用SystemInit函数,所以请注释掉

;库函数版本代码,建议添加此代码(SystemInit函数必须在外部实现)以初始化stm32时钟等.

; IMPORT SystemInit调用SystemInit函数

c语言入门实例_c语言从入门到精通(实例版)_c语言初中生入门操作实例

; LDR R0,= SystemInit

; BLX R0

LDR R0,= __ main

BX R0

ENDP

当系统找不到SystemInit函数时,有三种解决方法

①在外部(在任何其他.c文件中)定义函数SystemInit或一个空函数.

②放置

IMPORT SystemInit

LDR R0,= SystemInit

BLX R0

注释或删除这两个句子.

③您可以将库文件system_stm32f10x.c添加到项目中,即可解决该问题.

但是第三个方法更麻烦,因为如果您自己定义一些函数,则可能与system_stm32f10x.c

冲突.

8. 文件包含的问题

#include操作是,如果后跟<>,则在安装路径中找到该文件;

如果后跟“”,则在源目录中找到该文件.

9,易失性声明

如果在变量前添加关键字volatile,则每当系统使用此变量时,都必须重新读取该变量的值.

此类语句用于描述与内存映射或寄存器(例如IO端口寄存器)相对应的大量输入和输出端口.

如下:

int标志= 0;

void car_action()

{

同时(1)

{

如果(flag)car_go();

}

}

void car_stop()

{

flag = 1;

}

在上面的示例中,car_action并未更改标志操作,因此可能只是第一次执行car_action

仅读取标志的值. 第一次读取的值将直接在后续步骤中使用. 实际上,在car_stop中c语言入门实例,flag的值已更改.

在这种情况下,car_action函数的执行结果可能是错误的.

但是,如果在定义中使用了volatile int标志,则每次标识该标志时,都会将其跟踪到存储在源地址中的数据以获取数据,并且程序可以正常执行.

最后,如果您想学习C / C ++编程,则可以通过私人信函编辑器“ 01”获得资料和开发工具以及参加课程的权利!


本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-227599-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      • 末主耶律直鲁古
        末主耶律直鲁古

        直接动动炮肯定不妥

      热点图片
      拼命载入中...