简体   繁体   English

如何区分c中函数的INPUT,OUTPUT和INPUT-OUTPUT参数?

[英]How to distinguish INPUT, OUTPUT and INPUT-OUTPUT parameter of function in c?

reading "Software Detailed Description" Documents of some software modules, I see in the description of each function: 阅读“软件详细说明”一些软件模块的文档,我在每个函数的描述中看到:

  1. INPUT PARAMETER: ..... 输入参数:.....
  2. OUTPUT PARAMETER: ..... 输出参数:.....
  3. INPUT-OUTPUT PARAMETER: ..... 输入输出参数:.....

For Example, we have the following: 例如,我们有以下内容:

typedef struct
{
    u16_t elementA;
    u16_t elementB;
    u8_t  elementC;

} myStruct;


void somefunction(myStruct *pToMyStruct)
{

   pToMyStruct->elementA  = 1;
   pToMyStruct->elementB  = 5;
   pToMyStruct->elementC  = 7;
}

In the Software Description Document, following is described: 在软件描述文档中,描述如下:

  1. INPUT PARAMETER: none INPUT PARAMETER:无
  2. OUTPUT PARAMETER: none 输出参数:无
  3. INPUT-OUTPUT PARAMETER: pointer to structure (pToMyStruct) INPUT-OUTPUT PARAMETER:指向结构的指针(pToMyStruct)

I'm not so deep with the c programming technique, but why is in this case the "pToMyStruct" an INPUT-OUTPUT Parameter? 我不太熟悉c编程技术,但为什么在这种情况下“pToMyStruct”是一个INPUT-OUTPUT参数? Why is it not only an INPUT parameter? 为什么它不仅仅是一个INPUT参数? How can I, as a not experienced programmer but understand the code, easily identify these 3 types of parameter in an function? 作为一个没有经验的程序员但是理解代码,我怎样才能在函数中轻松识别这3种类型的参数? INPUT parameters for example are only modified within it's own function, or? 例如,INPUT参数只能在它自己的功能中修改,或者?

Will be thankful! 会感恩的!

// INPUT-OUTPUT PARAMETER: pointer to structure (pToMyStruct)
void somefunction(myStruct *pToMyStruct) {
   pToMyStruct->elementA  = 1;
   ...
}

"Why is it not only an INPUT parameter?" “为什么它不仅仅是一个INPUT参数?” - technically you are correct: it is only an input parameter. - 从技术上讲,你是对的:它只是一个输入参数。 The only output of a function is its return value and its affect on the global environment (global variables, printf() , etc.) 函数的唯一输出是它的返回值及其对全局环境的影响(全局变量, printf()等)

The "Software Detailed Description" (author) is stuck with "C-does-not-have-pass-by-reference", so wants to create a new "point-of-view". “软件详细描述”(作者)坚持“C-does-not-pass-by-reference”,因此想要创建一个新的“观点”。 As in: let us call input pointer parameters as a pseudo pass-by-reference which is: input, output or IO. 如下所示:让我们将输入指针参数调用为伪传递引用,即:输入,输出或IO。 Author wants you to document to that model. 作者希望您记录该模型。

// the return value is an output
int foo()

// x is an input parameter
void foo(int x)

// what x points to is an input parameter, be it an `int` or array of `int` or NULL
void foo(const int *x)

