关于结构体成员c语言 typedef structt

UNIX环境高级编程(21)
今天在定义结构体的时候发现typedef struct与struct定义结构体有一些不同之处:
结构也是一种数据类型, 可以使用结构变量, 因此, &象其它 类型的变量一样, 在使用结构变量时要先对其定义。 &&
定义结构变量的一般格式为: &&
& & &struct 结构名 &&
& & & & & 类型 &变量名; &&
& & & & & 类型 &变量名; &&
& & & & & ... &&
& & &} 结构变量; &&
&结构名是结构的标识符不是变量名。 &&
另一种常用格式为: & &&&
&typedef struct 结构名 &&
& & & & & 类型 &变量名; &&
& & & & & 类型 &变量名; &&
& & & & & ... &&
& & &} 结构别名; &&&
另外注意: &在C中,struct不能包含函数。在C++中,对struct进行了扩展,可以包含函数。 &
编程中gcc报错:&expected specifier-qualifier-list before sth。网上查了下出错原因,解释如下:
在使用GCC时经常会遇到expected specifier-qualifier-list before sth之类的错误。specifiers是指void、char、struct Foo等词汇;qualifiers是指像const和volatile一类的关键字。一个词汇在未定义之前就使用就会出项这种错误,可以通过typedef进行定义以后再使用。出错语句如下所示:
typedef struct {
typedef struct {
struct stu
//通过编译
}用struct定义结构体也会有同样的问题,解决方法也一样。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:63228次
积分:1541
积分:1541
排名:第19125名
原创:93篇
转载:14篇
(2)(11)(15)(14)(16)(24)(11)(2)(6)(4)(2)&&/&&&&/&&&&/&&
struct 是个神奇的关键字,它将一些相关联的数据打包成一个整体,方便使用。
在网络协议、通信控制、嵌入式系统、驱动开发等地方,我们经常要传送的不是简单的字节流(char 型数组),而是多种数据组合起来的一个整体,其表现形式是一个结构体。
经验不足的开发人员往往将所有需要传送的内容依顺序保存在char 型数组中,通过指针偏移的方法传送网络报文等信息。这样做编程复杂,易出错,而且一旦控制方式及通信协议有所变化,程序就要进行非常细致的修改,非常容易出错。这个时候只需要一个结构体就能搞定。平时我们要求函数的参数尽量不多于4 个,如果函数的参数多于4 个使用起来非常容易出错(包括每个参数的意义和顺序都容易弄错),效率也会降低(与具体CPU 有关,ARM芯片对于超过4 个参数的处理就有讲究,具体请参考相关资料)。这个时候,可以用结构体压缩参数个数。
一、空结构体多大?
结构体所占的内存大小是其成员所占内存之和(关于结构体的内存对齐,请参考预处理那章)。这点很容易理解,但是下面的这种情况呢?
struct student
sizeof(stu)的值是多少呢?在Visual C++ 6.0 上测试一下。
很遗憾,不是0,而是1。为什么呢?你想想,如果我们把struct student 看成一个模子的话,你能造出一个没有任何容积的模子吗?
显然不行。编译器也是如此认为。编译器认为任何一种数据类型都有其大小,用它来定义一个变量能够分配确定大小的空间。既然如此,编译器就理所当然的认为任何一个结构体都是有大小的,哪怕这个结构体为空。那万一结构体真的为空,它的大小为什么值比较合适呢?
假设结构体内只有一个char 型的数据成员,那其大小为1byte(这里先不考虑内存对齐的情况).也就是说非空结构体类型数据最少需要占一个字节的空间,而空结构体类型数据总不能比最小的非空结构体类型数据所占的空间大吧。这就麻烦了,空结构体的大小既不能为0,也不能大于1,怎么办?定义为0.5个byte?但是内存地址的最小单位是1 个byte,0.5 个byte 怎么处理?解决这个问题的最好办法就是折中,编译器理所当然的认为你构造一个结构体数据类型是用来打包一些数据成员的,而最小的数据成员需要1 个byte,编译器为每个结构体类型数据至少预留1 个byte的空间。所以,空结构体的大小就定位1 个byte。
二、柔性数组
也许你从来没有听说过柔性数组(flexible array)这个概念,但是它确实是存在的。
C99 中,结构中的最后一个元素允许是未知大小的数组,这就叫做柔性数组成员,但结构中的柔性数组成员前面必须至少一个其他成员。柔性数组成员允许结构中包含一个大小可变的数组。sizeof 返回的这种结构大小不包括柔性数组的内存。包含柔性数组成员的结构用malloc ()函数进行内存的动态分配,并且分配的内存应该大于结构的大小,以适应柔性数组的预期大小。
柔性数组到底如何使用呢?看下面例子:
typedef struct st_type
& &int a[0];
有些编译器会报错无法编译可以改成:
typedef struct st_type
& &int a[];
这样我们就可以定义一个可变长的结构体, 用sizeof(type_a) 得到的只有4 , 就是sizeof(i)=sizeof(int)。那个0 个元素的数组没有占用空间,而后我们可以进行变长操作了。通过如下表达式给结构体分配内存:
& &type_a *p = (type_a*)malloc(sizeof(type_a)+100*sizeof(int));
这样我们为结构体指针p 分配了一块内存。用p-&item[n]就能简单地访问可变长元素。
但是这时候我们再用sizeof(*p)测试结构体的大小,发现仍然为4。是不是很诡异?我们不是给这个数组分配了空间么?
别急,先回忆一下我们前面讲过的&模子&。在定义这个结构体的时候,模子的大小就已经确定不包含柔性数组的内存大小。柔性数组只是编外人员,不占结构体的编制。只是说在使用柔性数组时需要把它当作结构体的一个成员,仅此而已。再说白点,柔性数组其实与结构体没什么关系,只是&挂羊头卖狗肉&而已,算不得结构体的正式成员。
需要说明的是:C89 不支持这种东西,C99 把它作为一种特例加入了标准。但是,C99所支持的是incomplete type,而不是zero array,形同int item[0];这种形式是非法的,C99 支持的形式是形同int item[];只不过有些编译器把int item[0];作为非标准扩展来支持,而且在C99 发布之前已经有了这种非标准扩展了,C99 发布之后,有些编译器把两者合而为一了。
当然,上面既然用malloc 函数分配了内存,肯定就需要用free 函数来释放内存:
& &free(p);
经过上面的讲解,相信你已经掌握了这个看起来似乎很神秘的东西。不过实在要是没掌握也无所谓,这个东西实在很少用。
三、struct 与class 的区别
在C++里struct 关键字与class 关键字一般可以通用,只有一个很小的区别。struct 的成员默认情况下属性是public 的,而class 成员却是private 的。很多人觉得不好记,其实很容易。你平时用结构体时用public 修饰它的成员了吗?既然struct 关键字与class 关键字可以通用,你也不要认为结构体内不能放函数了。
当然,关于结构体的讨论远没有结束,在指针与数组那一章,你还会要和它打交道的。
推荐文章 TOP10关于WNDCLASSEX结构体中cbWndExtra成员的作用 - 推酷
关于WNDCLASSEX结构体中cbWndExtra成员的作用
有人问WNDCLASSEX结构体中cbWndExtra成员到底是做什么用的,在网上也查了一些资料,但说的都不太正确,MSDN上说的也较为含糊,但这个cbWndExtra成员的作用确实是较为重要,首先Windows默认的对话框类会用到它(即窗体类为#32770的对话框),几乎所有的Windows标准控件也会用到它,可以说cbWndExtra类给予了Windows窗体一个可扩展的途径,使得用户可以在HWND句柄中存储额外的数据。微软就是用这种方法在C语言上实施了面向对象“继承”的概念。
下面以创建一个自定义组件为例,介绍WNDCLASSEX结构体中cbWndExtra成员的用法。
第一步,注册窗体类
在注册窗体类时,设置cbWndExtra成员的值。
/// 窗体句柄附加数据长度
#define CTRLWINDOWEXTRA 32
/// 声明回调函数的宏
#define DECLARE_WNDPROC(ProcName) \
LRESULT CALLBACK ProcName(HWND, UINT, WPARAM, LPARAM);
/// 声明钟表组件的消息回调函数
DECLARE_WNDPROC(ClockCtrlProc)
/// 注册窗体类
ATOM _RegistCtrlClass(HINSTANCE hInst, LPCTSTR lpszClsName, WNDPROC pWndProc)
WNDCLASSEX wcex = {
sizeof(WNDCLASSEX),
CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS,
0, CTRLWINDOWEXTRA, hInst, NULL, NULL,
(HBRUSH)(COLOR_BTNFACE + 1),
0, lpszClsName, NULL
return RegisterClassEx(&wcex);
/// 初始化用户自定义控件
BOOL InitializeUserControls()
ATOM atom = _RegistCtrlClass(_INSTANCE, _T("ClockCtrl"), (WNDPROC)ClockCtrlProc);
_ASSERT(atom);
if (atom == 0)
return FALSE;
return TRUE;
CTRLWINDOWEXTRA
宏就定义了要预留空间的大小,本例中为32字节,可以取值为0~40字节,而且数值应该为4的倍数(或者sizeof(long)的倍数)。
第二步:定义要存储的数据类型
/// 保存绘图对象的结构体
typedef struct tagCLK_GDIOBJ
HBRUSH brushBackground,
// 控件背景画刷
brushDigitalDark,
// 数字表盘暗色画刷
brushDigitalLight,
// 数字表盘亮色画刷
brushClockB // 表盘背景
LOGFONT fontDate,
// 控件全局字体
fontClockN // 表盘数字字体
HPEN penBorder,
// 控件边框画笔
penDigitalBorder, // 数字边框画笔
penClockBorder,
// 表盘边框画笔
// 表盘箭头画笔
} CLK_GDIOBJ, *LPCLK_GDIOBJ;
/// 保存运行时信息的结构体
typedef struct tagCLK_RUNTIME
SYSTEMTIME stimN // 当前时间
BOOL isDigitalSecondD // 数字表盘的秒针是否为灰色
UINT_PTR timS // 按秒进行的定时器句柄
} CLK_RUNTIME, *LPCLK_RUNTIME;
/// 表示数据位置的常量
#define CLKP_GDIOBJ 0 // 0~3字节存放CLK_GDIOBJ结构体变量地址
#define CLKP_RUNTIME (CLKP_GDIOBJ + sizeof(LPCLK_GDIOBJ)) // 4~7字节存放CLK_RUNTIME结构体变量地址
这里定义了两个结构体,一个用于存储GDI对象,一个用于存储运行时状态,这两个结构体的变量都应该和对应的窗口(HWND)句柄进行绑定,这样才能做到令窗体类为“ClockCtrl”的不同窗体都能取到正确的,属于自己的数据。
这里定义的两个宏
CLKP_GDIOBJ
CLKP_RUNTIME
分别用于存储上述两个结构体变量,由于存储的只能是指针类型(这两个结构体的大小必然超出了cbWndExtra成员的规定大小),所以两个宏表示的值相差4个字节。
第三步:存储数据
存储数据主要使用
SetWindowLongPtr
(或者SetWindowLong,已不再推荐使用)函数,使用起来非常简单。
/// 窗口创建消息
int _OnCreate(HWND hCtrl, LPCREATESTRUCT lpcs)
LPCLK_GDIOBJ pG
LPCLK_RUNTIME pRunTm;
HFONT fontD
if (!_LOCHEAP)
_LOCHEAP = HeapCreate(0, 0, 0);
// 创建本地堆句柄
fontDef = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
/// 设置默认的GDI对象
pGdi = HeapAlloc(_LOCHEAP, HEAP_ZERO_MEMORY, sizeof(CLK_GDIOBJ));
GetObject(fontDef, sizeof(LOGFONT), &pGdi->fontDate);
GetObject(fontDef, sizeof(LOGFONT), &pGdi->fontClockNumber);
pGdi->brushBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
pGdi->brushClockBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
pGdi->brushDigitalDark = CreateSolidBrush(RGB(0xEE, 0xEE, 0xEE));
pGdi->brushDigitalLight = CreateSolidBrush(RGB(0xFF, 0, 0));
pGdi->penBorder = CreatePen(PS_SOLID, 1, RGB(0x90, 0xC4, 0xE8));
pGdi->penClockArrow = (HPEN)GetStockObject(BLACK_PEN);
pGdi->penClockBorder = (HPEN)GetStockObject(BLACK_PEN);
pGdi->penDigitalBorder = (HPEN)GetStockObject(WHITE_PEN);
SetWindowLongPtr(hCtrl, CLKP_GDIOBJ, (LONG_PTR)pGdi); // 存储GDI对象结构体指针
/// 设置默认的运行时状态
pRunTm = HeapAlloc(_LOCHEAP, HEAP_ZERO_MEMORY, sizeof(CLK_RUNTIME));
pRunTm->isDigitalSecondDark = FALSE;
GetLocalTime(&pRunTm->stimNow);
SetWindowLongPtr(hCtrl, CLKP_RUNTIME, (LONG_PTR)pRunTm); // 存储运行时状态结构体指针
SendMessage(hCtrl, WM_START, 0, 0); // 发送启动消息
可以看到,上述代码使用
SetWindowLongPtr
函数,在0(CLKP_GDIOBJ)位置存储了CLK_GDIOBJ结构体的指针,在4(CLKP_RUNTIME)位置存储了CLK_RUNTIME结构体的指针,这样就相当于我们扩展了HWND句柄,在其中存储了我们所需的数据。
第四步:获取数据
获取数据主要使用GetWindowLongPtr(同理,也可以为GetWindowLong,但不推荐)函数,执行之前代码的反向操作即可。
/// 窗口销毁消息
void _OnDestory(HWND hCtrl)
LPCLK_GDIOBJ pG
LPCLK_RUNTIME pRunTm;
pGdi = (LPCLK_GDIOBJ)GetWindowLongPtr(hCtrl, CLKP_GDIOBJ); // 获取GDI对象结构体
/// 删除所有的GDI对象
DeleteObject(pGdi->brushBackground);
DeleteObject(pGdi->brushClockBackground);
DeleteObject(pGdi->brushDigitalDark);
DeleteObject(pGdi->brushDigitalLight);
DeleteObject(pGdi->penBorder);
DeleteObject(pGdi->penClockArrow);
DeleteObject(pGdi->penClockBorder);
HeapFree(_LOCHEAP, 0, pGdi); // 从内存中删除结构体
pRunTm = (LPCLK_RUNTIME)GetWindowLongPtr(hCtrl, CLKP_RUNTIME); // 获取运行时状态结构体
if (pRunTm)
KillTimer(hCtrl, pRunTm->timSecond); // 停止定时器
HeapFree(_LOCHEAP, 0, pRunTm); // 从内存中删除结构体
可以看到,上述代码使用
GetWindowLongPtr
函数,在0(CLKP_GDIOBJ)位置获取了CLK_GDIOBJ结构体的指针,在4(CLKP_RUNTIME)位置获取了CLK_RUNTIME结构体的指针,这样就取到了我们之前存储的数据。
首先,WNDCLASSEX结构体中cbWndExtra成员表示
“为每个窗体预留的空间大小”
,即使用指定窗体类创建的每个窗体都有这么个空间,但存储的值各不相关。cbWndExtra的值可以在0~40之间,单位是字节,并非固定大小,可由程序员自行掌握。(例如Windows在创建标准对话框类#32770时,cbWndExtra成员值为DLGWINDOWEXTRA,DLGWINDOWEXTRA宏的值为30,表示每个对话框窗口有额外30个字节的空间可以使用)。
其次,设置和获取额外空间内容时,是按照字节数来获取而非数据存放的顺序索引。例如:SetWindowLongPtr(hWnd, 0, 1234L)表示在额外空间从0字节开始的位置设置内容1234,用掉4个字节;而SetWindowLongPtr(hWnd, 8, _T(&Hello&))表示在额外空间的第9个字节开始设置内容&Hello&指针,也用掉4个字节。由于SetWindowLongPtr设置的值(以及GetWindowLongPtr获取的值)类型为sizeof(LONG_PTR)类型,所以对于额外空间的存取颗粒度应该总是4字节的。
最后,cbWndExtra成员和使用GWLP_USERDATA(或者GWL_USERDATA)设置和获取的值无关,每个HWND句柄都关联了4(或者sizeof(void*))字节的空间,可以随时通过SetWindowLongPtr(hWnd,&GWLP_USERDATA, 一个LONG值)设置以及通过GetWindowLongPtr(hWnd, GWLP_USERDATA)获取,但要使用cbWndExtra成员指定的空间,则必须在注册窗体类时,预先预留好指定的大小,否则无法使用。
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致结构体成员为数组,该如何初始化typedef struct ABCD_STRU{ &
char A[16]; &
char B[16]; &
char C[16]; &
char D[16];}ABCD;我想把该结构体成员都初始化为“0000”该如何做?strcpy(ABCD.A, “0000”);strcpy(ABCD.B, “0000”);strcpy(ABCD.C, “0000”);strcpy(ABCD.D, “0000”);这样操作有问题吗?
回答1:  C/C++ code  #include &stdlib.h&
#include &stdio.h&
#include &string.h&
typedef struct
char A[16], B[16], C[16], D[16];
int main()
memset(&test, '0', sizeof(test));
#define end(name) test.name[15]
end(A) = end(B) = end(C) = end(D) = '\0';
#undef end
#define str(name) test.name
printf(&%s %s %s %s\n&, str(A), str(B), str(C), str(D));
回答2:探讨C/C++ codestrcpy(ABCD.A, “0000”);strcpy(ABCD.B, “0000”);strcpy(ABCD.C, “0000”);strcpy(ABCD.D, “0000”);//应改为strcpy(ABCD.A,&000&);……
sun_qin2005> 问题详情
下列结构体类型说明和变量定义中正确的是( 。 A.typedefstruct; {intn;charC;}REC; RECt1,t2;
悬赏:0&答案豆
提问人:匿名网友
发布时间:
下列结构体类型说明和变量定义中正确的是( 。A.typedefstruct; {intn;charC;}REC; RECt1,t2;B.structREC; {intn;charC;} RECt1,t2;C.typedefstructREC; {intn=0;charc=A;}t1,t2D.struct {intn;charC;}REC; RECt1,t2请帮忙给出正确答案和分析,谢谢!
您可能感兴趣的试题
1有如下程序:#include&iostream&usingnamespacestd;classConcharID;public:Con():ID(A){cout&&1;}Con(charID):ID(ID){eout&&2;}Con(Con&c):ID(c.getID()){cout&&3;}chargetID()corlst{returnID;}};voidshow(Conc)(cout&&C.getID();}intmain(){Conc1:show(c1);Conc2(B);show(c2);return0;}执行上面程序的输出是(  )。A.13A23AB.23A13BC.13A23BD.13823A2使用白盒测试法时,确定测试数据应该根据(  )和指定的覆盖标准。A.程序的内部逻辑B.程序的复杂结构C.使用说明书D.程序的功能
我有更好的答案
论文写作技巧
相关考试课程
请先输入下方的验证码查看最佳答案
图形验证:
验证码提交中……

我要回帖

更多关于 typedef struct a b 的文章

 

随机推荐