随笔 - 14, 文章 - 2, 评论 - 1, 引用 - 0
数据加载中……

指针 数组 const

函数指针

类型说明符 (*函数名)(参数)
int (*func)(int *p);

首先找到那个未定义的标识符,就是func,它的外面有一对圆括号,而且左边是一个*号,这说明func是一个指针,然后跳出这个圆括号,先看右边,也是一个圆括号,这说明(*func)是一个函数,而func是一个指向这类函数的指针,就是一个函数指针,这类函数具有int*类型的形参,返回值类型是int。

int (*func)(int *p, int (*f)(int*));

func被一对括号包含,且左边有一个*号,说明func是一个指针,跳出括号,右边也有个括号,那么func是一个指向函数的指针,这类函数具有int *和int (*)(int*)这样的形参,返回值为int类型。再来看一看func的形参int (*f)(int*),类似前面的解释,f也是一个函数指针,指向的函数具有int*类型的形参,返回值为int。

int (*func[5])(int *p);

func右边是一个[]运算符,说明func是一个具有5个元素的数组,func的左边有一个*,说明func的元素是指针,要注意这里的*不是修饰func的,而是修饰func[5]的,原因是[]运算符优先级比*高,func先跟[]结合,因此*修饰的是func[5]。跳出这个括号,看右边,也是一对圆括号,说明func数组的元素是函数类型的指针,它所指向的函数具有int*类型的形参,返回值类型为int。

函数指针数组是一个其元素是函数指针的数组。那么也就是说,此数据结构是是一个数组,且其元素是一个指向函数入口地址的指针。
根据分析:首先说明是一个数组:数组名[]
其次,要说明其元素的数据类型指针:*数组名[].
再次,要明确这每一个数组元素是指向函数入口地址的指针:函数返回值类型 (*数组名[])().请注意,这里为什么要把“*数组名[]”用括号扩起来呢?因为圆括号和数组说明符的优先级是等同的,如果不用圆括号把指针数组说明表达式扩起来,根据圆括号和方括号的结合方向,那么 *数组名[]() 说明的是什么呢?是元素返回值类型为指针的函数数组。有这样的函数数祖吗?不知道。所以必须括起来,以保证数组的每一个元素是指针。


int (*(*func)[5])(int *p);

func被一个圆括号包含,左边又有一个*,那么func是一个指针,跳出括号,右边是一个[]运算符号,说明func是一个指向数组的指针,现在往左看,左边有一个*号,说明这个数组的元素是指针,再跳出括号,右边又有一个括号,说明这个数组的元素是指向函数的指针。总结一下,就是:func是一个指向数组的指针,这个数组的元素是函数指针,这些指针指向具有int*形参,返回值为int类型的函数。


指针数组与数组指针

*p[2]:指针数组。 按照符号优先级来看,下标[ ]优先于指针*,所以可以看作是*(p[2]),那么应该首先是一个数组
p[2]。而该数组的每个元素都是指针。
指针数组:一个数组里存放的都是同一个类型的指针,通常我们把他叫做指针数组。
比如 int * a[10];它里边放了10个int * 型变量,由于它是一个数组,已经在栈区分配了10个(int * )的空间,也就是32位机上是40个byte,每个空间都可以存放一个int型变量的地址,这个时候你可以为这个数组的每一个元素初始化,在,或者单独做个循环去初始化它。

(*p)[2]:数组指针。按照符号优先级来看,括号( )优先于[ ],那么应该首先是一个指针。而该指针指向一个数组。
数组指针 : 一个指向一维或者多维数组的指针;
int * b=new int[10]; 指向一维数组的指针b ;
注意,这个时候释放空间一定要delete [] ,否则会造成内存泄露, b 就成为了空悬指针.
int (*b2)[10]=new int[10][10]; 注意,这里的b2指向了一个二维int型数组的首地址.
注意:在这里,b2等效于二维数组名,但没有指出其边界,即最高维的元素数量,但是它的最低维数的元素数量必须要指定!就像指向字符的指针,即等效一个字符串,不要把指向字符的指针说成指向字符串的指针。这与数组的嵌套定义相一致。 
int (*b2) [20];     //二级指针;
b2=new int [30] [20]; 