// what x points to is an output parameter 
void foo(int *x) {
  // *x not read before being set

// what x points to is an I/O parameter
void foo(int *x) {
  // *x read before being set

So myStruct *pToMyStruct is either an output or IO parameter. 所以myStruct *pToMyStruct是输出或IO参数。 If one does not probe into the body of the function, safer to classify it as IO as the function signature does allows reading and writing to *pToMyStruct . 如果没有探测到函数的主体,则将其归类为IO更安全,因为函数签名允许读取和写入*pToMyStruct Given the trivial example function, it is an output parameter. 给定简单的示例函数,它是一个输出参数。

That is because a pointer to the structure is being passed, and it is not const -qualified. 这是因为正在传递一个指向结构的指针,并且它不是const -qualified。 Here are the rules 这是规则

  1. input: A normal argument, that the function does not modify. input:一个普通的参数,该函数不会修改。 This can be a const pointer. 这可以是一个const指针。
  2. output: A pointer to a variable that the function will modify when it returns. output:指向函数返回时将修改的变量的指针。 Before you call the function, the variable is uninitialized. 在调用函数之前,变量未初始化。
  3. input-output: A combination of the above two. 输入输出:以上两者的组合。 You pass a pointer, that already points to valid data, and when the function returns, the data will be changed in some way. 传递已指向有效数据的指针,当函数返回时,数据将以某种方式更改。 The swap function is a good example of this. swap功能就是一个很好的例子。

As said in the description, pToMyStruct is a pointer, which means the parameter is actually a memory address of the structure's data. 如在描述中所述,pToMyStruct是指针,这意味着该参数实际上是结构数据的存储器地址。 Thus, the data transmitted can be used but also modified, that's why it's an INPUT-OUTPUT parameter. 因此,传输的数据可以使用但也可以修改,这就是它是INPUT-OUTPUT参数的原因。

An INPUT parameter would be a parameter that could not be modified in the function, like a normal variable. INPUT参数是一个无法在函数中修改的参数,就像普通变量一样。

A simple OUTPUT parameter is, basically, the value returned by the function. 简单的OUTPUT参数基本上是函数返回的值。

The problem is that functions often need to have several OUTPUT variables. 问题是函数通常需要有几个OUTPUT变量。 To do that, one must use pointers given as parameter. 要做到这一点,必须使用作为参数给出的指针。 So, unless you have a really good understanding of the code, you cannot deduct whether a pointer in the parameters is just INPUT, OUTPUT or INPUT-OUTPUT. 因此,除非您非常了解代码,否则无法推断参数中的指针是仅INPUT,OUTPUT还是INPUT-OUTPUT。 The only way to know it for sure is to look into the documentation as you did for your example. 了解它的唯一方法就是像你的例子那样查看文档。

input - you are only passing a value/argument to the function. 输入 - 您只是将值/参数传递给函数。 output - The function will update the value of the variable passed(This is possible only with a pointer in C and pointer or reference in C++) intput and output - The same variable can be used to pass value and also to get updated values and the variable type is same as o/p. output - 该函数将更新传递的变量的值(这只能用C中的指针和C ++中的指针或引用)intput和output - 相同的变量可用于传递值,也可用于获取更新的值和变量类型与o / p相同。

In your code, a structure variable is passed and you are getting an updated structure in your function where you call somefunction(). 在您的代码中,传递了一个结构变量,您将在函数中获得一个更新的结构,您可以在其中调用somefunction()。 Hence it is input and output variable. 因此它是输入和输出变量。

Parameters in C are always passed by copy. C中的参数始终按副本传递。 When you use a pointer, it does a copy of the pointer which "points" to the same object. 当您使用指针时,它会执行指向同一对象的指针的副本。 Then if you modify the content of the "copy of the pointer" it will modify the "real object". 然后,如果您修改“指针副本”的内容,它将修改“真实对象”。

Consequently, it is an input/output parameter (as it is possible to modify it). 因此,它是输入/输出参数(因为可以修改它)。

If you had instead 如果你有的话

void somefunction(myStruct theStruct)

then it is the structure itself which will be copied; 那么结构本身就会被复制; then it will be an input parameter. 那么它将是一个输入参数。

Contrary to some other languages, C (as well as C++) doesn't really have a keyword to indicate, what parameter is what, but as a rule of thumb: 与其他一些语言相反,C(以及C ++)并没有真正的关键字来表示,什么参数是什么,但作为经验法则:

  • input parameters are usually pointer to const (or passed by value) 输入参数通常是指向const指针(或通过值传递)
  • you should avoid pure output parameters if possible and use the return value instead (thats what they are there for). 如果可能的话,你应该避免使用纯输出参数,而是使用返回值(这就是它们的用途)。
  • So unless documentation states otherwise or the function name makes it obvious, I'd assume that a pointer to non-const parameter represent input-output-parameter. 因此,除非文档另有说明或函数名称使其显而易见,否则我假设指向非const参数的指针表示input-output-parameter。

Edit: 编辑:
I should mention that the second (and consequently the third) point might be somewhat controversial as there are a lot of APIs that use pure output parameters - some for good reason (eg because they use the return value to indicate failure or success), some because they date back to times, when compilers where a lot dumber and this was actually an inportant performance optimization. 我应该提到第二点(以及第三点)可能有点争议,因为有很多API使用纯输出参数 - 有些是有充分理由的(例如因为它们使用返回值来表示失败或成功),有些因为它们可以追溯到时代,当编译器中有很多笨重的时候,这实际上是一个重要的性能优化。

but why is in this case the "pToMyStruct" an INPUT-OUTPUT Parameter? 但为什么在这种情况下“pToMyStruct”是一个INPUT-OUTPUT参数? Why is it not only an INPUT parameter? 为什么它不仅仅是一个INPUT参数? How can I, as a not experienced programmer but understand the code, easily identify these 3 types of parameter in an function? 作为一个没有经验的程序员但是理解代码,我怎样才能在函数中轻松识别这3种类型的参数? INPUT parameters for example are only modified within it's own function, 例如,INPUT参数只能在它自己的函数中修改,

I like this question. 我喜欢这个问题。 Perhaps it is too broad to answer in just a few ideas, but here are some to get started with: 也许只是在一些想法中回答太广泛,但这里有一些开始:

  • Idea 1 - A formal parameter that can not be modified by the function / method, can only be input to the function or method. 想法1 - 函数/方法无法修改的形式参数只能输入到函数或方法中。

Thus "const T formalParam" is clearly an input ... the const is commanding the compiler to declare an error if the function attempts to modify the const T formalParam. 因此“const T formalParam”显然是一个输入......如果函数试图修改const T formalParam,则const命令编译器声明错误。

Likewise, "const T& formalParam" is an input. 同样,“const T&formalParam”是一个输入。 Some people use this parameter style to provide access to a large data item while avoiding the cost of copying. 有些人使用此参数样式来提供对大型数据项的访问,同时避免了复制的成本。


  • Idea 2 - A formal parameter which is a copy of the actual parameter, as in pass-by-value, can only be input to the function or method. 想法2 - 形式参数是实际参数的副本,如在按值传递时,只能输入到函数或方法。

Thus in "void foo(int t1);", the formal parameter t1 of type int is a copy of the actual parameter. 因此,在“void foo(int t1);”中,int类型的形式参数t1是实际参数的副本。 Changing t1 has no impact to the actual int. 更改t1对实际int没有影响。 This parameter behaves as if it is a local automatic variable pre-initialized with a copy of actual parameter's value. 此参数的行为就像是使用实际参数值的副本预先初始化的本地自动变量。

This also applies to passing class instances. 这也适用于传递类实例。 So that "void foo (T t2)", the formal parameter is a copy of some actual parameter. 所以“void foo(T t2)”,形式参数是一些实际参数的副本。 Again, modifying the copy has no impact to the original, so this can only be an input. 同样,修改副本对原始文件没有影响,因此这只能是输入。


  • Idea 3 - A formal parameter which is a reference (or pointer) to an existing actual parameter, as in pass-by-reference (and perhaps you might say pass-by-pointer) can be an output or a input/output parameter. 构思3 - 作为现有实际参数的引用(或指针)的形式参数,如在引用中传递(也许您可能会说通过指针)可以是输出或输入/输出参数。

So, in "void foo(int& t1, char* label)", both formal parameters can be either output or input/output. 因此,在“void foo(int&t1,char * label)”中,两个形式参数都可以是输出或输入/输出。 And you can only tell by looking at how the formal parameters are used in the method code. 而且您只能通过查看形式参数在方法代码中的使用方式来判断。


  • Idea 4 - Back when I first started with C++, I found studying the library functions informative. 想法4 - 当我第一次使用C ++时,我发现研究图书馆功能提供了丰富的信息。 Some examples: 一些例子:
 void* memcpy( void* dest, const void* src, size_t count ); // wrt memcpy: ^^output ^^^^^input ^input:pass-by-value // Note direction: to <---move <---from // I think this right-to-left idea might be a trend in C (research?) // return would seem useless, but is sometimes convenient value: copy of dest int memcmp ( const void* lhs, const void* rhs, size_t count ); // ^^^^^input ^^^^^input ^input:pass-by-value // return is result of comparison negative: int, 0, positive int int isalpha( int ch ); // ^input:pass-by-value // return is 0 (false) or non-zero (true) //from std::string::find size_type find( const basic_string& str, size_type pos = 0 ) const; // ^^^^^ input ^input: pass-by-value // return is npos or index where str found 

  • Idea 4 - Your next job may specify a sequence for input output and results in something called a "coding standard". 想法4 - 您的下一个工作可能会指定输入输出的序列,并产生称为“编码标准”的内容。

I have reviewed some of Google's coding standard, it is not hard to find. 我已经回顾了一些Google的编码标准,不难发现。 Books have been published on the subject. 已经出版了关于这一主题的书籍。 (research effort: Search for C++ coding standards, or perhaps C coding standards, and review.) (研究工作:搜索C ++编码标准,或者可能是C编码标准,并进行审查。)

  • Idea 5 - consult others 想法5 - 咨询其他人

I prefer that the return value of my methods to be a "status", and not the result of the method or function. 我更喜欢我的方法的返回值是“状态”,而不是方法或函数的结果。 (status means GOOD or FAIL) As a result, if my code outputs something, it then must have at least 1 output parameter, but methods often modify a data attribute of the class instance (instead of an output parameter). (状态表示GOOD或FAIL)结果,如果我的代码输出了某些东西,那么它必须至少有1个输出参数,但方法通常会修改类实例的数据属性(而不是输出参数)。 I generally arrange them as: 我通常将它们安排为:

 T foo ( <input parameters> , <output parameters> ); 

T can be any class which has a simple and quick evaluation. T可以是任何具有简单快速评估的类。 Lately, I have used std::string, and when the string.size() is 0, it means there were no errors during the function. 最近,我使用了std :: string,当string.size()为0时,表示函数期间没有错误。 When size is positive, the string contains an error message for reporting. 当size为正数时,该字符串包含用于报告的错误消息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM