C/C++ replacement/redefinition rules? - c++

I am not particularly new to C/C++ but today I discovered some things that I didn't expect.
This compiles in gcc:
/* test.c */
#include <stddef.h> // !
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
return 0;
}
This doesn't:
/* test.c */
#include <stddef.h>
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // ERROR
return 0;
}
This doesn't either:
/* test.h */ // ! header
typedef unsigned long int size_t;
typedef unsigned long int size_t; // ERROR
Similarly in g++ this compiles:
/* test.h */ // ! header
#include <cstddef>
inline void* operator new(size_t, void* p) throw() { return p; }
This doesn't:
/* test.h */ // ! header
#include <new> // !
inline void* operator new(size_t, void* p) throw() { return p; } // ERROR
This does:
/* test.cc */
#define _NEW
#include <new> // !
#include <iostream>
#include <cstdlib>
using std::cout;
using std::endl;
inline void* operator new(size_t size) throw() // NO ERROR EXPECTED
{
cout << "OPERATOR NEW CALLED" << endl;
return malloc(size);
}
inline void* operator new(size_t, void* p) throw() // NO ERROR
{
cout << "PLACEMENT NEW CALLED" << endl;
return p;
}
int main()
{
char *buffer[4];
int *i = new (buffer) int;
int *j = new int;
return 0;
}
(Replacing the standard new operator works in all of the above cases. Replacing the replacement new operator is illegal, I know.)
It is easy to see a pattern, but can somebody offer me a "standard" explanation?
Why can I do things in .c or .cc files that I can't in .h files (redefine old typedefs, replace functions that are illegal to replace)?
Thanks for the reply. I have omitted some code including the header guards. In the last .cc example, I HTML encoded << as & g t ; & g t ; by mistake and forgot to include cstdlib.
I have fixed the code so it compiles. However, another thing that I had omitted was #define _NEW, which proved crucial. Apparently in GNU the header guard of <new> defines _NEW, so my defining it here prevented the inclusion of the standard new header, so I the replacement worked
m#m:~/Desktop/Library$ ./a.out
PLACEMENT NEW CALLED
OPERATOR NEW CALLED
So yeah, the only thing that is left unexplained is how come I can re-typedef stuff in .c/.cc files multiple times but not in .h like so:
/* test.c */
#include <stddef.h>
typedef unsigned long int size_t; // NO ERROR
typedef unsigned long int size_t; // NO ERROR
int
main(void)
{
typedef unsigned long int size_t; // NO ERROR
return 0;
}
Not that I want to do that anyway, but just wondering.
EDIT: Thanks, that really answers all of it. Changing it to xyz does not allow multiple definitions in a given scope, which feels right. :)
The reason why I was doing these little tests is that I am writing a subset of C and C++ for a small operating system but since I am using the existing libraries without removing anything to assist me in the testing of mine, I was trying to figure out how to ensure that (1) my code is being called in the tests (e.g my placement new) and (2) that my code doesn't clash with the GNU libraries.
The answer to (1) now seems pretty obvious. I just #define the header guard macro from the standart X.h into my X.h :).

