In some library I'm using (written in C) its
StorePGM(image, width, height, filename)
char *image;
int width, height;
char *filename;
{
// something something
}
All functions are defined this way. I never seen such function definitions in my life. They seem to be valid to MSVC but when I compile it as C++ it gives errors.
What is it? some kind of old version C?
Yes. K&R, pre-standard C. Avoid using it.
Before the 1989 ANSI C standard, C didn't have prototypes (function declarations that specify the types of the parameters); these old-style declarations and definitions were all that was available.
In 1989, the ANSI C standard (which essentially became the 1990 ISO C standard) introduced prototypes. If I recall correctly, the idea actually came from C++ (which had not yet been standardized at the time). Old-style declarations and definitions remained legal, so that old code could still be compiled. The 1989 standard also said that old-style declarations were "obsolescent", meaning that they could be removed in a future version of the standard.
The 1999 ISO C standard, which (officially) superseded the 1990 standard, left this alone; old-style declarations and definitions are still legal, and all conforming compilers must support them (though they're free to warn about them, as they can warn about anything else).
As of the latest C201X draft (large PDF), this still hasn't changed. Old-style function declarations and definitions are still a required part of the language, and all conforming compilers must support them. (Personally, I consider this unfortunate.)
C++, on the other hand, has never (?) supported anything other than prototypes as function declarations; Stroustrup wasn't as concerned about maintaining compatibility with old C code.
But unless you need to maintain very old code and/or use very old compilers, there is no good reason to use old-style function declarations or definitions.
Note that, at least in C, this definition:
int main() {
/* ... */
}
is actually an old-style definition. It's correct for C++, where it's a prototype indicating that main has no parameters, but in C it should be
int main(void) {
/* ... */
}
(C++ also accepts this form for compatibility with C -- but by the time you're writing main, you should already have decided which language you're using.)
Yep, it's K&R-Style. (Kernighan & Ritchie are the inventors of C) See also http://www.lysator.liu.se/c/bwk-tutor.html for examples of this pre-ANSI style.
Related
From the following stackoverflow answer, the user says:
It means that the variable is local to a translation unit (simply put,
to a single source file), and cannot be accessed from outside it. This
use of static is in fact deprecated in the current C++ Standard -
instead you are supposed to use anonymous namespaces:
static int x = 0;
should be:
namespace {
int x = 0;
}
I don't disagree that anonymous namespaces are the preferred method,
but is using static really deprecated now?
Where does the standard say this?
No, it is not currently deprecated. It was at one point but this was reversed due to C comparability issues. At some point before 1999 it was deprecated and this lead to defect report 174 which says:
The decision to deprecate global static should be reversed.
We cannot deprecate static because it is an important part of C and to abandon it would make C++ unnecessarily incompatible with C.
Because templates may be instantiated on members of unnamed namespaces, some compilation systems may place such symbols in the
global linker space, which could place a significant burden on the
linker. Without static, programmers have no mechanism to avoid the
burden.
This lead to defect report 223 in which the meaning of deprecation was revised from:
deprecated is defined as: Normative for the current edition of the Standard, but not guaranteed to be part of the Standard in future revisions.
it was noted that this implies, only non-deprecated features will be support in future standards:
However, this definition would appear to say that any non-deprecated feature is "guaranteed to be part of the Standard in future revisions." It's not clear that that implication was intended, so this definition may need to be amended.
and changed the meaning of deprecated to:
These are deprecated features, where deprecated is defined as: Normative for the current edition of the Standard, but having been identified as a candidate for removal from future revisions.
and later the feature was undeprecated due to C compatibility issues by defect report 1012:
Although 7.3.1.1 [namespace.unnamed] states that the use of the static keyword for declaring variables in namespace scope is deprecated because the unnamed namespace provides a superior alternative, it is unlikely that the feature will be removed at any point in the foreseeable future, especially in light of C compatibility concerns. The Committee should consider removing the deprecation.
If you use extern C it with C++ files, does that allow defined C behavior that is undefined in C++?
blah.h
extern "C"
{
struct x {
int blah;
char buf[];
};
char * get_buf(struct x * base);
struct x * make_struct(int blah, int size);
}
some_random.cpp
#include "blah.h"
...
x * data=make_struct(7, 12);
std::strcpy(get_buf(data), "hello");
Is using the defined behavior in C's flexible array member, defined behavior when used this way?
Flexible array members are a standard feature of C, starting with the 1999 standard. They do not exist in C++.
Your code is not valid C++. Wrapping it in extern "C" doesn't change that. A conforming C++ compiler must at least warn about it, and arguably should reject it.
It happens that g++ implements C-style flexible array members as an extension to C++. That's perfectly legitimate (compilers are allowed to implement extensions), but its use is not portable. Its behavior, like that of any language extension, is defined by the compiler, not by the language.
If you compile it with g++ -pedantic, you'll get a warning:
c.cpp:5:21: warning: ISO C++ forbids zero-size array ‘buf’ [-Wpedantic]
char buf[];
^
If you want to use C-style flexible array members in a C++ program without relying on a compiler-specific extension, you can compile your C code as C and link it into your C++ program. You can't make the type with the flexible array member visible to your C++ code, but you can use it internally in the C code, and perhaps provide access to it in your C++ code via an opaque pointer. See the C++ FAQ for information about mixing C and C++ within the same program. (Or you can just use the g++ extension, at the cost of not being able to compile your code with other compilers.)
(I'm assuming that you're using g++. Some other compilers probably implement similar extensions.)
No.
extern "C" is only a linkage specification, so that enclosed symbols can be linked to from C. It does not switch your compiler to "C mode" for a section of code.
An extern "C" declaration only affects linkage of external functions, so that name mangling is not performed. It doesn't mean that the functions will be compiled using the rules of the C language instead of C++. In other words, including the code in some_random.cpp will not make its behavior defined.
It's just ascii until such time as the compiler runs. So the preprocessor will paste the files together, then the compiler will treat the result as whatever language you specified.
It isn't a C flexible array member, it's a text file. Undefined behaviour remains.
I know Macro implementation of putc() in C, but is it same in C++?
It will depend on your implementation of cstdio. In most cases this is really just a wrapper around stdio.h, with wrappers declared inside the std namespace, and the C and C++ compilers share the same standard library for C functions. For example, VS2010 uses stdio.h for C++, in which putc is implemented as both a macro and a function, depending on environment and other compile-time definitions.
Which version of C++? C++83 (1983)? C++98 (1998)? C++11 (2011)?
The C++98 and C++11 Specifications rely on the ISO C specifications for C Library functions, and do not put additional implementation constraints on them, other than trivial ones like renaming stdio.h to cstdio.h and allowing inclusion without the dot-h suffix.
See: C++98 Specification
See: C++11 Specification
Look in cstdio.h if you are interested in your particular compiler.
However, if we dig deeper and take a look at the ISO C standard: "ISO/IEC 9899:1990" (C89/C90), well, we find that it is unavailable for free viewing on the web (not even the final draft standard), so moving on to C99 (NOT ISO C), you find...
...that C99 (Not "ISO C") says putc() MAY be implemented as a macro,
See: C99 Specification
So if you are really developing in Obj-C++ (which uses C99), then C99 is the relevant specification to consider, not ISO C (C90). Also, since C99 lets the compiler writer decide whether to make putc() a macro or not, you should consider it an open possibility, and decide whether you really care to know about the C90 (ISO C) spec which is becoming obsolete (now that even C11 (2011) is out.)
Yes it is. Both C and C++ use <stdio.h> which has the same scheme in all implementations that I know of.
Are all the functions in a conformant C++98/03/0x implementation completely C99 conformant?
I thought C++0x added some C99 (language) features, but never heard or read anything definitive about the C library functions.
Just to avoid any confusion, I'm talking about a C++ program using functions declared in the <c*> header set.
Thanks.
Most of the C99 standard library has been imported in C++0X but not all. From memory, in what wasn't imported there are
<ctgmath> simply includes <ccomplex> and <cmath>,
<ccomplex> behaves as if it included <complex>
<cmath> has quite a few adjustment (providing overload and template functions completing the C99 provided one)
Some other headers (<cstdbool>, <iso646.h>, ...) have adjustments to take differences between language into account (bool is primitive in C++, a macro provided by <stdbool.h> in C for instance), but nothing of the scope of the math part.
The headers <xxx.h> whose <cxx> form doesn't behaves as the C99 version simply declares the content of <cxxx> in the global namespace, they aren't nearer of the C99 <xxx.h> content.
A related thing: C++0X provides some headers in both cxxx and xxx.h forms which aren't defined in C99 (<cstdalign> and <cuchar>, the second one is defined in a C TR)
(I remembered that a bunch of mathematical functions from C99 had been put in TR1 but not kept in C++0X, I was mistaken, that bunch of mathematical functions weren't part of C99 in the first place).
No. C++03 is aligned with ANSI C89/ISO C90, not C99.
The upcoming C++0x standard is expected to be aligned to some degree with C99. See paragraph 17.6.1.2 in the current draft which lists ccomplex, cinttypes, cstdint etc. Note that, as AProgrammer mentions, some headers aren't exactly the same; further, that the header cuchar is aligned with the C Technical Report 19769 rather than C99.
In C++, is it safe/portable to use static member function pointer for C API callbacks? Is the ABI of a static member function the same as a C function?
It is not safe per the C++ standard. As stated in this SO posting:
A C callback function implemented in C++ must be extern "C". It may seem to work as a static function in a class because class-static functions often use the same calling convention as a C function. However, doing that is a bug waiting to happen (see comments below), so please don't - go through an extern "C" wrapper instead.
And according to comments made by Martin York in that answer there are real-world problems trying to do so on some platforms.
Make your C ABI callbacks extern "C".
Edit: Adding some supporting quotes from the standard (emphasis mine):
3.5 "Program and linkage":
After all adjustments of types (during which typedefs (7.1.3) are replaced by their definitions), the types specified by all declarations referring to a given object or function shall be identical, except that declarations for an array object can specify array types that differ by the presence or absence of a major array bound (8.3.4). A violation of this rule on type identity does not require a diagnostic. [3.5/10]
[Note: linkage to non-C++ declarations can be achieved using a linkage-specification (7.5). ] [3.5/11]
And
7.5 "Linkage specifications":
... Two function types with different language linkages are distinct types even if they are otherwise identical. [7.5/1]
So if the code making the callback is using C language bindings for the callback, then the callback target (in the C++ program) must as well.
After searching and several breaks while attacking other problems, I found an answer which is clear and succinct (for standardese, anyway):
Calling a function through an expression whose function type has a language linkage that is different from the language linkage of the function type of the called function's definition is undefined. [5.2.2/1]
I still maintain that it is problematic at a fundamental level to use text from the C++ standard to define the behavior of a C library compiled with a C compiler, and exactly how that interlanguage interoperability works is very implementation-specific; however, this is the closest I think either standard can (currently) hope to define such interaction.
In particular, this is undefined behavior (and isn't using a C library so that issue doesn't arise):
void call(void (*pf)()) { pf(); } // pf() is the UB
extern "C" void f();
int main() { call(f); }
// though I'm unsure if a diagnostic is required for call(f)
Comeau does give a diagnostic at call(f) (though it can do that even if the diagnostic isn't required).
This isn't undefined behavior, and shows how to include language linkage in a function pointer type (which is through a typedef):
extern "C" typedef void F();
void call(F* pf) { pf(); }
extern "C" void f();
int main() { call(f); }
Or could be written:
extern "C" {
typedef void F();
void f();
}
void call(F* pf) { pf(); }
int main() { call(f); }
For all the Windows C++ compilers that I'm aware of, the answer is yes, but nothing in the language standard guarantees this. I wouldn't let that stop you however, it's a very common way of implementing callbacks using C++ - you may find you need to declare the static functions as WINAPI however. This is taken from an old threading library of my own:
class Thread {
...
static DWORD WINAPI ThreadFunction( void * args );
};
where this is the callback use by te Windows threading API.
ABI isn't covered by either the C or C++ standards, even though C++ does give you "language linkage" through extern "C". Therefore, ABI is fundamentally compiler/platform specific. Both standards leave many, many things up to the implementation, and this is one of them.
Consequently, writing 100% portable code—or switching compilers—is hard to impossible, but allows vendors and users considerable flexibility in their specific products. This flexibility allows more space and time efficient programs, in ways that don't have to be anticipated in advance by the standards committees.
As I understand it, ISO's rules do not allow a standard more often than once every 10 years (but there can be various publications, such as TC1 and TR1 for C++). Plus there is the idea (I'm not sure if this comes from ISO, is carried over from the C committee, or even from elsewhere) to "distill"/standardize existing practice rather than going off into left field, and there are many existing practices, some of which conflict.