C++: static array inside class having unknown size - c++

I wasn't familiar with this. I searched it on google but didn't find my answer. So, posting my question.
Just tried following program:
#include <iostream>
class test
{
static char a[];
static int b[];
};
int main()
{
test t;
}
It compiles fine without any warnings on MSVS 2010 & g++ 4.8.1. It also compiles fine in C++14 compiler. (See live demo here.) So, where does C++ standard says about this? If I remove static keyword from the declaration of char array in test class, compiler gives an error ISO C++ forbids zero size array when I use -pedantic-errors command line option in g++ & /Zaoption in MSVS 2010 compiler it says error C2133: 'test::a' : unknown size. So, my questions are:
1) what is the use of unknown size static array?
2) How do I later specify size of them & access that array elements? I am really getting confused.
3) Why removing static keyword leads to compilation errors?
It would be better if someone would explain it using simple example.
Thanks.

The compiler doesn't care about the size. It's just a declaration for the static field, so telling it you have an array is enough. Size doesn't matter at this point.
You only have a declaration for the static field at this point. You never use those arrays and the compiler is permissive... it won't complain.
If you want to use them however, you'll need a definition. If you omit the size there, you'll get similar error messages you saw before.
There isn't anything special going on.

Related

How to build object using C++ vector library in gcc?

so I have some working code that calls gcc in a makefile. I then add my own class that uses the c++ vector stl, and I want to compile the same object.
If I just run the same command, I get an error:
fatal error: vector: No such file or directory
#include <vector>
If i try to use g++ instead to compile, I instead get a million errors, so I'm guessing that I shouldn't do that.
I googled how to add a c++ library to a gcc call, and I was told to use
gcc -lstdc++
However, that doesn't seem to have any effect. How can i go about building this object?
Would using g++ be the standard way? If I use g++ instead of gcc it seems like there are many conversion errors of this type:
globals.c:1381:50: error: invalid conversion from 'void*' to 'Global*' [-fpermissive]
struct Global *g = calloc(1,sizeof(struct Global)); /* allocate viewer context */
as well as an error of previous declaration:
d:\mingw\include\getopt.h:46:12: error: previous declaration 'int getopt(int, char* const*, const char*)' here
extern int getopt( int, char * const [], const char * );
There are quite a few issues here. First, the "gcc" executable will compile both C and C++ code, but it typically determines whether it should compile as C or C++ based on the file suffix. In your case, it appears to have tried to compile "globals.c" as a C source file instead of a C++ source file. The C compiler does not include the proper directory in the list of internal include paths so it will not even try to open the <vector> include. To compile as C++, you can force it with g++ or by changing the name of your source file to have a .cpp or .C suffix.
If you have more than one source file, then you are going to have more work to do. You will probably either need to compile everything with the C++ compiler, or will need to learn about "extern 'C'" and fix the interfaces between C++ and C. This may be more trouble than it is worth.
Next, you will need to address all of the errors in your compilation. It looks like the main problem you show has to do with typecasts. Those were more permissive under C than C++.
I would suggest that you take out the vector code, and keep using a pure C solution in your case. You have to perform the memory management yourself, but it isn't too hard. I have used realloc() in the past to resize memory. You'll need to keep track of a pointer to the allocated memory, the number of allocated objects and potentially the total size of the buffer.
The first error is because there is no automatic conversion from void * to other pointer types in c++. Which is not the case in c, so the code would compile correctly with a c compilier, to solve that you just need to cast the return value like this
Global *g = reinterpret_cast<Global *>(calloc(1,sizeof(Global)));
also notice that you don't need struct for declarations in c++.
I'd recommend the new operator, because if you add a constructor to struct Global it will automatically invoke the cosntructor, also
Global *g = new Global;
notice however that unlike calloc() the struct members here are not initialized to 0.
The important thing to know is that c and c++ are different languages, you can easily write code that would compile with a c compiler but not with a c++ compiler, like the code above, the other way it's even easier.

Visual Studio 2012 C++ arrays initialization using { }

i've just started programming in visual studio 2012 Express and from the beginning I'm having problems with arrays.
The environment says that this code is invalid:
int a[10] = {5,1,8,9,7, 2,3,11, 20,15};
First of all i had to declare that this array has fixed size using fixed keyword, but after that the program still has been wanting to put ; after a[10]. Filling up this array one number by one would be waste of time. Is it possible to work around it? I can't find any solution in google so I decided to post my problem here.
There's no fixed keyword in C++, perhaps in C#
The code you posted is perfectly valid in VS2012 Ultimate (and probably also Express)
From the above I might conclude you mismatched project and are trying to compile a C++ code in a C# environment.
Another reason that makes me think the above is the following error you get in a C# project if you try to compile the snippet above:
error CS0650: Bad array declarator: To declare a managed array the
rank specifier precedes the variable's identifier. To declare a fixed
size buffer field, use the fixed keyword before the field type.
which refers exactly to the fixed keyword you were trying to use.
Short story: you're trying to compile a C++ code in a C# project. Paste that code in a C++ project, not a C# one. Those are two different languages.
May be its too late to but you can use STL array for fix size arrays as
#include <array>
std::array<int, 5> ary { 1,2,3,4,5 }
This will be a fixed size array
As mentioned by Marco A. there is no "fixed" keyword in C++

