Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Function without prototype called with non-compatible type

I read the Standard N1570 section 6.5.2.2 Function calls and was confused about the special meaning of the function type that includes prototype. Precisely 6.5.2.2(p6)

If the function is defined with a type that does not include a prototype, and the types of the arguments after promotion are not compatible with those of the parameters after promotion, the behavior is undefined, except for the following cases:

— one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;

— both types are pointers to qualified or unqualified versions of a character type or void.

6.5.2.2(p7) provides a rule of calling function with prototype:

If the expression that denotes the called function has a type that does include a prototype, the arguments are implicitly converted, as if by assignment, to the types of the corresponding parameters, taking the type of each parameter to be the unqualified version of its declared type.

Consider the following example:

struct test_arg{
    int a;
};

void test_no_prototype(const struct test_arg a){ }

void test_with_prototype(const struct test_arg a);

void test_with_prototype(const struct test_arg a){ }

int main(){
    struct test_arg test = {.a = 42};
    test_no_prototype(test);   //1 UB?
    test_with_prototype(test); //2 Fine?
}

I think that 1 is UB because test_no_prototype does not include prototype and test has non-qualified version of struct test_arg, but the argument has type const struct test_arg which is non-compatible with struct test_arg because of different qualification.

I think that 2 is fine because test_with_prototype includes prototype and the simple assignment constraints from 6.5.16.1(p1) allow assignment of to a variable of qualified struct type from non-qualified version of the same struct.

This seems strange and for now I cannot imagine any reason of why we treat functions with and without prototype differently. Probably I understood the rule incorrectly... If so could you explain what it means?

like image 357
Some Name Avatar asked Mar 29 '19 14:03

Some Name


People also ask

What is function without prototype?

It means you need to either define your function or else prototype it. In a header file you need to type in something like this… int funtion_name(int parameter_names); and then in a file you need to actually define the function… int function_name(int parameter_name)

When can a function prototype be omitted?

A function prototype can always be omitted when: A.A function is defined before it is first invoked.

What information a function prototype does not carry?

Function prototype: To declare a function, the prototype function is used. It does not include the function's core, only tells the compiler about the name and return type of the function.

What are the three aspects of a function prototype?

Function prototypes include the function signature, the name of the function, return type and access specifier.


1 Answers

The term prototype does not mean a declaration of a function preceding its definition. It means a declaration of a function that declares the types of its parameters (C 2018 6.2.1 2).

test_no_prototype has a prototype because void test_no_prototype(const struct test_arg a){ } declares the type of its parameter, const struct test_arg.

An example of a declaration without a prototype is void test_no_prototype();. It is an old style of declaration that should not be used in new code.

like image 62
Eric Postpischil Avatar answered Nov 02 '22 22:11

Eric Postpischil