【C语言 全局-> 整形变量 布尔变量 数组变量 指针变量 结构体位域变量 枚举变量被其他.C文件相互访问】
- 【0】UI设计
- 【1】项目概述
- 【2】mainwindow.h头文件解析
- 【3】头文件源码
- 【4】mianwindow.c源文件解析
- 【5】源文件源码
- 【6】main文件解析+源码
- 【7】编译-链接-运行结果
学完这一篇,对于变量的使用不在迷糊
【0】UI设计
UI使用文本编辑框显示操作的记录
【1】项目概述
本次使用QT平台进行编写和编译,使大家掌握某个.C文件的变量可以被其他文件 访问 | 修改 等
全局变量 整形 结构体 枚举 使用exterm关键字声名
目的:其他文件通过添加本文件头文件,可以使用这些变量 修改值|获取值|传参等
需要处理
【1】在本头文件.h必须使用exterm关键字声明变量
【2】在本源文件.C文件定义变量(分配变量空间)
【3】typedef关键字作用起别名
【2】mainwindow.h头文件解析
结构体声明
/* 全局变量 整形 结构体 枚举 使用exterm关键字声名
* 目的:其他文件通过添加本文件头文件,可以使用这些变量 修改值|获取值|传参等*/
typedef struct {
int age;//可以被其他.c文件访问
}node_t;
extern node_t age_t;//可以被其他.c文件访问
常用数据类型变量声明
extern node_t age_t;//可以被其他.c文件访问
extern int global; //可以被其他.c文件访问
extern bool global_bool;//可以被其他.c文件访问
extern int array[10];//可以被其他.c文件访问
extern char str[8];//可以被其他.c文件访问
exterm “C” 使用C的编译规范
extern "C"{//使用C语言的编译规范 因为C++11警告在其他.c文件给p赋值字符串
extern char *p;//可以被其他.c文件访问
};
静态全局变量不能被其他.C文件访问
//extern static int a; //static关键字的一个作用就是限制变量的范围,即作用域 不能被其他.C文件访问
枚举声明
typedef enum{red,blue,green}color;//可以被其他.c文件访问
结构体位域声明
在嵌入式领域 几乎位域运算符的使用必不可少,这种处理的目的是为了给寄存器的某个位设置某个值,,或者对于一些标志位只有0和1的值,可以大大节省空间,其中位于的运算指标:
2
n
2^{n}
2n-1
举例:unsigned int bit:3; 那么
2
3
2^{3}
23-1=0-7 总共8个字符 也就是这个变量的最大值最多=7,最小值=0
注意:上面的变量用unsigned无符号修饰,所以取值范围:0-7 如果是有符号,请看下面说明。
位域变量的数据类型很重要
注意
在位域结构体中,常常使用结构体嵌套联合体,联合体在嵌套结构体,目的:联合体内的变量和联合体内的结构体共用一块内存保存数据,对联合体变量【uint32】赋值,就是对联合体内的结构体【bits】赋值,具体请看后面的代码实操
重点理解
【1】第一种赋值方式对uint32赋值,由于联合体内的变量共用一块内存,那么结构体内的uint16 | uint1 | 那个未使用占15个位的匿名变量将均分uint32的值
值分配的原则
【1】联合体内的结构体变量 从上到下 低字节-高字节
如uint32 = 0x0001ffff; 【十六进制 从左到右 高字节-低字节】
那么uint16=ffff 【占16个位 范围:0-65535】
uint1=1 【占1个位 范围:0-1】
匿名15位=0 【占15个位 范围:0-
2
15
2^{15}
215-1】
注意
联合体内的位域变量:16位+1位+15位=32位
和联合体内的uint32 = 32位相等
如此一来他们共用一块4字节的空间,赋值的时候不会出错。
【2】联合体内的位域变量赋值
先做初始化:
memset(&结构体栈地址,0x00,sizeof(结构体别名));目的:联合体内的所有变量=0
uint16=0xffff;
uint1=0x1;
此时想获取全部值,就uint32=0x0001FFFF
(高字节-低字节)
实例加深记忆
//位域结构体 常用于嵌入式寄存器设置位
typedef struct{
union{//记住联合体共用一块内存 如同一笔钱 赋值的时候类比给钱
//[1]家长可以给每个孩子钱 [2]每个孩子凑成的钱=家长的钱 孩子的个头不同 变量大小不同 分的钱也不同
unsigned int uint32; //无符号整形范围 类比家长
struct{ //结构体内部变量 类比孩子
unsigned int uint16:16;//用于保存16位数据 范围:0-65535
unsigned int uint1:1; //用于保存1个位值 范围:0-1
unsigned int :15; //无用 只作为对齐填充,默认情况下值都是0
}bits;
}UNION;
}str_union;
extern str_union bitstruct;//可以被其他.c文件访问
【3】头文件源码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
/* 全局变量 整形 结构体 枚举 使用exterm关键字声名
* 目的:其他文件通过添加本文件头文件,可以使用这些变量 修改值|获取值|传参等*/
typedef struct {
int age;//可以被其他.c文件访问
}node_t;
extern node_t age_t;//可以被其他.c文件访问
extern int global; //可以被其他.c文件访问
extern bool global_bool;//可以被其他.c文件访问
extern int array[10];//可以被其他.c文件访问
extern char str[8];//可以被其他.c文件访问
extern "C"{//使用C语言的编译规范 因为C++11警告在其他.c文件给p赋值字符串
extern char *p;//可以被其他.c文件访问
};
//extern static int a; //static关键字的一个作用就是限制变量的范围,即作用域 不能被其他.C文件访问
typedef enum{red,blue,green}color;//可以被其他.c文件访问
//位域结构体 常用于嵌入式寄存器设置位
typedef struct{
union{//记住联合体共用一块内存 如同一笔钱 赋值的时候类比给钱
//[1]家长可以给每个孩子钱 [2]每个孩子凑成的钱=家长的钱 孩子的个头不同 变量大小不同 分的钱也不同
unsigned int uint32; //无符号整形范围 类比家长
struct{ //结构体内部变量 类比孩子
unsigned int uint16:16;//用于保存16位数据 范围:0-65535
unsigned int uint1:1; //用于保存1个位值 范围:0-1
unsigned int :15; //无用 只作为对齐填充,默认情况下值都是0
}bits;
}UNION;
}str_union;
extern str_union bitstruct;//可以被其他.c文件访问
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void setTextEdit();//显示所有值
void setColor(color val);//接收枚举变量
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
【4】mianwindow.c源文件解析
全局变量定义处,必不可少
在定义时可以赋值和不赋值,根据需求去写
/*全局变量定义处*/
node_t age_t;
int global;
int array[10]={0};
char str[8]="hello";//最多可存储8个字符
char *p="NULL";
bool global_bool=false;
str_union bitstruct;
变量初始化
对于结构体而言,一般使用这种方式初始化
memset(&bitstruct,0x00,sizeof (bitstruct));
使用两个函数来显示操作的记录
//设置显示文本
void MainWindow::setTextEdit()
{
ui->textEdit->append(QString("年龄=%1").arg(age_t.age));
ui->textEdit->append(tr("global=%1").arg(global));
ui->textEdit->append(tr("global_bool=%1").arg(global_bool));
ui->textEdit->append(tr("enum red=%1").arg(red));
ui->textEdit->append(tr("array[0]=%1").arg(*array));//只获取第一个值
ui->textEdit->append(tr("array[2]=%1").arg(array[2]));//只获取第3个值
ui->textEdit->append(tr("str=%1").arg(str));
ui->textEdit->append(tr("p=%1").arg(p));
if(global_bool ==true)
{
qDebug("孩子uint16->hex=0x%x ",bitstruct.UNION.bits.uint16);
qDebug("孩子uint1->hex=0x%x ",bitstruct.UNION.bits.uint1);
qDebug("家长uint32->hex=0x%x \r\n",bitstruct.UNION.uint32);
}
}
//接收一个枚举变量值
void MainWindow::setColor(color val)
{
ui->textEdit->append(tr("enum green=%1").arg(val));
}
【5】源文件源码
#include "mainwindow.h"
#include "ui_mainwindow.h"
/*全局变量定义处*/
node_t age_t;
int global;
int array[10]={0};
char str[8]="hello";//最多可存储8个字符
char *p="NULL";
bool global_bool=false;
str_union bitstruct;
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
global=100;//全局变量初始化
memset(&bitstruct,0x00,sizeof (bitstruct));
ui->textEdit->append(QString("结构体所有值=%1").arg(bitstruct.UNION.uint32));
}
MainWindow::~MainWindow()
{
delete ui;
}
//设置显示文本
void MainWindow::setTextEdit()
{
ui->textEdit->append(QString("年龄=%1").arg(age_t.age));
ui->textEdit->append(tr("global=%1").arg(global));
ui->textEdit->append(tr("global_bool=%1").arg(global_bool));
ui->textEdit->append(tr("enum red=%1").arg(red));
ui->textEdit->append(tr("array[0]=%1").arg(*array));//只获取第一个值
ui->textEdit->append(tr("array[2]=%1").arg(array[2]));//只获取第3个值
ui->textEdit->append(tr("str=%1").arg(str));
ui->textEdit->append(tr("p=%1").arg(p));
if(global_bool ==true)
{
qDebug("孩子uint16->hex=0x%x ",bitstruct.UNION.bits.uint16);
qDebug("孩子uint1->hex=0x%x ",bitstruct.UNION.bits.uint1);
qDebug("家长uint32->hex=0x%x \r\n",bitstruct.UNION.uint32);
}
}
//接收一个枚举变量值
void MainWindow::setColor(color val)
{
ui->textEdit->append(tr("enum green=%1").arg(val));
}
【6】main文件解析+源码
从mainwindow.c 到main.c就是本次项目的重点,
我们需要在main.c获取mianwindow.c里面的变量,需要做两点:
【1】在main.c添加mianwindow.c的头文件
【2】在mianwindow.c/h文件中 声明 定义全局变量
以下代码在嵌入式或者其他领域都是通用性的,请大家仔细阅读,并理解通透
#include "mainwindow.h"
#include <QDebug>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
age_t.age=100; //某个.c文件的全局结构体变量 在这里赋值
qDebug()<<age_t.age;
w.setTextEdit();
global =120; //某个.c文件的全局变量 在这里赋值
w.setTextEdit();
w.setColor(green);//某个.c文件的全局枚举变量 在这里赋值
//mainwindow数组修改值
array[0]=1;//赋值方式1
array[1]=2;
*(array+2)=3;//赋值方式2
//修改字符串值
str[0]='K';
w.setTextEdit();
//修改指针值
p="ignore waring";
global_bool=true;//某个.c文件的全局布尔变量 在这里赋值
/*unsigned int 占4字节 有32位 在下面的举例中 uint16 占unsigned int[0-31]中的低16位 0-15 可看成unsigned short
uint1 占unsigned int中的低17位 在16 其余不用的17-31保留复位值 */
//给结构体-联合体-结构体位设置值 分散设置
memset(&bitstruct,0x00,sizeof(bitstruct));//初始化的一种方式 复位全部为零
w.setTextEdit();
bitstruct.UNION.bits.uint16=0xffff;//2n次方 n=16 等65536 范围:0-65535 hex=0x0000 - 0xFFFF
bitstruct.UNION.bits.uint1=1; //2n次方 n=1 等2 范围:0-1 hex=0x0 - 0x1
w.setTextEdit();
//给结构体-联合体-结构体位设置值 一次性设置
memset(&bitstruct,0x00,sizeof(bitstruct));
bitstruct.UNION.uint32 |=(unsigned int)1<<16 ; //设置uint1 这个位=1 其他位保持不变 【嵌入式寄存器必用】
w.setTextEdit();
bitstruct.UNION.uint32 |=(unsigned int)1<<15 ; //设置uint16 最高位=1 其他位保持不变 【嵌入式寄存器必用】
w.setTextEdit();
bitstruct.UNION.uint32 =0x00018000;//将上面的两步一次性赋值
w.setTextEdit();
memset(&bitstruct,0x00,sizeof(bitstruct));
bitstruct.UNION.uint32 =0x00018000;//将上面的两步一次性赋值
bitstruct.UNION.uint32 &= ~((unsigned int)1<<16);//清空uint1这个位 其他位保持不变 【嵌入式寄存器必用】
w.setTextEdit();
//初始化的另一种方式 复位全部为零
int arry=0x00;
memcpy(&bitstruct,&arry,sizeof (arry));
w.setTextEdit();
w.show();
return a.exec();
}
【7】编译-链接-运行结果
打印结果
结构体所有值=0
年龄=100
global=100
global_bool=0
enum red=0
array[0]=0
array[2]=0
str=hello
p=NULL
年龄=100
global=120
global_bool=0
enum red=0
array[0]=0
array[2]=0
str=hello
p=NULL
enum green=2
年龄=100
global=120
global_bool=0
enum red=0
array[0]=1
array[2]=3
str=Kello
p=NULL
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
年龄=100
global=120
global_bool=1
enum red=0
array[0]=1
array[2]=3
str=Kello
p=ignore waring
文本框一次显示不完,输出结果就是上面这段,可以对比源码观看,效果更佳
位域结构体实例运行结果
11:01:10: Starting C:\Users\sujieyin\Desktop\QT\build-TEST-Desktop_Qt_5_14_2_MinGW_64_bit-Debug\debug\TEST.exe ...
100
孩子uint16->hex=0x0
孩子uint1->hex=0x0
家长uint32->hex=0x0
孩子uint16->hex=0xffff
孩子uint1->hex=0x1
家长uint32->hex=0x1ffff
孩子uint16->hex=0x0
孩子uint1->hex=0x1
家长uint32->hex=0x10000
孩子uint16->hex=0x8000
孩子uint1->hex=0x1
家长uint32->hex=0x18000
孩子uint16->hex=0x8000
孩子uint1->hex=0x1
家长uint32->hex=0x18000
孩子uint16->hex=0x8000
孩子uint1->hex=0x0
家长uint32->hex=0x8000
孩子uint16->hex=0x0
孩子uint1->hex=0x0
家长uint32->hex=0x0