In one of the SO thread, I had seen a usage of unnamed struct acting as a placeholder for multiple variables of different types inside for loop:
For example:
for(struct {
int i;
double d;
char c;
} obj = { 1, 2.2, 'c' };
obj.i < 10;
++obj.i)
{
...
}
This compiles fine with g++.
Is this a standard C++03 syntax?
You can use an unnamed struct anywhere you can use a struct - the only difference is that it doesn't get a name that can be used somewhere else. You can declare a new type anywhere you can use a type, pretty much. It may not be particularly meaningful to do so in most places, but that's another matter.
I wouldn't exactly recommend this, other than in very special cases, but it's valid.
Below code will work in C++ (g++ 5.4.0).
http://rextester.com/ELWLF59792
//g++ 5.4.0
#include <iostream>
#include <stdio.h>
int main()
{
int i = 0;
for(struct st{ int a[9]; }t;i<3;i++)
printf("%d\n", t.a);
}
And below code will work in C (gcc 5.4.0).
//gcc 5.4.0
#include <stdio.h>
int main()
{
int i = 0;
struct st{ int a[9]; }t;
for(;i<3;i++)
printf("%d\n", t.a);
}
Related
I have a doubt regarding structs and if statements in C++
For the sake of simplicity, I have created a sample code to explain my intention
int var = 10
struct example{
int a;
int b;
if(var > 8){
int c;
}
};
I have a codebase which uses similar kind of code as above. Commenting out the if portion does not give any errors.
My question is
Could if statements be put in struct declarations?
If not, what is the possible remedy for this, since if statment is mandatory.
Note: I cannot use #if,#else directives nor std::optional or other standard libraries to mitigate this, so please help me find another solution.
No you can't use if statement inside your struct or class definition. Instead, for condition declaration, you can use #if directive.
#define var 10
struct example {
int a;
int b;
#if var > 8
int c;
#endif
}
This will work.
'#if' is a compiler directive (pre-processor directive). if statement on the other hand is runtime statement.
Other than this there is no other way!
int main()
{
int var = 10;
if(var>10){
struct example{
int a;
int b;
int c;
};
}else {
struct example{
int a;
int b;
};
}
cout<<"Hello World";
return 0;
}
There are multiple ways to address your problem one way of achieving is shown.
We cannot add if Statement in the Structure.
Consider a program with mixed C and C++ code. The C++ part contains a class which dinamically allocates a C-style typedef struct. Minimal example:
obj.h (C-code)
typedef struct _Ctype {
int i;
} Ctype;
class.hpp (C++ code)
struct A {
struct _Ctype *x;
A(int i);
~A();
};
class.cpp (C++ code)
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = new struct _Ctype;
x->i = i;
}
A::~A()
{
delete(x);
}
main.cpp (C++ code, main program)
#include "class.hpp"
int main()
{
A a(3);
return 0;
}
(The rationale for this design originates from this answer)
Is it safe (i.e., no UB) to use a new expression to allocate a C-style type struct _Ctype, as in the code above, or should one better use the C-style malloc/free?
class.cpp (C++ code, alternative)
#include <cstdlib>
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = (struct _Ctype *)malloc(sizeof(struct _Ctype));
x->i = i;
}
A::~A()
{
free(x);
}
ADDITION
To clarify the question after some comments below: In the minimal example above, all the code is compiled with a C++ compiler. One can however think to use the C++ code in conjunction with a C library. The question can then be reformulated as follows:
If I allocate memory for an C-style typedef struct via a C++ code, can the C library safely use the allocated variable? If so, are the alternatives given above both safe?
Note that one could also think to allocate the memory for Ctype through a C function, so that the C++ code only manages a pointer to it, for example:
obj.h (C-code)
typedef struct _Ctype {
int i;
} Ctype;
Ctype *allocate_Ctype();
void deallocate_Ctype(Ctype* p);
obj.C (C-code)
#include <stdlib.h>
#include "obj.h"
Ctype *allocate_Ctype()
{
return (Ctype *)malloc(sizeof(Ctype));
}
void deallocate_Ctype(Ctype *p)
{
free(p);
}
class.cpp (C++ code)
#include "class.hpp"
extern "C" {
#include "obj.h"
}
A::A(int i)
{
x = allocate_Ctype();
x->i = i;
}
A::~A()
{
deallocate_Ctype(x);
}
(Note: of course the copy constructor and operator assignment of class A need to be properly defined, the code serves as illustration of the question)
As long as the deallocation only ever happens under your control and using a delete expression, there is no problem at all. The C code interacting with the structure does not care how it was allocated.
Side note: the name _Ctype is not legal in C++, as it starts with an underscore followed by an uppercase letter. Such names (as well as names containing double underscore) are reserved for the compiler & standard library.
Is it normal that this compiles fine?
#include <vector>
#include <algorithm>
int main()
{
std::vector<int> buf;
generate(buf.begin(), buf.end(), []{ return 0; });
}
(Note the missing std:: in front of generate())
Is this behavior documented somewhere? Or did I stumble across a compiler or library bug? Which in my case would be GCC 5.3.0 and Clang 3.8.0 on Linux; both use libstdc++, so maybe library bug?
This is allowed, essentially because the arguments to generate are in std.
Code like
namespace Foo
{
struct B{};
void foo(const B&);
}
int main()
{
Foo::B b; /*Requires Foo::*/
foo(b); /*Does not require Foo:: as that is gleaned from the argument*/
}
is acceptable for similar reasons. We call it argument dependent lookup. See https://en.wikipedia.org/wiki/Argument-dependent_name_lookup
I am having trouble understanding c++ namespaces. Consider the following example:
//distr.h
namespace bogus{
extern const int x;
extern const int y;
double made_up_distr(unsigned param);
}
Now if I define my variables like the cpp below everything compiles fine
//distr.cpp
#include "distr.h"
#include <cmath>
const int bogus::x = 10;
const int bogus::y = 100;
double bogus::made_up_distr(unsigned param){
auto pdf = (exp(param) / bogus::x) + bogus::y;
return pdf;
}
But if I try to simply bring in the bogus namespace and use instead
//broken distr.cpp
#include "distr.h"
#include <cmath>
using namespace bogus;
const int x = 10;
const int y = 100;
double made_up_distr(unsigned param){
auto pdf = (exp(param) / x) + y;
return pdf;
}
My compiler tells me that the reference to x and y is ambiguous.
Why is that?
There's a simple reason why this can't plausibly work the way you expected:
namespace bogus {
const int x;
}
namespace heinous {
const int x;
}
using namespace bogus;
using namespace heinous;
const int x = 10;
now, should x above refer to bogus::x, heinous::x or a new global ::x?
It would be the third without the using statements, which means here that adding a using statement would change the meaning of existing code in a particularly subtle way.
The using statement is used to introduce the contents of a scope (usually but not necessarily a namespace) for lookup. The statement
const int x = 10;
wouldn't normally require a lookup in the first place, except to detect an ODR violation.
Name lookup for the identifier in declarations/definitions doesn't work the same way as name lookup in usage. In particular, it doesn't care about using statements. There is a very simple reason for this: if it were different, it would lead to all sorts of nasty surprises. Consider this:
// sneakattack.h
namespace sneakattack { void foo(); }
using namespace sneakattack;
// somefile.cpp
#include "sneakattack.h"
void foo() { std::cout << "Hello\n"; }
// otherfile.cpp
void foo();
int main() { foo(); }
This program currently works: the declaration sneakattack::foo is ignored, and the definition ::foo is correctly linked to the use in otherfile. But if name lookup worked differently, somefile would suddenly define sneakattack::foo, not ::foo, and the program would fail to link.
Taken from http://www.ocf.berkeley.edu/~wwu/riddles/cs.shtml
It looks very compiler specific to me. Don't know where to look for?
1. Abuse C++ automatic typedefs
(Note that the struct needs to be declared in an inner scope so that it takes precedence over the outer name in C++.)
#include <stdio.h>
int main(void)
{
char x;
{
struct x { char dummy[2]; };
printf("%s\n", sizeof (x) == 1 ? "C" : "C++");
}
}
A similar version that doesn't rely on the ambiguity between sizeof (type) and sizeof (variable), using only types:
#include <stdio.h>
int main(void)
{
typedef char t;
{
struct t { char dummy[2]; };
printf("%s\n", sizeof (t) == 1 ? "C" : "C++");
}
}
2. Abuse C++ struct/class equivalence, automatic typedefs, and automatically-generated default constructors
#include <stdio.h>
int isC = 0;
void Foo() { isC = 1; }
int main(void)
{
struct Foo { int dummy; };
Foo();
printf("%s\n", isC ? "C" : "C++");
}
3. Abuse nested struct declarations in C
Also see Symbol clashing of inner and outer structs, C++ vs C
#include <stdio.h>
int main(void)
{
typedef struct inner { int dummy; } t;
{
struct outer { struct inner { t dummy[2]; } dummy; };
printf("%s\n",
sizeof (struct inner) == sizeof (t)
? "C++"
: "C");
}
}
4. Abuse // comments
This won't work with C99 or with C89 compilers that support // as an extension.
#include <stdio.h>
int main(void)
{
printf("%s\n",
0 //* */
+1
? "C++"
: "C");
}
or alternatively:
printf("%s\n",
1 //* */ 2
? "C++"
: "C");
5. sizeof differences with char literals
Note that this isn't guaranteed to be portable since it's possible that some hypothetical platform could use bytes with more than 8 bits, in which case sizeof(char) could be the same as sizeof(int). (Also see Can sizeof(int) ever be 1 on a hosted implementation?)
#include <stdio.h>
int main(void)
{
printf("%s\n", sizeof 'a' == 1 ? "C++" : "C");
}
6. Abuse differences in when lvalue⇒rvalue conversions are performed
This is based off of the 5.16, 5.17, 5.18 example in the ISO C++03 standard, and it works in gcc but not in MSVC (possibly due to a compiler bug?).
#include <stdio.h>
int main(void)
{
void* array[2];
printf("%s\n",
(sizeof (((void) 0), array) / sizeof (void*) == 1)
? "C"
: "C++");
}
7. Abuse differences in the way C and C++'s grammars parse the ternary operator
This one isn't strictly legal, but some compilers are lax.
#include <stdio.h>
int main(void)
{
int isCPP = 1;
printf("%s\n", (1 ? isCPP : isCPP = 0) ? "C++" : "C");
}
(You also could check for the __cplusplus preprocessor macro (or various other macros), but I think that doesn't follow the spirit of the question.)
I have implementations for all of these at:
http://www.taenarum.com/csua/fun-with-c/c-or-cpp.c
We had to do a similar assignment at school. We were not allowed to use preprocessor (except for #include of course). The following code uses the fact that in C, type names and structure names form separate namespaces whereas in C++ they don't.
#include <stdio.h>
typedef int X;
int main()
{
struct X { int ch[2]; };
if (sizeof(X) != sizeof(struct X))
printf("C\n");
else
printf("C++\n");
}
Simple enough.
#include <stdio.h>
int main(int argc, char ** argv) {
#ifdef __cplusplus
printf("C++\n");
#else
printf("C\n");
#endif
return 0;
}
Or is there a requirement to do this without the official standard?
puts(sizeof('a') == sizeof(int) ? "C" : "C++");
Here's the program:
#include <stdio.h>
int main(int argc, char *argv[])
{
printf("This is %s\n", sizeof 'a' == sizeof(char) ? "C++" : "C");
return 0;
}
And here is some nice reading on C and C++ differences.
Just look to see if the __STDC__ and __cplusplus compiler macros are defined.
One word, __cplusplus.
I'm guessing the intent is to write something that depends on differences between the languages themselves, not just predefined macros. Though it's technically not absolutely guaranteed to work, something like this is probably closer to what's desired:
int main() {
char *names[] = { "C", "C++"};
printf("%s\n", names[sizeof(char)==sizeof('C')]);
return 0;
}
For what it's worth, here's another answer:
char x[sizeof(char *)+2], y[1];
printf("%.*s\n", sizeof(1?x:y)-sizeof(char *)+1, "C++");
You could try preprocessor directives, but that might not be what they are looking for.