Const
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,则const就是修饰指针本身,即指针本身是常量。



posted @ 2008-07-21 13:46 Jeremy1111 阅读(751) | 评论 (0)编辑 收藏

C/C++中宏的使用

关于## 和 #及#@的用法


## 是连接符号 连接两个宏,##被称为连接符(concatenator),用来将两个Token连接为一个Token。注意这里连接的对象是Token就行,而不一定是宏的变
量。比如你要做一个菜单项命令名和函数指针组成的结构体的数组,并且希望在函数名和菜单项命令名之间有直观的、名字上的关系。那就可以使用:宏参数##
固定部分。当然还可以n个##符号连接 n+1个Token,这个特性也是#符号所不具备的。
#define LINK_MULTIPLE(a,b,c,d) a##_##b##_##c##_##d
typedef struct _record_type LINK_MULTIPLE(name,company,position,salary);
// 这里这个语句将展开为:
//      typedef struct _record_type name_company_position_salary;


#@功能是将其后面的宏参数进行字符化。
#define makechar(x)  #@x
a
= makechar(b);
//a = 'b';


#是把名字代替成字符串,宏体中,#的功能是将其后面的宏参数进行字符串化操作(Stringfication),简单说就是在对它所引用的宏变量通过替换后在其左右各加上一个
双引号。
#define WARN_IF(EXP)        \
        do{ if (EXP)        \
                fprintf(stderr, "Warning: " #EXP "\n"); }       \
        while(0)
那么实际使用中会出现下面所示的替换过程:
WARN_IF (divider == 0);
被替换为
do {
        if (divider == 0)
fprintf(stderr, "Warning" "divider == 0" "\n");
} while(0);
这样每次divider(除数)为0的时候便会在标准错误流上输出一个提示信息。


!IF constantexpression

如果 constantexpression 计算结果为非零值,则处理 !IF 和下一个 !ELSE!ENDIF 之间的语句。
!ENDIF

标记 !IF!IFDEF!IFNDEF 块的结尾。同一行上 !ENDIF 后面的所有文本被忽略。

posted @ 2008-07-16 15:09 Jeremy1111 阅读(209) | 评论 (0)编辑 收藏

DDK中build说明

设备驱动程序一般都使用BUILD实用程序来进行,BUILD只是
NMAKE外面的一个外包装程序。BUILD本身其实相当简单,编
译的大部分工作实际上由BUILD传递给NMAKE来进行

posted @ 2008-07-15 17:19 Jeremy1111 阅读(519) | 评论 (0)编辑 收藏

DDK中build脚本中涉及相关 批处理

语法
ECHO [ON|OFF]
若要用echo命令显示一条命令,可用下述语法:
echo [message]
参数 ON|OFF
指定是否允许命令的回显。若要显示当前的ECHO的设置,可使用不带参数的
ECHO
命令。
message
指定让MS-DOS在屏幕上显示的正文。

还可以用这种方式查看变量值
set XP_TEST=$(XP_TEST)
@echo (%XP_TEST%)

CALL

从一个批处理程序中调用另一个批处理程序,而不会引起第一个批处理的中止。

语法
CALL [drive:][path]filename [batch-parameters]

参数
[drive:][path]filename
指定要调用的批处理程序的名字及其存放处。文件名必须用.BAT作扩展名。

batch-parameters
指定批处理程序所需的命令行信息。

PAUSE

暂停批处理程序的执行并显示一条消息,提示用户按任意键继续执行。只能在批处
理程序中使用该命令。

语法

PAUSE

REM

在批处理文件或CONFIG.SYS中加入注解。也可用REM命令来屏蔽命令(在CONFIG.SYS
中也可以用分号(;)代替REM命令,但在批处理文件中则不能替代)。

语法

REM [string]

参数

string
指定要屏蔽的命令或要包含的注解。

批处理文件的参数

批处理文件还可以像C语言的函数一样使用参数(相当于DOS命令的命令行参数),这需要用到一个参数表示符"%"

%[1-9]表示参数,参数是指在运行批处理文件时在文件名后加的以空格(或者Tab)分隔的字符串。变量可以从%0%9%0表示批处理命令本身,其它参数字符串用%1%9顺序表示。

2C:根目录下有一批处理文件名为f.bat,内容为:
@echo off
format %1

如果执行C:\>f a:
那么在执行f.bat时,%1就表示a:,这样format %1就相当于format a:,于是上面的命令运行时实际执行的是format a:

3C:根目录下一批处理文件名为t.bat,内容为:
@echo off
type %1
type %2

那么运行C:\>t a.txt b.txt
%1 :
表示
a.txt
%2 :
表示
b.txt
于是上面的命令将顺序地显示a.txtb.txt文件的内容。
pushd 和 popd
切换当前目录
@echo off
c: & cd\ & md mp3    #在 C:\ 建立 mp3 文件夹
md d:\mp4             #在 D:\ 建立 mp4 文件夹
cd /d d:\mp4          #更改当前目录为 d:\mp4
pushd c:\mp3          #保存当前目录,并切换当前目录为 c:\mp3
popd                    #恢复当前目录为刚才保存的 d:\mp4


环境变量
%ALLUSERSPROFILE%
局部
返回“所有用户配置文件”的位置。

%APPDATA%
局部
返回默认情况下应用程序存储数据的位置。

%CD%
局部
返回当前目录字符串。

%CMDCMDLINE%
局部
返回用来启动当前的 Cmd.exe 的准确命令行。

%CMDEXTVERSION%
系统
返回当前的“命令处理程序扩展”的版本号。

%COMPUTERNAME%
系统
返回计算机的名称。

%COMSPEC%
系统
返回命令行解释器可执行程序的准确路径。

%DATE%
系统
返回当前日期。使用与 date /t 命令相同的格式。由 Cmd.exe 生成。

%ERRORLEVEL%
系统
返回上一条命令的错误代码。通常用非零值表示错误。

%HOMEDRIVE%
系统
返回连接到用户主目录的本地工作站驱动器号。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。

%HOMEPATH%
系统
返回用户主目录的完整路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。

%HOMESHARE%
系统
返回用户的共享主目录的网络路径。基于主目录值而设置。用户主目录是在“本地用户和组”中指定的。

%LOGONSERVER%
局部
返回验证当前登录会话的域控制器的名称。

%NUMBER_OF_PROCESSORS%
系统
指定安装在计算机上的处理器的数目。

%OS%
系统
返回操作系统名称。Windows 2000 会将该操作系统显示为 Windows NT。

%PATH%
系统
指定可执行文件的搜索路径。

%PATHEXT%
系统
返回操作系统认为可执行的文件扩展名的列表。

%PROCESSOR_ARCHITECTURE%
系统
返回处理器的芯片体系结构。值:x86 或 IA64(基于 Itanium)。

%PROCESSOR_IDENTFIER%
系统
返回处理器说明。

%PROCESSOR_LEVEL%
系统
返回计算机上安装的处理器的型号。

%PROCESSOR_REVISION%
系统
返回处理器的版本号。

%PROMPT%
局部
返回当前解释程序的命令提示符设置。由 Cmd.exe 生成。

%RANDOM%
系统
返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。

%SYSTEMDRIVE%
系统
返回包含 Windows 服务器操作系统根目录(即系统根目录)的驱动器。

%SYSTEMROOT%
系统
返回 Windows 服务器操作系统目录的位置。

%TEMP% 和 %TMP%
系统和用户
返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其他应用程序则需要 TMP。

%TIME%
系统
返回当前时间。使用与 time /t 命令相同的格式。由 Cmd.exe 生成。

%USERDOMAIN%
局部
返回包含用户帐户的域的名称。

%USERNAME%
局部
返回当前登录的用户的名称。

%USERPROFILE%
局部
返回当前用户的配置文件的位置。

%WINDIR%
系统
返回操作系统目录的位置。

posted @ 2008-07-14 14:03 Jeremy1111 阅读(897) | 评论 (0)编辑 收藏

仅列出标题
共2页: 1 2