精华内容
下载资源
问答
  • 调用规范stdcall和c语言的区别在函数参数处理上不同 _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32 Api都采用_stdcall调用方式 _cdecl是C/C++的缺省调用...

    华为c语言编程规范是怎样的

    2011 版本 附件传给你了。

    调用规范stdcall和c语言的区别

    878785cf76ac4ecdb93cc9d43b2b7586.png

    在函数参数处理上不同 _stdcall是Pascal程序的缺省调用方式,参数采用从右到左的压栈方式,被调函数自身在返回前清空堆栈。WIN32 Api都采用_stdcall调用方式 _cdecl是C/C++的缺省调用方式,参数采用从右到左的压栈方式。

    调用函数时规范的编程是吧主函数main写在前面呢还是把调用函数写在前面??

    实用的C语言编程规范 简介: 在项目团队协作开发的情况下,编程时应该强调的一个重要方面是程序的易读性,在保证软件速度等性能指标能满足用户需CSS布局HTML小编今天和大家分享的情况下,能让其他程序员容易读懂你所编写的程序。若项目小组的所有开发人员都遵循统一的、鲜明

    简洁紧凑、灵活方便 C语言一共只有32个关键字,9种控制语句,程序书写自由,主要用小写字母表示。它把高级语言的基本结构和语句与低级语言的实用性结合起来。 C 语言可以象汇编语言一样对位、字节和地址进行操作, 而这三者是计

    一,C语言的特点1,语言简洁,紧凑,使用方便,灵活2,运算符丰富3,数据类型丰富,具有现代语言的各种数据结构4,具有结构化的控制语句5,语法限制不太严格,程序设计自由度大6,C语言允许直接访问物理地址,能进行位(bit)操作。

    linux 下c编程.linux系统调用和c标准函数有什么区标准的c函数库是所有的编译都要具有的函数库,(实际上还是略有不同),但是这些基本上实现方法略有不同,但是结果和标准是一样的。但是linux的系统调用,调用是linux的系统库,比如说unistd.h下的fork这个是Linux下特有,你在vs上。

    c,c++的编程规范如此晦涩,怎么还有那么多人遵从?

    在学校和工作初期一直在搞java和c#, 最近换工作开始搞c, c++. 这开始阶C语言发展如此迅速,而且成为最受欢迎的语言之一,主要因为它具有强大的功能。许多著名的系统软件,如DBASE Ⅳ都是由C 语言编写的。用C 语言加上一些汇编语言子程序,就更能显示C 语言的优势了,像PC- DOS 、WORDSTAR等就是用这种方法编写的。

    展开全文
  • 常见C/C++函数调用规范

    千次阅读 2010-12-03 22:22:00
    大多数API都采用__stdcall调用规范,这是因为几乎所有的语言都支持__stdcall调用.相比之下,__cdecl只有在C语言中才能用. 但是__cdecl调用有一个特点,就是能够实现可变参数的函数调用,比如printf,这用__stdc

    例子不太好举啊,其实就是在函数声明的时候多加一个关键字,比如很多API函数就是象这样声明的:
    int   WINAPI   MessageBoxA(HWND,LPCSTR,LPSTR,UINT);
    而WINAPI实际上就是__stdcall.
    大多数API都采用__stdcall调用规范,这是因为几乎所有的语言都支持__stdcall调用.相比之下,__cdecl只有在C语言中才能用. 但是__cdecl调用有一个特点,就是能够实现可变参数的函数调用,比如printf,这用__stdcall调用是不可能的.
    __fastcall这种调用规范比较少见,但是在Borland   C++   Builder中比较多的采用了这种调用方式.
    如果有共享代码的需要,比如写DLL,推荐的方法是用__stdcall调用,因为这样适用范围最广.如果是C++语言写的代码供Delphi这样的语言调用就必须声明为__stdcall,因为Pascal不支持cdecl调用(或许Delphi的最新版本能够支持也说不定,这个我不太清楚).在其他一些地方,比如写COM组件,几乎都用的是stdcall调用.在VC或Delphi或C++Builder里面都可以从项目设置中更改默认的函数调用规范,当然你也可以在函数声明的时候加入__stdcall,__cdecl,__fastcall关键字来明确的指示本函数用哪种调用规范.
    __declspec一般都是用来声明DLL中的导出函数.这个关键字也有一些其他的用法,不过非常罕见.

    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~·

    几种函数调用方式

    __cdecl 是C DECLaration的缩写(declaration,声明),表示C语言默认的函数调用方法:所有参数从右到左依次入栈,这些参数由调用者清除,称为手动清栈。被调用函数不需要求调用者传递多少参数,调用者传递过多或者过少的参数,甚至完全不同的参数都不会产生编译阶段的错误。

    _stdcall 是StandardCall的缩写,是C++的标准调用方式:所有参数从右到左依次入栈,如果是调用类成员的话,最后一个入栈的是this指针。这些堆栈中的参数由被调用的函数在返回后清除,使用的指令是 retnX,X表示参数占用的字节数,CPU在ret之后自动弹出X个字节的堆栈空间。称为自动清栈。函数在编译的时候就必须确定参数个数,并且调用者必须严格的控制参数的生成,不能多,不能少,否则返回后会出错。

    PASCAL 是Pascal语言的函数调用方式,也可以在C/C++中使用,参数压栈顺序与前两者相反。返回时的清栈方式忘记了……

    _fastcall是编译器指定的快速调用方式。由于大多数的函数参数个数很少,使用堆栈传递比较费时。因此_fastcall通常规定将前两个(或若干个)参数由寄存器传递,其余参数还是通过堆栈传递。不同编译器编译的程序规定的寄存器不同。返回方式和_stdcall相当。

    _thiscall 是为了解决类成员调用中this指针传递而规定的。_thiscall要求把this指针放在特定寄存器中,该寄存器由编译器决定。VC使用ecx,Borland的C++编译器使用eax。返回方式和_stdcall相当。

    _fastcall 和 _thiscall涉及的寄存器由编译器决定,因此不能用作跨编译器的接口。所以Windows上的COM对象接口都定义为_stdcall调用方式。

    C中不加说明默认函数为_cdecl方式(C中也只能用这种方式),C++也一样,但是默认的调用方式可以在IDE环境中设置。

    带有可变参数的函数必须且只能使用_cdecl方式,例如下面的函数:

    int printf(char * fmtStr, ...);

    int scanf(char * fmtStr, ...);

    */几种调用约定的区别

    编辑本段几种调用约定的区别

    __cdecl __fastcall与 __stdcall,三者都是调用约定(Calling convention),它决定以下内容:1)函数参数的压栈顺序,2)由调用者还是被调用者把参数弹出栈,3)以及产生函数修饰名的方法。

    1、__stdcall调用约定:函数的参数自右向左通过栈传递,被调用的函数在返回前清理传送参数的内存栈,

    2、_cdecl是C和C++程序的缺省调用方式。每一个调用它的函数都包含清空堆栈的代码,所以产生的可执行文件大小会比调用_stdcall函数的大。函数采用从右到左的压栈方式。注意:对于可变参数的成员函数,始终使用__cdecl的转换方式。

    3、__fastcall调用约定:它是通过寄存器来传送参数的(实际上,它用ECX和EDX传送前两个双字(DWORD)或更小的参数,剩下的参数仍旧自右向左压栈传送,被调用的函数在返回前清理传送参数的内存栈)。

    4、thiscall仅仅应用于"C++"成员函数。this指针存放于CX寄存器,参数从右到左压。thiscall不是关键词,因此不能被程序员指定。

    5、nakedcall采用1-4的调用约定时,如果必要的话,进入函数时编译器会产生代码来保存ESI,EDI,EBX,EBP寄存器,退出函数时则产生代码恢复这些寄存器的内容。naked call不产生这样的代码。naked call不是类型修饰符,故必须和_declspec共同使用。

    编辑本段名字修饰约定

    1、修饰名(Decoration name):"C"或者"C++"函数在内部(编译和链接)通过修饰名识别

    2、C编译时函数名修饰约定规则:

    __stdcall调用约定在输出函数名前加上一个下划线前缀,后面加上一个"@"符号和其参数的字节数,格式为_functionname@number,例如 :function(int a, int b),其修饰名为:_function@8

    __cdecl调用约定仅在输出函数名前加上一个下划线前缀,格式为_functionname。

    __fastcall调用约定在输出函数名前加上一个"@"符号,后面也是一个"@"符号和其参数的字节数,格式为@functionname@number。

    编辑本段设置方法

    1 可以直接在代码中写 __cdecl 等调用约定

    2 在MS-VC++6.0中,调用约定也可以通过工程设置:Setting.../C/C++ /Code Generation项进行选择,缺省状态为__cdecl。名字修饰约定。

    展开全文
  • 日志文件推荐至少保存15天,因为有些异常具备以“周”为频次发生的特点C .避免重复打印日志,浪费磁盘空间,务必在log4j.xml中设置additivity=false。 D .错误日志和业务日志尽量分开存放。 多选 16.关于...
  • C 向 C++ 进阶系列导航 1. C++ 标准库简介 C++ 标准库(C++ Standard Library),是类库和函数的集合。C++ 编译器厂商根据 C++ 标准委员会官方的 ISO 规范并将其转化为代码。C++ 编译器厂商在实现 C++ 标准库...

    1. C++ 标准库简介

    C++ 标准库(C++ Standard Library),是类库和函数的集合。C++ 编译器厂商根据 C++ 标准委员会官方的 ISO 规范并将其转化为代码。C++ 编译器厂商在实现 C++ 标准库过程中必须依赖其不同操作系统所提供的系统调用接口,因此每个平台都有其自己的 C++ 标准库实现。C++ 标准库的特点如下:

    • C++ 标准库不是 C++ 语言标准的一部分,由类库和函数库组成。
    • C++ 标准库中定义的类和对象都位于 std 命名空间中。
    • C++ 标准库的头文件都不带 .h 后缀。
    • C++ 标准库包含一个涵盖 C 库功能的子库,通常头文件以 c 开头吗,如 #include 、#include 等。

    2. 标准输入输出

    C++ 中的输入输出实际使用了输入输出流对象,类与对象的实现与创建在 中完成。输入输出流有以下四种:

    流对象 含义 设备
    cin 标准输入 键盘
    cout 标准输出 屏幕
    cerr 错误输出 屏幕
    clog 错误缓存输出 屏幕

    最常用的应该就是 cin、cout 这两个对象,并且 cin 对运算符 “>>” 进行重载,cout 对运算符 “<<” 进行重载,从而实现了形象的输入输出功能。

    • 示例:
    int main(int argc, char *argv[])
    {
    	int num = 16;
    	cout << "num = " << num << endl;                // num = 16
    	cout << hex << "hex:num = " << num << endl;     // hex:num = 10
    	cout << oct << "oct:num = " << num << endl;     // oct:num = 20
    }
    

    更多从 C 向 C++ 进阶系列博文

    展开全文
  • 本书按照C语言的新标准C 99进行介绍,所有程序都符合C 99的规定,使编写程序更加规范;对C语言和程序设计的基本概念和要点讲解透彻,全面而深入;按照作者提出的“提出问题—解决问题—归纳分析”三部曲进行教学、...
  • 特点是效率高、跨平台、完全异步,当然这是从boost.asio继承而来; 自动重连,数据透明传输,自动解决分包粘包问题(你可以像udp一样使用它); 注:只支持tcp协议; 教程:...
  • 全书最后还有三个附录,分别给出了过程调用交叉参考表、程序代码中用到的c数据结构交叉参考表以及xinu函数和常量。本书可供计算机和通信专业的研究生、高年级本科生作为教科书和学习参考书,也可供各种从事科研的...
  • 1.3、特点 2、对C使用Mock 2.1、安装 2.2、配置 2.3、优缺点 3、Mock规范使用 3.1、sample代码 3.2、核心关键字解析 3.2.1、调用次数约束(expects()/stubs()) 3.2.2、调用者选择器(caller) 3.2.3、...

    目录

    1、Mock介绍

    1.1、概述        

    1.2、相关概念

    1.3、特点

    2、对C使用Mock

    2.1、安装

    2.2、配置

    2.3、优缺点

    3、Mock规范使用

    3.1、sample代码

    3.2、核心关键字解析

    3.2.1、调用次数约束(expects()/stubs())

    3.2.2、调用者选择器(caller)

    3.2.3、函数参数约束(with)

    3.2.4、调用次序(before、id、after)

    3.2.5、函数调用行为(will、then)

    3.3、难点代码演练

    3.3.1、函数调用行为指定返回值       

    3.3.2、入参数约束之内存监控(参数类型也参与检查)

    3.3.3、同一个函数指定多个mock规范

    3.3.4、入参约束之对象内容监控(spy)

    3.3.5、入参约束之定制化检查(check)

    3.3.6、指针设置输出参数outBoundP

    3.3.7、mock规则匹配失败

    3.3.8、mock调用次序(id、before、after)

    3.3.9、mock实际调用次数

    3.3.10、清空Mock规则GlobalMockObject::verify()


    1、Mock介绍

    1.1、概述        

            mock工具的作用是指定函数的行为(模拟函数的行为)。可以对入参进行校验,对出参进行设定,还可以指定函数的返回值。例如,当我们在写代码时,涉及到模块间进行交互,双方分别提供了函数接口或消息互相发送时,使用MockCpp进行模拟函数的调用或消息的转发。再如,当我们进行FT测试校验时,涉及到模块间的交互时我们也可以使用MockCpp进行测试用例的补充与校验。

    1.2、相关概念

            ①mock规范:每个MOCKER(function)开始,跟一系列的.stubs、.with、.will等的内容的整体,称为一个mock规范。
            ②核心关键字:指stubs/defaults/expects/before/with/after/will/then/id等这些直接跟在‘ . ’ 点后面的关键字。
            ③扩展关键字:指once()/eq()/check()/returnValue()/repeat()等这些作为核心关键字参数的关键字。

    1.3、特点

            ① 开源。
            ② mockcpp支持C函数的mock和虚接口的mock。
            ③ VC下,mockcpp支持cdecl和stdcall调用约定的函数。(socket/bind/ftp等函数就是stdcall调用约定的)
            ④ mockcpp的语法清晰、简单,容易理解(参见3.1小节两个sample)。
            ⑤ mockcpp是强类型检查的,强类型检查也是C/C++的一个优势,比如eq(3),如果调用函数时用的参数是UL,那么就应该用eq((UL)3),对于函数返回值也是一样,声明的返回值类型应该跟mock中定义的一致。mock中支持类型检查,可能会发现更多代码BUG的。C++强类型检查,也是为了提高程序安全性,有些问题通过类型检查在编译期可以发现的,就不需要在运行时再痛苦的定位了。C/C++的强类型检查是优势,我们不用把它抛弃了。
            ⑥ mockcpp的错误信息提示非常友好,包含完整的mock规范定义和实际运行情况(参见下面的样例)。

    Unexpected invocation: the invocation cannot be found in allowed invoking list.//没有匹配的mock规则
    Invoked: add((int)0x1/1, (int)0x2/2)//实际调用add(x,y)传入的参数为1,2
    Allowed:
    method(add)
      .stubs()
      .invoked(0)//第一次调用
      .with(eq((int)0xa/10), eq((int)0x14/20))//规则指定入参必须为(10,20),所以匹配失败
      .will(returnValue((int)0xc8/200));

    2、对C使用Mock

    2.1、安装

            需要按照当前我们使用的gtest模式进行编译。在mockcpp/build子目录下执行cmake,其中$xunit_home是gtest头文件所在目录(此时gtest.h路径为$xunit_home/include/gtest/gtest.h)。
            cmake -DMOCKCPP_XUNIT=gtest -DMOCKCPP_XUNIT_HOME=$xunit_home ../
            make
            make install
           安装后的头文件和库在/usr/local下面,可以不用额外指定头文件搜索路径和库文件搜索路径。后续如果觉得好用,也可以把头文件和库提取出来,指定到项目目录树中。

    2.2、配置

           测试工程,使用mock接口的文件需要包含:#include <mockcpp/mokc.h>,同时链接mockcpp的库:-lmockcpp

    2.3、优缺点

            缺点:被mock的函数,是需要事先存在的,mockcpp并不能完成自动打桩的工作。mockcpp做的,是改变或检查函数的行为,使配合我们的测试工作,虽然mockcpp的实现要复杂得多,但是其用途和原理,和《嵌入式c语言的TDD开发》里的实例是一样的。
            优点:省去打桩的繁琐步骤是mock

    3、Mock规范使用

    3.1、sample代码

            首先,请看两段mockcpp的使用规范示例代码,其中带“/”或者“|”的表示在该位置可能有多种选择;带中括号的表示是可选的。一段简单的mockcpp使用sample代码:(带有完整核心关键字

    TEST(mockcpp simple sample)
    {
        MOCKER(function) / MOCK_METHOD(mocker, method)
            .stubs() / defaults() / expects(once())
            [.before("some-mocker-id")]
            [.with(eq(3))]
            [.after("some-mocker-id")]
            .will(returnValue(1)) / .will(repeat(1, 20))
            [.then(returnValue(2))]
            [.id("some-mocker-id")]
    }

             下面是一段比较详细的mockcpp使用sample代码:(带有完整扩展关键字)

    TEST(mockcpp detail sample)
    {
        MOCKER(function) / MOCK_METHOD(mocker, method)
            .stubs() / defaults() / expects(never() | once() | exactly(3) | atLeast(3) | atMost(3) )
            [.before("some-mocker-id")]
            [.with( any() | eq(3) | neq(3) | gt(3) | lt(3) | spy(var_out) | check(check_func)
                    | outBound(var_out) | outBoundP(var_out_addr, var_size) | mirror(var_in_addr, var_size)
                    | smirror(string) | contains(string) | startWith(string) | endWith(string) )]
            [.after("some-mocker-id")]
            .will( returnValue(1) | repeat(1, 20) | returnObjectList(r1, r2)
                    | invoke(func_stub) | ignoreReturnValue()
                    | increase(from, to) | increase(from) | throws(exception) | die(3))
            [.then(returnValue(2))]
            [.id("some-mocker-id")]
    }

    3.2、核心关键字解析

            mockcpp当前的实现支持七种类型的约束/行为:(调用顺序必须按照以下序列进行)
            ① 调用次数约束—— expects()/stubs()
            ② 调用者选择器—— caller()
            ③ 先行调用约束—— before()
            ④ 调用参数约束—— with()
            ⑤ 后行调用约束—— after()
            ⑥ 函数调用行为—— will()/then()
            ⑦ 标识符指定—— id()           

    3.2.1、调用次数约束(expects()/stubs())

            紧跟着MOCKER/MOCK_METHOD之后的是stubs、或者defaults、或者expects,三个必须有一个。(这是与AMOCK不同的地方,在这个层次上确定这三个关键字必须有一个,可以让mock语法更清晰)
            ①defaults 表示定义一个默认的mock规范,但它优先级很低;如果后面有stubs或者expects重新指定函数行为,就会按照新指定的来运行。(一般用在setup中)
            ②stubs 表示指定函数的行为,不校验次数。
            ③expects 与stubs的区别就是校验次数。格式:(.expects(once()) / .expects(never()) / .expects(exactly(123)))
                一次:once()
                准确的次数:exactly(n)
                至少:atLeast(n)
                      atLeastOnce()
                至多:atMost(n)
                      atMostOnce()
                不调用:never() 
                注意:次数校验expects()需和GlobalMockObject::verify()一起使用才能校验生效,GlobalMockObject::verify()放在主函 数最后面)

    3.2.2、调用者选择器(caller

           这个功能当前主要用于C语言的单元测试/集成测试。当一个函数会被一个流程的多个函数调用时,当其它的选择器很难以进行描述时,可以使用调用者选择器来缩小定位范围。调用者选择器通过caller(function)来指定。其中,function是一个字符串,应该等于调用函数的名字。

    3.2.3、函数参数约束(with

        ①入参数约束:
            相等:eq(value)
            不等:neq(value)
            大于: gt(value)
            小于: lt(vlaue)
            内存匹配 :mirror(var_in_addr, var_size)用来约束内存内容的严格相等性。如果用来约束对象内容,则可以忽略size参数
            对象内容监控:spy(address)读取监控对象值
            字符串匹配:smirror(str) 约束字符串的相等性
            startWith(str):入参以str开始
            endWith(str) :入参以str结尾
            占位符: any()
            定制化检查:checkWith(CheckNum(num)) 内部必须是结构体、类
        ② 输出参数约束
            通过引用设置输出参数:outBound(reference, 输入参数约束/sizeof(reference))
            通过指针设置输出参数:outBoundP(pointer, 输入参数约束/sizeof(pointer))    

    3.2.4、调用次序(before、id、after)

            ①标识符指定(id):当一个调用描述用到before()/after()等调用顺序约束时,需要给被参照的调用描述一个标识符。标识符通过id(identity)指定。其中identity是一个字符串。在一个对象范围内,identity必须唯一,否则mock++则可能会引用到错误的调用描述。
            ②before(id):之前
            ③after(id):之后
            注意:(before、id、after不能和stubs一起使用)

    3.2.5、函数调用行为(will、then)

            ①will指定返回值/②then指定下一次返回值
            返回一个值:returnValue(value)
            重复返回一个值:repeat(value, times)
            步增一个值:increase(from, to)/increase(from)
            返回一系列的值:returnObjectList(o1, o2,…);依次返回o1, o2,…;超过返回列表数据个数,报错。返回个数有限。
            抛出异常:throws(exception(“Exception!”))
            异常退出:die表示程序退出,并且返回指定的值。用于模拟一个函数调用崩溃的情况。
            忽略返回值:ignoreReturnValue(),如果函数定义的返回值类型不是void ,则一定要指定函数调用行为;即使不关心返回值,也要通过ignoreReturnValue()来指定。
            转调一个stubFunction函数:invoke(stubFunction)
            注意:带有返回值的函数,MOCKER后面必须有will,否则mockcpp认为无返回值,校验时会发现返回类型不匹配。

    接口:char * sysMemRosBottom (void){}
    mock规则:MOCKER(sysMemRosBottom).expects(once()).will(returnValue(NULL));
    
    错误:
    .../mockcpp/ChainableMockMethod.h:69: Failure
    Returned type does NOT match the method declaration
    Required : char*
    Returned : long, which is from
    method(sysMemRosBottom)
         .expects(once())
         .invoked(1)
         .will(returnValue((long)0/0));
    unknown file: Failure
    C++ exception with description "failed due to mockcpp exception" thrown in the test body.
    

    3.3、难点代码演练

    3.3.1、函数调用行为指定返回值       

           will指定函数的返回值:.will(returnValue(expect_var));如果要多次重复的相同值,则用.will(repeat(expect_var, repeat_cnt)),若果超过返回次数,后面没有接then,则报错需要指定下一次返回值则用.then(returnValue(expect_var));具体见如下代码

        int i=0,repeat_cnt = 20,expect_var = 100;
        //入参1,2:前repeat_cnt次,返回值为expect_var;第repeat_cnt+1次,返回值expect_var+1
        MOCKER(add).defaults().with(eq(1), eq(2)).will(repeat(expect_var, repeat_cnt)).then(returnValue(expect_var+1));
        //入参3,4:第一次返回值为expect_var;第2,3,4....次,返回值expect_var+1
        MOCKER(add).defaults().with(eq(3), eq(4)).will(returnValue(expect_var)).then(returnValue(expect_var+1));
    
    
        for(i = 0; i < repeat_cnt; i++)
        {
          EXPECT_EQ(expect_var, add(1,2));  
        }
        EXPECT_EQ(expect_var + 1, add(1,2));
        
        EXPECT_EQ(expect_var, add(3,4));
        EXPECT_EQ(expect_var+1, add(3,4));//之后的返回值均为expect_var+1
        EXPECT_EQ(expect_var+1, add(3,4));//第3次
        GlobalMockObject::verify();

    3.3.2、入参数约束之内存监控(参数类型也参与检查)

           当函数的入参为一个指针时,此时eq(var)则无法校验指针指向的地址的内容,改用mirror(var_in_addr, var_size),用于监控内存地址中的内容,类似C标准库中的int memcmp(const void *s1, const void *s2, size_t n),参数类型必须一致(显示强转),否则匹配失败,;具体代码如下 :

    int testMethodInParaPointer(char* str)
    {
        return 0;
    }
    
    int callTestMethodInParaPointer()
    {
    
        char temp[10]={"hello"};
        return testMethodInParaPointer(temp);
    }
    
    TEST(RosMemBuf_adjust_capacity_T, GIVEN_ANY_WHEN_CALL_testMethodInParaPointer_THEN_OK)
    {
     
        int expect_var = 100;
        /*eq(var),全局变量和局部变量不同无法匹配,显示:the invocation cannot be found in allowed invoking list*/
        //MOCKER(testMethodInParaPointer).defaults().with(eq((char*)"hello")).will(returnValue(expect_var));
        /*字符串"hello"需要加(char *),否则解析成(char const *)依然无法匹配*/
        MOCKER(testMethodInParaPointer).defaults().with(mirror((char *)"hello",strlen("hello"))).will(returnValue(expect_var));
        EXPECT_EQ(expect_var,callTestMethodInParaPointer());
        GlobalMockObject::verify();    
    }

    3.3.3、同一个函数指定多个mock规范

           当对同一个函数指定多个mock规范,那么这些mock规范一般是应该在输入方面有差异的,否则没必要指定多个。而且,在输入方面无差异的两个mock规范,让mockcpp内部无法判断是否满足规范约束。 比如,测试函数 void testMtehodParaInOut(int input,int *p_output),前面一个是入参,后面一个是出参,希望input为10时,输出*p_output为100,input为11时,输出*p_output为111,那么应该这样写:

        int in_var = 10,expect_var = 100,real_var1 = 0;
        
        MOCKER(testMtehodParaInOut).expects(once()).with(eq(in_var),outBoundP(&expect_var,sizeof(expect_var))); 
        testMtehodParaInOut(in_var,&real_var1);
        EXPECT_EQ(expect_var, real_var1);
    
        expect_var = 111;
        MOCKER(testMtehodParaInOut).expects(once()).with(eq(in_var+1),outBoundP(&expect_var,sizeof(expect_var))); 
        testMtehodParaInOut(in_var+1,&real_var1);
        EXPECT_EQ(expect_var, real_var1);
    
        GlobalMockObject::verify();

            假设你把eq(in_var)、eq(in_var+1)写为any(),那么mockcpp会判断你的两个调用testMtehodParaInOut(in_var,&real_var1);和testMtehodParaInOut(in_var,&real_var1);都符合第一个mock规范,从而报告与你定义的次数1不匹配。或者仅有一条mock规范(此时outBoundP相同),但是实际调用两次保同样的错,信息如下:

    .../ChainableMockMethod.h:69: Failure
    Invocation is expected only once(), but you are trying to invoke more than that
    method(testMtehodParaInOut)
         .expects(once())
         .invoked(1)//实际调用次数
         .with(any(), outBoundP((int*)0x00ada680));
    unknown file: Failure
    C++ exception with description "failed due to mockcpp exception" thrown in the test body.

    3.3.4、入参约束之对象内容监控(spy)

        spy的作用是监视,下面例子,就是监视test在调用add时,传入的值是多少。有些时候,测试用例需要这样的值,这种方式是很有效的。

        int var_out1, var_out2,expect_var = 100;
        MOCKER(add).defaults().with(spy(var_out1),spy(var_out2)).will(returnValue(expect_var));
        EXPECT_EQ(expect_var, add(3,4));
        EXPECT_EQ(var_out1, 3);//监控到第一个参数为3
        EXPECT_EQ(var_out2, 4);//监控到第二个参数为4

    3.3.5、入参约束之定制化检查(check)

          约束关键字中,有很多都是对入参进行检查的,比如eq、neq、lt、gt等等,但它们都只实现了非常简单的检查。 如果用户想做一个定制化的检查,那么就可以用check,但是编译报错 error: 'check' was not declared in this scope,原因:mockcpp在2.4版本后没有了check关键字,代替的是checkWith注意大小写,以为还有一个CheckWith。 举一个例子:假设用户想检查入参p指向的结构的字段b是否大于10,那么可以如下这样写:

    
    typedef struct data_in{
        int a;
        int b;
    }def_data_in;
    
    //定义在C++中,不要定义在C中,编译无法识别bool(小写),
    bool checkTestMockcppCheckEx1(def_data_in *pdata){
        if(pdata->a >10)
            return true;
        else
            return false;
    }
    //实现一个检查函数,入参类型跟要检查的入参相同,返回值为bool,返回true表示检查通过。
    bool checkTestMockcppCheckEx2(def_data_in *pdata){
        if(pdata->b == 10)
            return true;
        else
            return false;
    }
    
    int testMockcppCheck(def_data_in *pdata1, def_data_in *pdata2 ){
    
        return 0;
    }
    
    TEST(xxxxx, DoubleParaTest)
    {
        def_data_in g_data1={11,9},g_data2={11,10};
        int expect_var = 100;
        MOCKER(testMockcppCheck).stubs()
        .with(checkWith(checkTestMockcppCheckEx1),checkWith(checkTestMockcppCheckEx2))//将校验参数填写到原来的参数限定位置
        .will(returnValue(expect_var));
    
        EXPECT_EQ(expect_var, testMockcppCheck(&g_data1,&g_data2));   
    }
    
    
    int func(int in, def_data_in *p)
    {
        return 0;//mockcpp对类型进行检查,对于有返回值类型的接口,没有return操作,打桩后会出现Segmentation fault
    }
    
    TEST(xxx, SingleParaTest)
    {
        def_data_in var={1,10};
        int expect_var = 100;
        MOCKER(func)
            .stubs()
            .with(any(),checkWith(checkTestMockcppCheckEx2))// error: 'check' was not declared in this scope,mockcpp在2.4版本后没有了check关键字,注意大小写,以为还有一个CheckWith
            .will(returnValue(expect_var));
        EXPECT_EQ(expect_var, func(1, &var));
    }
    

    3.3.6、指针设置输出参数outBoundP

             实际打桩过程中,经常需要指定接口出参的数值,当出参的类型为指针时则需要设置指针指向地址的内容,此时需要通过outBoundP来指定,具体代码如下:

    void testMtehodParaInOut(int input,int *p_output)
    {
        *p_output = input +1;
    }
    ...
    int in_var = 10,expect_var = 12,real_var1 = 0; 
    MOCKER(testMtehodParaInOut).stubs().with(eq(in_var),outBoundP(&expect_var,sizeof(expect_var))); //指定出参的指针内容为12
    testMtehodParaInOut(in_var,&real_var1);//调用后,real_var1的指针内容为12
    EXPECT_EQ(expect_var, real_var1);

    3.3.7、mock规则匹配失败

            如果要对某个函数(比如add)指定多个调用不同的行为(多个mock规范),比如调用入参为1,2时,返回30;调用入参为3、4时,返回300。那么可以这样写:

        MOCKER(add).stubs().with(eq(1), eq(2)).will(returnValue(30));
        MOCKER(add).stubs().with(eq(3), eq(4)).will(returnValue(300));
        EXPECT_EQ(300, add(1,4));//没有匹配的mock规则,运行报错
        GlobalMockObject::verify();

    只有参数满足条件桩函数才会生效,如果调用接口(add)没有匹配到mock规则,则报错(意外调用:在允许的调用列表中找不到调用),具体如下:

    ....../mockcpp/ChainableMockMethod.h:69: Failure

    =====================================
    Unexpected invocation: the invocation cannot be found in allowed invoking list.
    Invoked: add((int)0x1/1, (int)0x4/4)
    Allowed:
    method(add)
         .stubs()
         .invoked(0)
         .with(eq((int)0x1/1), eq((int)0x2/2))
         .will(returnValue((int)0x1e/30));

    method(add)
         .stubs()
         .invoked(0)
         .with(eq((int)0x3/3), eq((int)0x4/4))
         .will(returnValue((int)0x12c/300));

    =====================================

    unknown file: Failure
    C++ exception with description "failed due to mockcpp exception" thrown in the test body.

    结论:只要打桩了,那么就不会运行原函数,都是与mock规范匹配,运行桩,否则运行报错

    3.3.8、mock调用次序(id、before、after)

    如果上面的3.3.7小结的例子,希望对调用顺序做严格要求,必须第一次调用参数是1、2,第二次是3、4,那么可以这样写:

    MOCKER(add)
      .stubs()
      .with(eq(1), eq(2))
      .will(returnValue(30))
      .id("first");
    
    MOCKER(add)
      .stubs()
      .with(eq(3), eq(4))
      .after("first")
      .will(returnValue(700));

            自定义规则:假设有时候需要对同一个函数指定多个mock规范,并且它们是有规律的,那么可以借助循环来简化代码。 假设要mock的函数是void function(int in),希望它依次以0、1、2...10为入参被调用,每次都调用一次,那么可以像这样写:

    MOCKER(function)
      .expects(once())
      .with(eq(0))
      .id("0");
    
    for (int i = 1; i <= 10; i++)
    {
      MOCKER(function)
        .expects(once())
        .with(eq(i))
        .after(string(i - 1))
        .id(string(i));   
    }

    //没有实验,编译失败,版本(2.6)无法编译mock规则的id、after、before等着字段,显示:error: 'struct mockcpp::StubBuilder<mockcpp::MoreStubBuilder<mockcpp::DummyBuilder> >' has no member named 'after'。查阅对应的ChainingMockHelper.h,发现确实没有实现。需要更新版本

    3.3.9、mock实际调用次数

            在实际打桩过程我们可以通过expects(exactly(x))指定其精确运行x次,超过则报错,代码如下

        MOCKER(add).expects(exactly(2)).with(eq(100), eq(200)).will(returnValue(30));
        EXPECT_EQ(30, add(100,200));
        EXPECT_EQ(30, add(100,200));
        EXPECT_EQ(30, add(100,200));
        GlobalMockObject::verify();

    提示错误信息:

    .../ChainableMockObjectBase.cpp:85: Failure
    Expected invoking exactly 2 times, but it's actually invoked 3 times.
    method(add)
         .expects(exactly(2))
         .invoked(3)//实际第3次调用
         .with(eq((int)0x64/100), eq((int)0xc8/200))
         .will(returnValue((int)0x1e/30));
    unknown file: Failure
    C++ exception with description "failed due to mockcpp exception" thrown in the test body.

    3.3.10、清空Mock规则GlobalMockObject::verify()

            使用mockcpp时,校验是否按照mock规范进行调用的,应该用:GlobalMockObject::verify();verify之后,会自动执行reset。通常在进行Unit测试时,需要避免用例之间的联系,不能上一个用例的桩函数在本例生效,需要在用例的结尾处执行该语句。

    展开全文
  • 并行计算:MPI总结

    千次阅读 多人点赞 2020-08-03 22:52:07
    共有上百个函数调用接口,提供与C和Fortran语言的绑定 MPI是一种标准或规范的代表,而不是特指某一个对它的具体实现 MPI是一种消息传递编程模型,并成为这种编程模型的代表和事实上的标准 2.MPI的特点 MPI有以下的...
  • Java基础篇一

    千次阅读 2018-03-07 22:42:01
    个人感觉java语言的规范性要高于c,学起来不是很吃力。这可能归功于我先学的C吧。java语言特点:1.跨平台这是本人觉得的最大的特点;2.面向对象简单理解就是把一些属性和方法放在一个类里面,然后通过这个类的对象来...
  • webservice简介&CXF入门

    2016-08-16 14:39:30
    WebService 它是一种跨编程语言和跨操作系统平台的远程调用技术即跨平台远程调用技术.   面向服务架构 规范及三要素   1) SOAP协议:webservice的传输协议,即简单对象访问协议....特点:跨平台 跨语言 W3C
  • 易嵌入,可以方便的与c/c++编写的游戏逻辑互相调用 简单,不涉及任何复杂的编程概念,麻雀虽小五脏俱全 轻量,库体积很小,只有几百字节 易学习,游戏策划也能使用 高性能,对比c/c++其带来的性能损失可以忽略不计 ...
  • python (1) 变量

    2019-09-24 18:08:32
    python的特点:python被称为胶水语言,可以很好的跟其他开发语言,比如 c c++ shell 等嵌套调用。一。 python变量 (1)python变量的规范: 1. python 变量名只能是 数字 字母 下滑线组成。 2. 变量不能以数字开头,...
  • 内核模块嵌入式

    2018-04-30 16:31:23
    linux内核模块编程特点:1&gt;不能使用C库和C标准头文件2&gt;必须使用GNU规范3.没有内存保护机制4.不能处理浮点运算5.注意同步和并发的问题6.注意可移植性一,模块函数(1)加载函数://将模块函数用关键字...
  • <p>Serverless 的主要特点有: <ul><li>事件驱动</li><li>函数在 FaaS 平台中࿰c;需要通过一系列的事件来驱动函数执行。</li><li>无状态</li><li>因为每次函数执行࿰c;可能使用的都是不同的容器࿰...
  • 易语言窗口组件自适应,可以自动依据窗口分辨率调整,易语言窗口自适应改变大小模块源码例程程序调用API函数,根据窗口消息值实现窗口组件的自适应大小。 ' 5>功能特点: ' A:简单,两个命令直接可以自定义改变组件...
  • Servlet和Http:

    2020-11-09 21:11:03
    **作用:**规范了浏览器和服务器的数据交互 特点: 1.简单快速 2.灵活 3.无连接 4.无状态 5.支持b/s架构,c/s架构 http请求报文格式: 请求行 请求头 空行 请求体 http响应报文格式: 状态行 响应头 空行 响应体 ...
  • 主要特点: 1、多种语言和协议编写客户端。语言:Java,C,C++,C#,Ruby,Perl,Python,PHP。应用协议:OpenWire,Stomp REST,WS Notification,XMPP,AMQP 2、完全支持JMS1.1和J2EE 1.4规范 (持久化,XA消息,...
  • 程序设计语言的基本成分(数据、运算、控制和传输、过程(函数)调用) 面向对象程序设计 各类程序设计语言的主要特点和适用情况 C 语言以及C++(或Java)语言程序设计基础知识 程序语言概述 定义:程序语言是表达...
  • JavaScript 语言的一大特点就是单线程࿰c;也就是说࿰c;同一个时间只能做一件事。根据 <a href="https://www.w3.org/TR/html5/webappapis.html#event-loops">HTML 规范</a>: <p>To coordinate events...
  • C++标准库简介

    2020-10-14 22:06:01
    C++编译器厂商在实现C++标准库过程中必须依赖其不同操作系统所提供的系统调用接口,因此每个平台都有其自己的C++标准库实现。 C++标准库的特点如下: A、C++标准库不是C++语言标准的一部分,由类库和函数库组成。 B...
  • 精通matlab7.0混合编程.

    2015-06-30 09:21:20
    2.6 m文件编程规范 2.7 m文件评述器 2.8 提高m文件执行效率的技巧 2.8.1 矢量化操作 2.8.2 给数组预定义维 2.8.3 下标或者索引操作 2.8.4 尽量多使用函数文件而少使用非脚本文件 2.8.5 将循环体中的内容转换为c-mex ...
  • 5.易用的标签格式总结之前版本结合用户使用习惯设计出一套简单易用的标签规范,你只需花少量时间就能熟练掌握ShyPost企业网站管理系统前台页面ShyPost企业网站管理系统后台简介后台地址:http://域名/admin后台帐号...
  • 8.3寄存器使用规范(register conventions) 8.4函数结构和调用约定 8.5 C/C++与汇编语言的接口 8.6中断处理 8.7运行时支持的算术程序(mn.time—support£Lrithmetic routines) 8.8系统初始化 第9章 运行时支持函数 ...
  • 总结之前版本结合用户使用习惯设计出一套简单易用的标签规范,你只需花少量时间就能熟练掌握 ShyPost企业网站管理系统前台页面   ShyPost企业网站管理系统后台简介 后台地址:http://域名/admin 后台帐号...
  • 并符合它的安全规范c;就可以申请加入 HSTS 列表࿰c;之后用户不加 HTTPS 协议再去访问你的网站࿰c;浏览器都会定向到 HTTPS。无论匹配到没有࿰c;都要开始 DNS 查询工作了࿰c;提取出的主机名类似...
  • 嵌入式课件

    2012-04-06 16:48:49
    3.1.2 S3C2410A的技术特点 3.2 S3C2410A存储器控制器 3.2.1 S3C2410A的存储器控制器特性 3.2.1 S3C2410A的存储器映射 3.3 时钟和电源管理 3.4 S3C2410A的I/O口 3.4.1 S3C2410A的I/O口配置 3.4.2 S3C2410A的I/O口...
  • ShyPost企业管理系统符合W3C标准,兼容IE各版本,FireFox,Chrome,Opera等常用浏览器2.数十种商业模板精心设计开发 按照各个行业特点、精心开发数十种模板,网站整体色调设计突出,搭配合理,适合各行业使用。3.丰富的...
  • 英特尔面试专项准备

    2020-12-09 13:46:46
    <p>vivt和vipt cache的特点c;优缺点 </li><li> 什么场合下需要冲洗tlb࿰c;什么场合下需要冲洗cache </li><li> 关于memory barrier的问题࿰c;内核中的各种屏障(这个我答得不好࿰c;因为我...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 154
精华内容 61
关键字:

c调用规范特点