What is the rationale behind tentative definitions in C?

↘锁芯ラ 提交于 2019-12-03 07:48:08

问题


Consider following program. Will this give any compilation errors?

#include <stdio.h>
int s=5;
int s;
int main(void)
{
     printf("%d",s);
}

At first glance it seems that compiler will give variable redefinition error but program is perfectly valid according to C standard. (See live demo here http://ideone.com/Xyo5SY).

A tentative definition is any external data declaration that has no storage class specifier and no initializer.

C99 6.9.2/2

A declaration of an identifier for an object that has file scope without an initializer, and without a storage-class specifier or with the storage-class specifier static, constitutes a tentative definition. If a translation unit contains one or more tentative definitions for an identifier, and the translation unit contains no external definition for that identifier, then the behavior is exactly as if the translation unit contains a file scope declaration of that identifier, with the composite type as of the end of the translation unit, with an initializer equal to 0.

My question is, what is rationale for allowing tentative definitions? Is there any use of this in C? Why does C allow tentative definitions?


回答1:


Tentative definitions was created as a way to bridge incompatible models that existed pre-C89. This is covered in the C99 rationale section 6.9.2 External object definitions which says:

Prior to C90, implementations varied widely with regard to forward referencing identifiers with internal linkage (see §6.2.2). The C89 committee invented the concept of tentative definition to handle this situation. A tentative definition is a declaration that may or may not act as a definition: If an actual definition is found later in the translation unit, then the tentative definition just acts as a declaration. If not, then the tentative definition acts as an actual definition. For the sake of consistency, the same rules apply to identifiers with external linkage, although they're not strictly necessary.

and section 6.2.2 from the C99 rationale says:

The definition model to be used for objects with external linkage was a major C89 standardization issue. The basic problem was to decide which declarations of an object define storage for the object, and which merely reference an existing object. A related problem was whether multiple definitions of storage are allowed, or only one is acceptable. Pre-C89 implementations exhibit at least four different models, listed here in order of increasing restrictiveness:




回答2:


Here's an example of a case where it's useful:

void (*a)();

void bar();
void foo()
{
    a = bar;
}

static void (*a)() = foo;

/* ... code that uses a ... */

The key point is that the definition of foo has to refer to a, and the definition of a has to refer to foo. Similar examples with initialized structures should also be possible.



来源:https://stackoverflow.com/questions/33200738/what-is-the-rationale-behind-tentative-definitions-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!