Using GCC 4.0.1 on MacOS X 10.4.11 (ancient - but so's the computer), the example with "test.h" works - or my adaptation of it does. It appears you can have as many (identical) global typedefs of 'size_t' as you like - I had 5 with the version in stddef.h.
The first typedef inside main is 'obviously' legal; it is a new scope and can define a new meaning for the name.
The C99 Rationale says:
In C89, a typedef could be redeclared in an inner block with a declaration that explicitly contained a type name. This rule avoided the ambiguity about whether to take the typedef as the type name or a candidate for redeclaration. In C99, implicit int declarations are not allowed, so this anbiguity [sic!] is not possible and the rule is no longer necessary.
Later on, discussing standard headers, it also says:
The C89 Committee decided to make library headers “idempotent,” that is, they should be
includable any number of times, and includable in any order. This requirement, which reflects
widespread existing practice, may necessitate some protective wrappers within the headers to
avoid, for instance, redefinitions of typedefs. To ensure that such protective wrapping can be
made to work, and to ensure proper scoping of typedefs, standard headers may only be included outside of any declaration.
Clearly, therefore, redefinitions of a typedef in a single scope (e.g. the file scope) is not allowed in general.
I think, therefore, that the multiple external redefinitions of size_t is probably either a feature of GCC or a bug - actually, a feature.
If you change size_t to xyz, you get many more errors.

I am not sure how the multiple typedefs compile in your case. Remember, headers don't compile by themselves, but in conjunction with an implementation class. Also, your headers lack header guards or a #pragma once directive. What options are you using?
As for placement new -- it is explicitly forbidden by the standard (18.5.1.3) -- so that won't work.
There is no pattern here -- except for redefinition of already declared symbols.
BTW: None of your .c or .cpp examples compile with Comeau.

Related

How to access a structure array from 2 different files?

How would I go about doing something like this?
header.h
struct myStruct;
extern myStruct array[];
main.cpp
#include "header.h"
struct myStruct{
int a = 0;
};
myStruct array[5];
array[0].a = 1;
file2.cpp
#include "header.h"
std::cout << array[0].a;
The size and layout of myStruct needs to be known everythere you try to access its contents, so you must either define it inside of the .h file, or only access it using opaque pointers and dedicated functions.
Also, using C arrays in C++ is somewhat outdated. You should use STL containers instead, such as std::array<T, N> or std::vector<T>.
Well, first of all you should put struct declarations in the header files.
Second, you can't put assignments to arrays or std::cout statements just loose in files. I'm assuming you did this for short code and not because you didn't know it needed to be in a function, but I'm pointing it out just in case.
Third, struct declarations require a semicolon
What you would do is have a header file:
header.hpp:
#pragma once
struct MyStruct {
int a = 0;
};
extern MyStruct array[5];
The extern here means that the data is somewhere else. So let's make the somewhere else.
header.cpp:
#include "header.hpp"
MyStruct array[5];
main.cpp:
#include "header.hpp"
void someFunction() {
...
array[0].a = 1;
...
}
file2.cpp:
#include <iostream>
#include "header.hpp"
void someOtherFunction() {
...
std::cout << array[0].a;
...
}
How would I go about doing something like this?
You could go about doing something like what you did by doing something like what you did, except fixing the bugs in your attempt. Here is the list of bugs:
You failed to end the definition of myStruct with a semicolon.
.c suffix is conventionally for C source files while you're writing C++. Your compiler will likely be confused unless you provide some unconventional options to the compiler.
You use cout which you forgot to declare. Or did you intend to use std::cout? In that case you must include <iostream> in order to use it, and use the appropriate namespace.
In file2.c, you use the class myStruct in a way that depends on the definition of myStruct without providing that definition.
array[0].a = 1; and cout << array[0].a; are expression statements. Expression statements may not be in namespace scope, and must be within a block scope. In your program, those expression statements are in the namespace scope which makes the program ill-formed.

Conditional C/C++ struct definitions

I've stumbled across some code that looks like this:
typedef struct SomeStruct
{
int foo;
void * bar;
#if defined(__cplusplus)
SomeStruct();
#endif
} SomeStruct;
It's in a header file that will be included by both .c and .cpp files. That seems to be at least technically a violation of the One-Definition-Rule. The obvious impact I see is that if one of these is ever declared in .c file, the constructor won't run. And unfortunately, someone seems to have used this as a pattern for the correct way to declare structs, and has declared a couple dozen structs just like it.
I'm trying to figure out how serious a problem this is. Beyond the constructor possibly not running, is there any other likely impact? The constructor is implemented in a .cpp file. I see pointers to structs allocted in a .c file (with malloc) that are passed to functions in the .cpp files. They appear to work correctly (compiled with gcc/g++ 4.6.2 for Suse Linux, if that matters), as far as I can tell. Would something break if virtual member functions were also added? Right now, none of these classes have anything in their cplusplus section other than the default constructor, as shown above.
It's not exactly a violation of the ODR. Informally, the C compiler see a POD type and the C++ compiler see a class in the global namespace which will become an entity with a mangled name. More importantly, the structure is only declared differently for C and C++ compilers, but it is only defined once in a C++ source file. Most likely there's some allocation and free functions in a C++ source file which expose the constructor/destructor to a C API. For example,
Header file
$ cat some_struct.h
#ifndef SOME_STRUCT_H
#define SOME_STRUCT_H
typedef struct SomeStruct {
int foo;
void *var;
#if defined(__cplusplus)
SomeStruct();
#endif
} SomeStruct;
#if defined(__cplusplus)
extern "C" {
#endif
SomeStruct *some_struct_malloc();
void some_struct_free(SomeStruct **);
#if defined(__cplusplus)
} // extern "C"
#endif
#endif // SOME_STRUCT_H
C++ source file
$ cat some_struct.cpp
#include "some_struct.h"
#include <cstddef>
SomeStruct::SomeStruct()
{
foo = 10;
var = NULL;
}
SomeStruct *some_struct_malloc() { return new SomeStruct; }
void some_struct_free(SomeStruct **pp)
{
if (*pp)
delete *pp;
*pp = NULL;
}
C source file:
$ cat main.c
#include "some_struct.h"
#include <stdio.h>
int main()
{
SomeStruct *p = some_struct_malloc();
printf("%d\n", p->foo);
}
I would say it is a bad style. But it works as a convenient way to expose a C++ library to a C API

How not to pollute the global namespace with declarations of a C header?

I'm trying to wrap a C library in C++, to make it a modern, high level and idiomatic C++ library. What I want to do, is to make the C objects completely opaque and/or directly unavailable from the C++ code and wrap/replace them with higher-level alternatives.
The problem I'm facing with is simple: I want to include the C header only to the C++ source, so that the C++ header when included won't include the C header's declarations as well, that is, it won't pollute the global namespace.
But it looks like the correct separation of the header and source files does not allow me to do that. Here is a very much dummified version of my problem, the comments will tell you the rest:
my_header.h:
typedef enum
{
my_Consts_ALPHA = /* some special value */,
my_Consts_BETA = /* other special value */,
} my_Consts;
typedef struct
{
// members...
} my_Type;
void
my_Type_method(my_Type *const,
my_Enum);
my_header.hpp:
namespace my
{
enum class Consts; // <-- This header is missing the constant values of
// this enum, because its values are defined by
// the C header :(
class Type : public my_Type // <-- The super struct is coming from the
// C header, but I don't want to include
// that header here :(
{
public:
void
method(Consts constant);
};
}
my_source.cpp:
extern "C"
{
#include "my_header.h"
}
#include "my_header.hpp"
namespace my
{
enum class Consts
{
ALPHA = my_Consts_ALPHA,
BETA = my_Consts_BETA,
};
void
Type::method(Consts constant)
{
my_Type_method(static_cast<my_Type *const>(this),
static_cast<my_Consts>(constant));
}
}
So my questions are: am I missing something very obvious here? Is this even possible to achieve? Is there a trick that I'm not aware of?
In the comments of the question #AnalPhabet suggested sarcastically, that one should use #include of a C header inside a namespace. #n.m. confirmed, that it is actually a working solution, and now I tested it on my own setup, and fortunately it is working pretty fine.
(Although I have no idea, if this is implementation specific or not, but I tested on both g++ and clang++ and it is working.)
It does not solve the opaqueness problem, but at least it makes a bit harder to access to the raw C data directly as it is living in a separate namespace now, therefore the user can't accidentaly access, but willingly.
So, the my_header.hpp should look like this:
namespace my
{
extern "C"
{
#include "my_header.h"
}
enum class Consts
{
ALPHA = my_Consts_ALPHA,
BETA = my_Consts_BETA,
};
class Type : public my_Type
{
public:
void
method(Consts constant);
};
}
So wherever my_header.hpp is #include'd, the user can only access to the C values as follows:
my::my_Consts_ALPHA // The wrapped value is => my::Consts::ALPHA
my::my_Type // The wrapped value is => my::Type
my::my_Type_method(t,..) // The wrapped value is => t.method(..)
If the whole idea of writing high-level and idiomatic C++ wrapper is to bring safety, automatic memory management and convenient C++ types like std::sting, I would include C header into cpp file only.
Provide clean idiomatic C++ interface, and use C library only in the implementation.
Do not afraid to write a couple of utility functions that convert C data to C++ and back. If a C++ class should hold C-specific data, and it is not possible to replace it with C++ analog, use some type erasure technique to keep clean interface.
I wouldn't worry about performance due to such wrapping until I see it on top in a profiler log. In most cases it is not a bottleneck.
Again, splitting interface and implementation is usually a win.
UPDATE
Initially, I was thinking more about project specific C++ interface rather than universal C++ wrapper around C library.
Solution with extern "C" wrapped into a namespace looks correct to me (see §7.5 of C++11 standard). But, I've never seen this technique in the wild.
You can go further and add nested detail namespace to not pollute my namespace with C types. This trick is popular in header only libraries:
namespace my
{
namespace detail
{
extern "C"
{
#include "my_header.h"
}
}
enum class Consts
{
ALPHA = detail::my_Consts_ALPHA,
BETA = detail::my_Consts_BETA,
};
class Type : public detail::my_Type
{
public:
void
method(Consts constant);
};
}
Take into account that you can't make C functions completely opaque or wrap them to a single namespace when you link with static library. They have external linkage and know nothing about namespaces.
namespace A {
extern "C" void my_Type_method(my_Type *const, my_Enum);
}
namespace B {
extern "C" void my_Type_method(my_Type *const, my_Enum);
}
extern "C" void my_Type_method(my_Type *const, my_Enum);
Basically, all these declarations refer to the same C function. As C doesn't support namespaces and overloading, linker usually uses function names as unique identifiers (even argument types are ignored).
Anyway, this approach will help to avoid accidental access to C interface.
I'm not sure if it's language legal, but I think extern "C" is just there to unmangle functions, so as long as you keep them in the .cpp file you can get away with this.
This is a little profane, but it seems to work with gcc 4.3.5. It demonstrates that you can use C functions while also hiding them in a namespace.
I didn't bother with inheriting struct_t, but it should probably work. I have no idea if you can pull off the enum class.
foo.h
#ifndef foo_H
#define foo_H
typedef enum {
ALPHA,
BETA
} enum_t;
typedef struct
{
int i;
} struct_t;
void printit(struct_t print_me);
#endif // foo_H
foo.c
#include <stdio.h>
#include "foo.h"
void printit (struct_t print_me)
{
printf ("Hello World %d!\n", print_me.i);
}
bar.hpp
#ifndef bar_HPP
#define bar_HPP
namespace _foo {
// Don't need extern "C" since we're not using functions
#include "foo.h"
}
struct based_on_struct_t // : public _foo:struct_t // Do you really have to derive? It might be possible, but it's ugly
{
_foo::struct_t i;
double j;
based_on_struct_t (int _i, double _j) : j(_j) { i.i = _i; }
void print(void); // Gonna call printit, MUST be in .cpp
};
#endif // bar_HPP
bar.cpp
namespace _foo{
extern "C" {
#include "foo.h"
}
}
#include "bar.hpp"
#include <stdio.h>
void based_on_struct_t::print (void) {
// Call the old version...
printit(i);
// And do new crap
printf ("Goodbye World %d %f\n", i.i, j);
}
driver.cpp
#include "bar.hpp"
int main (void) {
based_on_struct_t B(10, .1);
B.print();
return 0;
}
Demo...
$ gcc foo.c -c -O3
$ g++ foo.o bar.cpp driver.cpp
$ ./a.out
Hello World 10!
Goodbye World 10 0.100000
$

How to use a C++ extern constant variable for a template argument in a different file

I have the following 5 files: global_vars.h, global_vars.cpp content.h content.cpp main.cpp.
global_vars.h
#ifndef global_vars_h
#define global_vars_h
namespace Constants{
extern const unsigned int b;
}
#endif
global_vars.cpp
#include "global_vars.h"
namespace Constants{
extern const unsigned int b(5);
}
content.h
#ifndef CONTENT_H_
#define CONTENT_H_
#include "global_vars.h"
#include <bitset>
struct a{
std::bitset<Constants::b> s;
int a=10;
};
#endif
content.cpp
#include "content.h"
a xVar;
main.cpp
#include "content.h"
int main(){
return 0;
}
I get the following errors:
In file included from content.cpp:1:0:
content.h:11:31: error: the value of ‘Constants::b’ is not usable in a constant expression
In file included from content.h:4:0,
from content.cpp:1:
global_vars.h:6:28: note: ‘Constants::b’ was not initialized with a constant expression
extern const unsigned int b;
I have to use Constants::b in files other than content.cpp/.h (for other bitsets) as well so how can I go around doing this? Appreciate the help.
thanks
What you ask is not possible.
In C++, templates are resolved entirely by the compiler, the linker only gets to see fully instantiated bodies of template classes and functions. The compiler only gets to see code that is in a given compilation unit.
Therefore, even if an int is extern const and assigned a value in some compilation unit (making it valid at run-time), it cannot possibly be used as a template parameter in any other compilation unit. There would be no way for the compiler to know the value of that int at the time that it is resolving which template instantiations refer to the same types.
The closest you can get most likely, is that you could a pointer to that int as a template parameter, and then if you have e.g. a function using that template parameter which is run at run-time, it could dereference the pointer to get the constant value. If you have link-time optimizations enabled it might even inline it, I'm not sure.

Undef a typedef in C++?

I am working on a huge project which has one file A.h whose code has a line
typedef unsigned __int16 Elf64_Half;
Also since I am building on Linux and using dlinfo function, I have to include link.h file in my project. And this is where it creates a conflict because I have two typedefs having the same name Elf64_Half. (Linux link.h includes elftypes.h and it too has: typedef unsigned short Elf64_Half;).
What do I do in such a case? Is the only option I have, to change my typedef in a.h? Remember it is not too easy because the project is huge and I will have to make a change in several places.
Is there a way to undef a typedef or something?
For clarification, Rahul Manne gave an easy solution. Do
#define Elf64_Half The_Elf64_Half_I_dont_care
#include<link.h>
#undef Elf64_Half
#include<A.h>
/*
* Code here and use Elf64_Half from A.h as you like.
* However, you can't use Elf64_Half from link.h here
* or you have to call it The_Elf64_Half_I_dont_care.
*
*/
This will substitute each Elf64_Half in link.h with The_Elf64_Half_I_dont_care and thus you get no conflicts with A.h. As long as you don't want to use Elf64_Half of link.h explicitly that will work with no problems. You just have to remember that Elf64_Half from link.h is now called The_Elf64_Half_I_dont_care in case you ever have to use it explicitly in this file.
What do I do in such a case?
A common remedy is to put the one which needs the least visibility behind a "compilation firewall". That is, to create your own abstraction/interface which provides the functionality you need, and then to limit the visibility of the included file to the *.cpp by including it in that *.cpp only. Of course, that *.cpp file would also not be permitted to include the header which has the other definition of the typedef.
Then the declarations won't cause conflict because they will never be visible to the same translation unit.
In your example, you'd likely create a wrapper over the dlinfo() functionalities you need. To illustrate:
DLInfo.hpp
namespace MON {
class DLInfo {
public:
/* ...declare the necessary public/client functionality here... */
int foo();
...
};
}
DLInfo.cpp
#include "DLInfo.hpp"
// include the headers for dlinfo() here.
// these includes should not be in your project's headers
#include <link.h>
#include <dlfcn.h>
// and define your MON::DLInfo implementation here, with full
// ability to use dlinfo():
int MON::DLInfo::foo() {
...
}
...
Here's a little work around I figured out: If you define it as something else first, then you can typedef it later. See here in the example (I'm on OS X using g++):
#import <iostream>
using namespace std;
typedef unsigned int uint32;
int main() {
cout << sizeof(uint32) << endl;
}
The output of this program is
4
Now consider this modified program:
#import <iostream>
using namespace std;
typedef unsigned int uint32;
#define uint32 blah
typedef unsigned long uint32;
int main() {
cout << sizeof(uint32) << endl;
}
The output of this program is
8
So to answer your question, you would add a line to your code:
#define Elf64_Half Elf64_Half_custom
For clarity, this works because you are basically renaming them all, but doing so with a single command instead of having to change all of your own names.