Why is this code returning -1?
memcmp() compares block of memory and takes 3 parameters in constructor but what happens when I miss the third parameter?
int main()
{
char ptr[] = "hello";
char ptr1[] = "hello";
int a = memcmp(ptr,ptr1);
printf("%d",a);
return 0;
}
Also the following program abruptly terminates without the third parameter:
int main()
{
char *ptr = "hello";
char *ptr1 = "hello";
int a = memcmp(ptr,ptr1);
printf("%d",a);
return 0;
}
For starters, memcmp() takes three arguments: the pointers to the memory segments to be compared and the size. Although the code may compile in C (I don't think it should) it certainly doesn't compile using C++. If the code compiled, the third argument is a pretty random value and it is unlikely that the memory after these strings is the same.
It will compile neither in C nor in C++. In C, first one does compile only when you do not include <stdlib.h> and it simply invokes undefined behavior because passing arguments to a function less than that of its parameter invokes UB.
Here is the output:
Related
So i recently stumbled on this code somewhere where it is copying one string to another using just one line of code with the help of a while loop , however , I am not able to understand as to how and why it happens-:
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = -1;
while(arr2[i] = arr1[++i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
Can somebody explain me what is happening in the backdrop?
and moreover if the above code works fine then why dont the below ones?
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = 0;
while(arr2[i++] = arr1[i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
another one-:
int main()
{
char arr1[100];
cin.getline(arr1 , 100);
char arr2[100];
int i = 0;
while(arr2[++i] = arr1[i]);
cout<<arr1<<endl<<arr2<<endl;
return 0;
}
The code snippet is relying on an order-of-evaluation guarantee that was added in C++17.
Since C++17 it is guaranteed that the right-hand side of a = operator is evaluated first. As a consequence the loop is equivalent to
int i = -1;
while(true) {
i++;
arr2[i] = arr1[i];
if(!arr2[i])
break;
};
Except that one would normally start at i = 0; and put i++; at the end of the loop iteration, I think it should be clearer what is happening now. The loop breaks when a null character is encountered, so it expects that arr1 is a null-terminated string and won't copy the whole array.
Before C++17 the order of evaluation was not specified and the code had undefined behavior as a consequence.
If you change the loop to int i=0; while(arr2[++i] = arr1[i]);, then (since C++17) you execute ++i only after indexing arr1[i], but before indexing arr2. As a consequence you are not copying to the beginning of arr2. Again, before C++17 this is undefined behavior.
int i=0; while(arr2[i++] = arr1[i]); should work correctly since C++17 as well. It does the increment only after indexing both arrays. Again, before C++17 it has undefined behavior.
You shouldn't use either of these, since they are hard to reason about and have undefined behavior if the user happens to set the C++ version switch to something before C++17 or tries to use it in C, where it is undefined behavior in all versions.
Also int may be too small to hold all indices of a string. Prefer std::size_t (which however is unsigned and so the first variant won't work).
Utilities for things like copying strings should be written in functions, not inline every place they're used. That makes it simpler to avoid the complexities of incrementing the same variable twice:
void copy_string(char* dest, const char *src) {
while (*dest++ = *src++)
;
}
Yes, I know, some people like to have their compiler ignore the rules and refuse to compile valid, well-defined code like this. If your compiler is set that way, figure out how to rewrite that code to make your compiler happy, and perhaps think about who's the boss: you or your compiler.
I was messing around with memory allocation. I was testing to see that, like Java, this program with give an exception.
int main() {
int* a = nullptr;
int b = *a;
std::cout << b;
}
Which indeed it does. Then I tested using malloc as a pointer to a, but not initializing a.
int main() {
int* a = (int*) malloc(sizeof(int));
int b = *a;
std::cout << b;
}
However, instead of throwing an exception, it prints out a seemingly random number in -842150451. I even tried replacing int with long:
int main() {
long* a = (long*) malloc(sizeof(long));
long b = *a;
std::cout << b;
}
However I got the same result. Then I tried it with short:
int main() {
short* a = (short*) malloc(sizeof(short));
short b = *a;
std::cout << b;
}
Then instead of the previous result, I got -12851. And it continued like this for every primitive type I could think of. What I want to know is, where are these numbers coming from and why these numbers specifically?
-842150451 is the two's complement representation of the value 0xCDCDCDCD, which is a common Visual Studio debugger value for heap-allocated uninitialized memory.
Uninitialized variables or memory have indeterminate values from the C++ specifications perspective, and using such values lead to undefined behavior. If you remember this, and always initialize such values or memory then you'll be alright.
All of your erroroneous programs have what's technically called undefined behaviour. Which means the behaviour of the program is unconstrained by the C++ standard, and therefore it's wrong to expect any particular outcome when you run your code.
C++ is quite unlike Java in this regard which specifies precise behaviours for most situations.
I am trying to print the following using the code as:
int main() {
char p[] = "hello";
char*t = p;
char**b = &t;
std::string s = b[0];
cout<<"string="<<s<<" b[0]="<<b[0];
}
The output I get is as expected:
string=hello b[0]=hello
Now the same thing I want to achieve using a function call in which I pass a variable by reference as:
void func(char**& p) {
char *k = (char*)malloc(8*sizeof(char));
k = (char*)"abc";
p = &k;
}
int main() {
char**j = NULL;
func(j);
std::string s1 = j[0];
cout<<s1;
}
Now I am getting a null string. What could be the reason and how to solve it ?
You have (at least) two problems:
The first is that you make p point to the local variable k.
The second is more subtle, and is that you reassign k losing the original memory you allocated and make k point to.
Then the usual spiel about never using arrays of char or pointers to char for strings, when you have std::string. And that you should never use malloc in C++, only new or new[]. And if you need new[] consider using std::vector instead (except for strings of course).
There is NO WAY to write code like this that follows any sort of standards of good programming. If you are serious about learning how to program you should abandon this mess and rewrite your code to do things the correct way. This is sort of mess is never necessary, even when interfacing with legacy code.
However the following 'works'
void func(char**& p) {
p = new char*;
*p = new char[8];
strcpy(*p, "abc");
}
And take note, I didn't need to use a cast.
When I tried below code I got strange results.I am trying to change value of constant by using the pointers.But when I output the results pointer value and the original variable variable value its giving two different values.Can anyone explain what exactly happens when explicit conversion take place?
int main()
{
int *p ;
const int a = 20;
p=(int *)&a;
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
output:
p is 30
a is 20
Both C and C++ say that any attempt to modify an object declared with the const qualifier results in undefined behavior.
So as a is object is const qualified, the *p = *p +10; statement invokes undefined behavior.
First of - You really shouldn't be doing this. const is a constant, meaning don't change it! :)
Now to explain what happens (I think):
The space on the stack is allocated for both variables, p and a. This is done for a because it has been referenced by an address. If you removed p, you'd effectively remove a as well.
The number 20 is indeed written to the a variable, and modified to 30 via p, which is what is being printed.
The 20 printed is calculated at compile time. Since it is a const, the compiler optimized it away and replaced with 20, as if you did a #define a 20.
Don't Do That.
If you would write this code in C++ with an explicit cast, you would get something like this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a); // the change
*p = *p +10;
cout<<"p is"<<*p<<"\na is"<<a;
}
Now, this code tells a bit more about what's going on: the constant is cast to a non-constant.
If you are writing a compiler, constants are special variables that are allowed to be 'folded' in the const folding phase. Basically this means that the compiler is allowed to change your code into this:
int main()
{
int *p ;
const int a = 20;
p= const_cast<int*>(&a);
*p = *p +10;
cout<<"p is"<<*p<<"\na is" << 20; // const fold
}
Because you're also using &a, you tell the compiler to put the value 20 in a memory location. Combined with the above, you get the exact results you describe.
This is undefined behavior.
A compiler can assume that nothing is going to change the value of a const object. The compiler knows that the value of "a" is 20. You told the compiler that. So, the compiler actually goes ahead and simply compiles the equivalent of
cout << "p is" << *p << "\na is" << 20;
Your compiler should've also given you a big fat warning, about "casting away const-ness", or something along the same lines, when it tried to compile your code.
Although it is defined as undefined behaviour (as everyone else tells you), it could be that your compiler has allocated a storage location (int) for the const int; that is why the *p= *p + 10 works, but may have repaced a in the output statement with the value 20, as it is supposed to be constant.
Let's say I have a macro called LengthOf(array):
sizeof array / sizeof array[0]
When I make a new array of size 23, shouldn't I get 23 back for LengthOf?
WCHAR* str = new WCHAR[23];
str[22] = '\0';
size_t len = LengthOf(str); // len == 4
Why does len == 4?
UPDATE: I made a typo, it's a WCHAR*, not a WCHAR**.
Because str here is a pointer to a pointer, not an array.
This is one of the fine differences between pointers and arrays: in this case, your pointer is on the stack, pointing to the array of 23 characters that has been allocated elsewhere (presumably the heap).
WCHAR** str = new WCHAR[23];
First of all, this shouldn't even compile -- it tries to assign a pointer to WCHAR to a pointer to pointer to WCHAR. The compiler should reject the code based on this mismatch.
Second, one of the known shortcomings of the sizeof(array)/sizeof(array[0]) macro is that it can and will fail completely when applied to a pointer instead of a real array. In C++, you can use a template to get code like this rejected:
#include <iostream>
template <class T, size_t N>
size_t size(T (&x)[N]) {
return N;
}
int main() {
int a[4];
int *b;
b = ::new int[20];
std::cout << size(a); // compiles and prints '4'
// std::cout << size(b); // uncomment this, and the code won't compile.
return 0;
}
As others have pointed out, the macro fails to work properly if a pointer is passed to it instead of an actual array. Unfortunately, because pointers and arrays evaluate similarly in most expressions, the compiler isn't able to let you know there's a problem unless you make you macro somewhat more complex.
For a C++ version of the macro that's typesafe (will generate an error if you pass a pointer rather than an array type), see:
Compile time sizeof_array without using a macro
It wouldn't exactly 'fix' your problem, but it would let you know that you're doing something wrong.
For a macro that works in C and is somewhat safer (many pointers will diagnose as an error, but some will pass through without error - including yours, unfortunately):
Is there a standard function in C that would return the length of an array?
Of course, using the power of #ifdef __cplusplus you can have both in a general purpose header and have the compiler select the safer one for C++ builds and the C-compatible one when C++ isn't in effect.
The problem is that the sizeof operator checks the size of it's argument. The argument passed in your sample code is WCHAR*. So, the sizeof(WCHAR*) is 4. If you had an array, such as WCHAR foo[23], and took sizeof(foo), the type passed is WCHAR[23], essentially, and would yield sizeof(WCHAR) * 23. Effectively at compile type WCHAR* and WCHAR[23] are different types, and while you and I can see that the result of new WCHAR[23] is functionally equivalent to WCHAR[23], in actuality, the return type is WCHAR*, with absolutely no size information.
As a corellary, since sizeof(new WCHAR[23]) equals 4 on your platform, you're obviously dealing with an architecture where a pointer is 4 bytes. If you built this on an x64 platform, you'd find that sizeof(new WCHAR[23]) will return 8.
You wrote:
WCHAR* str = new WCHAR[23];
if 23 is meant to be a static value, (not variable in the entire life of your program) it's better use #define or const than just hardcoding 23.
#define STR_LENGTH 23
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = (size_t) STR_LENGTH;
or C++ version
const int STR_LENGTH = 23;
WCHAR* str = new WCHAR[STR_LENGTH];
size_t len = static_cast<size_t>(STR_LENGTH);