why does c++ allow constant references to be initialized by a numeric value? - reference

Why does this work in c++? :
const int& a = 5;
A reference is an alias. Ideally, a reference declaration should not result in allocation of memory to any variable. However, try this:
cout<<&a<<endl;
You will get a memory address!
Instead, the following will do the same thing:
const int a = 5;
while being more elegant.
Again, what is the use of such a statement:
const int& a = 5;
? And why is it allowed in c++?

Related

How to assign value to union in VC++

There is an union in C and embedded into C++ as below:
typedef union MyUnion MyUnion_;
union MyUnion{
ULONG mLong;
char mChar;
...
};
When I trying to init it like:
MyUnion_ test;
test = (MyUnion_)NULL;
this is can compile by Mingw32, but gives
error: C2440: 'type cast': cannot convert from 'void *' to 'MyUnion_'
in VC++ (VS2015). So how to do cast & initialize of union in VC++ compiler?
Now I am doing like this:
MyUnion_ test;
test.mLong = NULL;
but this makes the program look bad when passing union as a parameter.
void test(MyUnion_ u)
ULONG i = 0;
// mingw32
test((MyUnion_)i);
// vc++
MyUnion_ temp;
temp.mLong = i;
test(temp);
Using a compiler that supports the C++11 uniform initialization syntax you can use a braced initializer with a single value which will be used to initialize the first non-static field of the union …
MyUnion test{ 0 };
You could use NULL instead of zero in the code above but it seems confusing to initialise mLong (which is a ULONG) with NULL.
You can also use braced initialization in an assignment statement if you have to set the variable after it was declared …
MyUnion test{ 0 };
// ...
test = { 3 };
Note that the braced initializer syntax may also be available in older compilers that offer experimental support for what used to be called C++0x
Visual Studio 2015 C++ supports braced initializers unless you are compiling a file with a .c extension or are using the /TC switch to compile as C code (rather than C++ code).
Older C++ (and C) compilers
When using compilers that don't support braced initialization the older assignment initialization syntax can be used in declarations ...
MyUnion_ test = { 0 };
… but not in assignment statements.
Casting to union type
According to this IBM Knowledge Center article casting to a union type is an extension to C99 "... implemented to facilitate porting programs developed with GNU C" - which suggests it's not standard C.
This Microsoft documentation indicates there are no legal casts in C for a union, struct or array.
In C++ a cast to a union type is possible if a suitable constructor exists...
union MyUnion {
unsigned long mLong;
char mChar;
MyUnion(unsigned long val) { mLong = val; };
};
// valid cast
test = (MyUnion)3ul;
// invalid cast - no suitable constructor exists
void * ptr = 0;
test = (MyUnion)ptr;
Default constructor?
typedef union MyUnion MyUnion_;
union MyUnion {
ULONG mLong;
char mChar;
MyUnion(): mLong(0) {}
};
int main()
{
MyUnion_ temp;
return 0;
}

How can I understand this code (string as a function parameter in c)

I have written this code but its not working but when I replace *targ and *sour by targ[] and sour[] then its working. Also it shows many error when I call the function converge like this converge(*targ, *sour). Please someone help me to understand this.
#include<stdio.h>
#include<string.h>
void converge(char *target, char *src);
int main()
{
char *targ = "xxxxxxxxxxxxxxxxxxx";
char *sour = "yyyyyyyyyyyyyyyyyyy";
converge(targ, sour);
//printf("%s", targ);
}
void converge(char *target, char *src)
{
int i, j;
for(i=0,j=strlen(src); i<=j; i++, j--)
{
target[i]= src[i];
target[j]= src[j];
printf("%s\n",target);
}
}
If you define a string like this:
char *targ = "abcd";
it is treated as read-only value, since the string "abcd" is stored in read-only memory, while the pointer targ is stored on your stack. Depending on your compiler you might get some warning unless you make this more explicit with const char *targ = "abcd";. An assignment like targ[i] = src[i]; is not allowed in this case.
If you define a string like this:
char targ[] = "abcd";
a char-array will be created on your data stack, this string can be changed, since data on your stack is readable and writable. Additionally you can access the first element of your array as pointer.

Error: this declaration has no storage class or type specifier ( Me making a simple struct. )

I was trying to make a simple struct to hold character stats.
This is what I came up with:
struct cStats
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
};
cStats mainchar;
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;
The mainchar. part is underlined red in visual studio, and when I mouse over it it shows this:
Error: this declaration has no storage class or type specifier
Any explanation of why it's doing this, and what I should be doing to fix it would be appreciated.
If this is C you should tag your question as such. cStats is a structure tag, not a type specifier. You need to declare mainchar as:
struct cStats mainchar;
If you wanted to use cStats as a type specifier you would define it as:
typedef struct
{
int nStrength;
int nIntelligence;
int nMedical;
int nSpeech;
int nAim;
} cStats;
If you did that your cStats mainchar would work.
Note that in C, char and character mean “ASCII alphanumeric character”, not “character in a play or game”. I suggest coming up with a different term for your program.
Another bit of advice; do not prefix your names with their data type; like nStrength for integer Strength. The compiler will tell you if you get your data types wrong, and if you ever need to change a type, for example to float nStrength to handle fractional Strengths, changing the name will be a big problem.
main(){
mainchar.nStrength = 10;
mainchar.nIntelligence = 10;
mainchar.nMedical = 10;
mainchar.nSpeech = 10;
mainchar.nAim = 10;}
These initialization should be written within the main() function.
Or else, write a init function and call it from main function.