Declaring an array using const integer

I was trying to declare an int array in C++ and found this problem. The following code runs fine on g++ compiler but the compilation fails on Visual Studio. I was following Bruce Eckel and found this code.
#include<iostream>
int main()
{
const int j = std::cin.get();
char buf[j];
}
Keeping j just an int would be a problem, that I understand. Since the value of j would be const during the run-time, the program should get compiled. Please correct me if I am wrong anywhere.
Since the value of j would be const during the run-time, the program should get compiled.
No, the const-ness of j is irrelevant here. C++ currently only supports statically-sized C-arrays. Its size must be a compile-time constant.
If you want an array of dynamic size, use std::vector.
The fact that g++ by default compiles this is a bit unfortunate (for compatibility). You should use the -pedantic flag when using g++ to ensure that such compiler extensions aren’t enabled (using compiler extensions of course isn’t bad in itself, but in this case there’s not really any advantage).
You are trying to define buf as a variable-length array. This is a feature of C (not C++) that is supported by g++ as a non-standard extension. Evidently your other compiler does not support it.
I would suggest turning buf into std::vector<char> (or indeed std::string?)
Variable length arrays are C99 feature both gcc and clang supports them as an extension in C++ but Visual Studio never did and even though they recently added support for C99 is it not supported in C++
Since you are developing in C++ unless you have a good reason to not use it then std::vector or std::string should be sufficient.
I had the same problem. It seems very difficult to create an array of which its length is stored as a variable. What I did is create an additional function:
void Class:: initMyArray(const int size) {
myArray = new int[size]
}
Now, you just have to call that function and give it your variable. I'm not sure whether this is a proper solution though (I'm not a C++ expert).

C++11 for xCode errors

I want to use std collections, for example std::vector in my xCode 4.5 project. Following the explanation here no type named 'shared_ptr' in namespace 'std' I changed my compiler options accordingly, but now when I come to build the project I get a bunch of errors such as Type float cannot be narrowed to GLubyte (aka unsigned char) in initializer list.
These errors are in a ccType.h, which is part of the Cocos2d library I'm using for my game.
I'm thinking the right thing to do is not to start debugging Cocos2d, but to change some of the compiler options.
How should I proceed?
Here is the code that causes the errors:
static inline ccColor4B ccc4BFromccc4F(ccColor4F c) {
return (ccColor4B){c.r*255.f, c.g*255.f, c.b*255.f, c.a*255.f};
}
The error message is exactly as I brought it above.
You should cast the type accordingly because C++11 disallow implicit conversion in initialisers lists, specifically in this case from float to unsigned char.
I guess this should be enough to solve the issue:
return (ccColor4B){static_cast<GLubyte>(c.r*255.f), static_cast<GLubyte>(c.g*255.f), static_cast<GLubyte>(c.b*255.f), static_cast<GLubyte>(c.a*255.f)};

Why the size of the object is zero

I am getting the sizeof of object as zero, which is ought not to be. Please explain me the concept as why the compiler is giving this answer?
#include<iostream>
using namespace std;
class xxx{
public: int a[]; // Why this line is not giving error.
};
int main(int argc, char *argv[])
{
xxx x1;
cout<<sizeof(x1); //Q=Why this code is not giving error.
return 0;
}
As the others have said, an object in C++ can never have size 0.
However, since the code isn’t valid C++ in the first place (arrays cannot be empty) this is inconsequential. The compiler just does what it wants.
GCC with -pedantic rejects this code. MSVC at least warns. My version of clang++ with -pedantic ICEs but does emit a warning before that.
You're not using a standard-compliant compiler. An object size can't be 0, even an empty class or struct has size 1. Moreover, the array dimension has to be specified.
EDIT: It's strange, ideone also prints out 0. In MSVS I get a warning, but at least the size is 1.
5.3.3. Sizeof
[...] When applied to a class, the result is the number of bytes in an object of that class [...] The size of a most derived class shall
be greater than zero. [...] The result of applying sizeof to a base class subobject is the size of the base class type. [...]
EDIT 2:
I tried the following in MSVS:
xxx a[100];
and it fails to compile. Strange how it doesn't pick up the error beforehand.
That element a in your class xxx is called a flexible array member.
Flexible array members are not in the C++ standard. They are a part of C99. However, many compiler vendors provide flexible array members as a C++ extension.
Your code as-is is not legal C code. It uses C++ specific constructs. Your code is easy to change to C. Change the class to struct, get rid of the public, and change the use of C++ I/O to C's printf. With those changes, your converted code is still illegal C99 code. Flexible array members are only allowed as the last element of a structure that is otherwise non-empty.
Apparently your vendor took the flexible array member concept over to C++, but not the constraint that the structure be otherwise non-empty.
The size of an object can not be zero. even if the class is empty, its size is never zero.
Checkout the link to know more Bjarne Stroustrup's C++ Style and Technique FAQ.