C++/CX: Why doesn't returning a StringReference work like passing one as an argument?

Platform::StringReference exists so that you can pass a const wchar_t* across the ABI boundary to a function accepting a String^ without making a copy. The StringReference implicitly converts to a String^ whose internal pointer matches the original const wchar_t*. This is verified by the following code; if you step through it you find that pz == z:
void param(String^ s)
{
const wchar_t* z = s->Data();
}
App::App()
{
std::wstring p = L"abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz";
const wchar_t* pz = p.c_str();
param(StringReference(pz));
}
However, trying to return a StringReference doesn't seem to work the same way and I'm curious why. If I have a function that returns String^ and I return a StringReference from it then the same implicit conversion operator is called, but when the caller gets their String^ it has a different internal data pointer that contains a copy. Here's some code that tries it:
String^ ret()
{
std::wstring s = L"12345678901234567890123456789012345678901234567890";
const wchar_t* z = s.c_str();
return StringReference(z);
}
App::App()
{
String^ r = ret();
const wchar_t* rz = r->Data();
}
That code verifies in two ways: first, if you step through you'll find that z != rz and second, r ends up pointing to a valid string rather than garbage, so a copy must have been made because the original string is freed at the end of ret.
I also tried returning via out parameter, but I get the same results as a straight return (z != oz and o ends up with a valid string):
void out(String^* r)
{
std::wstring s = L"12345678901234567890123456789012345678901234567890";
const wchar_t* z = s.c_str();
*r = StringReference(z);
}
App::App()
{
String^ o;
out(&o);
const wchar_t* oz = o->Data();
}
Is there a way to return a StringReference across the ABI boundary in the same way that you can pass one? I imagine the behavior would depend on the language of the caller and how that language marshals strings from WinRT, but it seems like at least a C++/CX caller ought to be able to do it.
No you can't return a StringReference across the ABI boundary. Returning a StringReference across the ABI boundary is similar (but not identical) to returning the address of a local variable. That's because the whole point of a StringReference is that the StringReference doesn't allocate any new memory.
Consider what would happen if you could return a StringReference across the ABI boundary. What would happen if you had:
String^ ReturnAString()
{
const wchar_t buffer[500] = "MyString";
return StringReference(buffer);
}
The StringReference is just a wrapper around the stack allocated buffer. And clearly you can't return that across the ABI boundary (the stack storage is reclaimed as soon as the routine exits).
Instead you need to return a real Platform::String - a Platform::String contains a copy of the string data and thus it can safely be returned to the caller.

allocating enough memory using typedef struct object whose size varies in another typedef struct

I have defined two typedef structs, and the second has the first as an object:
typedef struct
{
int numFeatures;
float* levelNums;
} Symbol;
typedef struct
{
int numSymbols;
Symbol* symbols;
} Data_Set;
I then defined numFeatures and numSymbols and allocate memory for both symbols and levelNums, then fill levelNums inside a for loop with value of the inner loop index just to verify it is working as expected.
Data_Set lung_cancer;
lung_cancer.numSymbols = 5;
lung_cancer.symbols = (Symbol*)malloc( lung_cancer.numSymbols * sizeof( Symbol ) );
lung_cancer.symbols->numFeatures = 3;
lung_cancer.symbols->levelNums = (float*)malloc( lung_cancer.symbols->numFeatures * sizeof( float ) );
for(int symbol = 0; symbol < lung_cancer.numSymbols; symbol++ )
for( int feature = 0; feature < lung_cancer.symbols->numFeatures; feature++ )
*(lung_cancer.symbols->levelNums + symbol * lung_cancer.symbols->numFeatures + feature ) = feature;
for(int symbol = 0; symbol < lung_cancer.numSymbols; symbol++ )
for( int feature = 0; feature < lung_cancer.symbols->numFeatures; feature++ )
cout << *(lung_cancer.symbols->levelNums + symbol * lung_cancer.symbols->numFeatures + feature ) << endl;
return 0;
When levelNums are int I get what I expect( i.e. 0,1,2,0,1,2,...) but when they are float, only the first 3 are correct and the remaining are very small or very large values, not 0,1,2 like expected. I then have two questions:
When allocating memory for symbols, how does it know how big a Symbol is since I have not yet defined how large levelNums will be yet.
How do I get float values into levelNums correctly.
The reason I am doing it like this is this is a data structure that will be sent to a GPU for GPGPU programming in CUDA and arrays are not recognized. I can only send in a continuous block of memory explicitly and the typedef structs are only there for conveying/defining the memory struture of the data.
A couple thing jump out at meet. For one thing, you only allocated a buffer for levelNums of the first symbol. Similarly, your inner loops always loop over the numFeatures of the first symbol.
You're doing a whole lot of dereferencing of arrays, which is fine in general, but the assignment in particular (inside the first set of loops) looks very strange. It's entirely possible I just don't understand what you're trying to do there, but I think it'd be a lot less confusing if you used some square bracket array accessors.

Resources