Passing reference to char pointer is resulting in an error - c++

I am trying to pass a char & value to a char * argument in a function, but it's not working as shown below:
#include <iostream>
using namespace std;
void change_sugar(const short& sugars, char* LOC);
int main()
{
static int caga = 0;
const short* mysweets;
char& lala;
change_sugar(mysweets, lala);
}
void change_sugar(const short& sugars, char** LOC[])
{
if (sugars == 3000)
LOC[1] = 5;
cout << "Sugar is not nCaga, nor caga" << " ___ !#S ";
cerr << "nCaga failed!";
}
Error output:
error: 'lala' declared as reference but not initialized
I am trying to pass a reference to a pointer of the same type. Is this correct?
Bear with me, I am new to C++, and I think I read the tutorial on pointers and references correctly.
EXTRA: I tried this with a different compiler, Turbo 16, I think, and it threw like ten other errors, so I don't know if it's a compiler problem or not.

In C++ a reference must always be valid (and not "dangling"), so you have to initalize it when creating it.
I am not sure what you wanted to do with your lala, but a proper usage of a reference variable is like so:
char a;
char & b = a; // has to be initialized here
Now you can use b wherever a variable of type char is meant to be used. However, your function wants char * as its second parameter.
Thus, after initializing the reference, you could still use its address to make it fit: &lala.
Also your definition and declaration is mismatched.

There are lots of things wrong with your code.
A reference and a pointer are not the same thing in the C++ language, although they are implemented the same way in the compiled machine code. You cannot pass a reference where a pointer is expected, and vice versa. You are trying to pass a short* where a short& is expected, and a char& where a char* is expected.
A reference can never be uninitialized (hense the compiler error), but a pointer can be uninitialized.
The parameters in your change_sugar() declaration do not match the parameters in the definition. In C++, they must match.
It is very unclear what change_sugar() is actually trying to do. Clearly, you want to alter the char that is passed in, but char is only 1 byte in size and you are trying to alter memory past the 1-byte boundary of the data being altered.
Try this instead:
#include <iostream>
using namespace std;
void change_sugar(const short& sugars, char* LOC);
int main()
{
short mysweets = 3000;
char lala = 0;
change_sugar(mysweets, &lala);
}
void change_sugar(const short& sugars, char* LOC)
{
if ((LOC) && (sugars == 3000))
*LOC = 5;
cout << "Sugar is not nCaga, nor caga" << " ___ !#S ";
cerr << "nCaga failed!";
}
Or this:
#include <iostream>
using namespace std;
void change_sugar(const short& sugars, char& LOC);
int main()
{
short mysweets = 3000;
char lala = 0;
change_sugar(mysweets, lala);
}
void change_sugar(const short& sugars, char& LOC)
{
if (sugars == 3000)
LOC = 5;
cout << "Sugar is not nCaga, nor caga" << " ___ !#S ";
cerr << "nCaga failed!";
}

There's a very simple paradigm for passing variables to methods wanting pointers:
void clear(char *p) { *p = '\0'; }
char c = 'a';
clear(&c); // after this call c == '\0'
Are you actually looking for something more advanced here?
Reference variables:
char &r = c;
Are actually pretty complicated. (And would still be passed with &r)

There are a lot of things that bothers me with the code so I'll go through some them.
1: Your prototype does not match.
Change
void change_sugar(const short& sugars, char** LOC[])
to
void change_sugar(const short& sugars, char* LOC)
or the other way around depending on what you actually want to do.
2. Your pointer is not initialized.
const short* mysweets is not initialized. Allocate some memory for it.
const short* mysweets = malloc(sizeof(short));
then
*mysweets = 3000;
3. lala is not a pointer.
If you want to pass the address of lala to your function, change_sugar, initialize it as so
char* lala = malloc(sizeof(char));
and pass it as
change_sugar(mysweets, lala);
If you don't want it to be a pointer but still want to pass by reference, declare it as so
char lala;
and pass it as
change_sugar(mysweets, &lala);
Finally:
Your code is very confusing to read and to figure out what you actually want to do. I suggest to step back and think about what you want to achieve and redesign your code.

Related

Pass non const char * in to const char *& argument of a function

I want to pass strings to a function but save the cost of
copying the pointer on the function's stack to improve performance.
I am aware of the multithreading hazards of manipulating const-ness.
One thing is to use &arr[idx] (char array) as a pointer to pass to
void func( const char*& charArrItemRef).
Compiler complains it can't bind the reference to function arg.
how can I manipulate the build to allow it?
I tried to first forcefully cast a char* to const char*, store it in a variable and then pass that variable to your func. Note that it has to be stored in a variable since you are passing the pointer as a reference. Hope this is what you were looking for:
#include <iostream>
using namespace std;
void func(const char* &charArrItemRef)
{
cout << charArrItemRef << endl;
}
int main()
{
char* a[5] = {(char*)"abc", (char*)"def", (char*)"sss", (char*)"dasds", (char*)"aad"};
const char* c = reinterpret_cast<const char*>(a[0]);
func(c);
// EDIT:
char b[10] = "abcdefghi";
const char* d = &b[3];
func(d);
return 0;
}

Win32 DLL Not Returning correct data

I'm very new to C++ programming. I have a 3rd party app that can utilize Win32 DLLs. The test project I'm working on compiles without error, but in use doesn't seem to actually return the expected data.
With the below function Foo, the expectation is that the char array that is passed in will return the same values.
Instead, regardless of the data passed in my 3rd party app only sees the return value: 0
My suspicion is that I am not using the pointer 'char *data_out' correctly.
DemoLib.h:
#pragma once
#define DLL_EXP extern "C" __declspec(dllexport)
DLL_EXP void Foo(char* data_in, char *data_out);
DemoLib.cpp:
#include "stdafx.h"
#include "DemoLib.h"
#include <iostream>
DLL_EXP void Foo(char* data_in, char *data_out)
{
int a_size = sizeof(data_in) / sizeof(char);
std::string s_a = convertToString(data_in, a_size);
char strArray[100];
strcpy_s(strArray, s_a.c_str());
data_out = strArray;
}
std::string convertToString(char* a, int size)
{
int i;
std::string s = "";
for (i = 0; i < size; i++) {
s = s + a[i];
}
return s;
}
Exports.def:
LIBRARY DemoLib
EXPORTS
Foo #1
There are a couple of problems in your code. First, the line:
int a_size = sizeof(data_in) / sizeof(char);
will not give you the length of the data_in string! Rather, it will give you a (fixed) value that is the size of a pointer divided by the size of a char. So, assuming you have a C-style, null-terminated string, use this:
int a_size = int(strlen(data_in));
Second, your line:
data_out = strArray;
does not copy the string data from strArray to data_out! Rather, it simply replaces the pointer value (address) that data_out holds with the address of the (local) strArray array. (However, this will not change the value of any pointer in the calling module.)
What you need to do, here, is actually copy the data directly from the std::string into the string pointed to by the data_out argument (assuming it is a big enough buffer).
With these changes in mind, your Foo function could look like this:
DLL_EXP void Foo(char* data_in, char *data_out)
{
int a_size = int(strlen(data_in)); // Note: "strlen" returns a "size_t" (unsigned) type
std::string s_a = convertToString(data_in, a_size);
strcpy(data_out, s_a.c_str());
}
Alternatively, if you actually want the function to return a pointer to some local data, then you will: (a) need to declare that local data static; and (b) make the corresponding argument a pointer-to-pointer:
DLL_EXP void Foo(char* data_in, char** data_out)
{
int a_size = int(strlen(data_in)); // Note: "strlen" returns a "size_t" (unsigned) type
std::string s_a = convertToString(data_in, a_size);
static char strArray[100];
strcpy(strArray, s_a.c_str());
*data_out = strArray;
}

Modifying pointer to string literal in separate function

I have what is hopefully a trivial question that someone can explain to me in simpler terms than what I have already come across. While working through
A Tour of C++ (Second Edition)
I've been trying a few examples.
I'm currently trying to modify a pointer to a string literal in a separate function (I thought it would be easy.....).
using namespace std;
void test(char *ptr)
{
ptr = "test";
}
int main()
{
char *p = "abc";
test(p);
cout << p << "\n";
return 0;
}
When using g++ to compile, I get a
Warning: ISO C++ forbids converting a string constant to char*
Apparently g++ is auto-converting *p to a const? Surely I'm missing something basic, but my previous SO and google searches have gotten me no closer to the answer. Thank you for your responses!
EDIT:
Both great examples below. Thank you everyone for your responses, very helpful!
Apparently g++ is auto-converting *p to a const?
Quite the opposite. The string "abc" will be in your binary, and that is supposed to be readonly for your program. Therefore, that string should only be read, and the value you get when assigning the string literal in this situation is of type const char*. You get the error because you're assigning it to a non-const char*. Try this instead:
const char *p = "abc";
Also, you'll have to change the function, too:
void test(const char *ptr)
{
ptr = "test";
}
It's still going to print abc, however. That's because you're only modifying a copy of the value that you're passing. But C++ lets you pass a reference instead, which you can do like this:
void test(const char *&ptr)
{
ptr = "test";
}
Now that's a reference to a pointer pointing to a const char... whew! Both the "abc" and "test" will be in the program's binary when it is compiled. When the program is run, the address of "abc" is assigned to char *p, and then the function to change it to have the address of "test" instead is called. The & tells it to work with the actual char *p and not just a copy of it that gets lost when the function finishes.
There are two things that can be const; the pointer (char * const), or the object (const char *).
The string literal is const, that's what the compiler is complaining about. You should use
const char *p = "abc";
The function would still not modify the pointer p from main() though, because it is passed by value to the function.
This should modify the pointer:
using namespace std;
const char * str2 = "test";
void test(const char *& ptr)
{
ptr = str2;
}
int main()
{
const char *p = "abc";
test(p);
cout << p << "\n";
return 0;
}
live demo

Compilation error while passing double pointer in cpp

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x)
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str);
cout << str << endl;
return 0;
}
Please tell me why this program is giving compilation Error.I am using the g++ compiler
Error :temp1.cpp:16:8: error: cannot convert ‘char (*)[6]’ to ‘char**’ for
argument ‘1’ to ‘void f(char**)’
Arrays can be implicitly converted to pointers, but that doesn't mean that the implicit "pointer equivalent" already exists.
You are hoping that f(&str); will implicitly create both a pointer to str and a pointer to that pointer.
This small (working) change illustrates this point:
int main()
{
char str[]="hello";
char *pstr = str; // Now the pointer extists...
f(&pstr); // ...and can have an address
cout << str << endl;
return 0;
}
You are passing pointer of constant char to the function but in function you are taking it as pointer of pointers. That is the problem. I commented out below where the problem lies.
[Off topic but N. B. : Arrays and pointers are different concept.]
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
void f(char **x) //**x is pointer of pointer
{
(*x)++;
**x = 'a';
}
int main()
{
char str[]="hello";
f(&str); //You are passing pointer of constant char.
cout << str << endl;
return 0;
}
You're going to run into a serious problem with your function f since &str and &str[0] both evaluate to the same value ... as other posters have pointed out, these operations point to different types, but the actual pointer r-value will be the same. Thus in f when you attempt to double-dereference the char** pointer x, you're going to get a segfault even if you attempted something like a cast to massage the type differences and allow compilation to happen with errors. This is because you are never getting a pointer-to-pointer ... the fact that &str and &str[0] evaluate to the same pointer value means that a double-dereference acually attempts to use the char value in str[0] as a pointer value, which won't work.
Your problem is that you're treating arrays as pointers, when they're not. Arrays decay into pointers, and in this case, it doesn't. What you're passing in is a char (*)[6] when it expects a char **. Those are obviously not the same.
Change your parameter to char (*x)[6] (or use a template with a size parameter):
template <std::size_t N>
void f(char (*x)[N])
Once inside, you try to increment what x is pointing to. You can't increment an array, so use an actual pointer instead:
char *p = *x;
p++;
*p = 'a';
All put together, (sample)
template <std::size_t N>
void f(char(*x)[N])
{
if (N < 2) //so we don't run out of bounds
return;
char *p = *x;
p++;
*p = 'a';
}

strcmp confusion

To my knowledge the standard strcmp function looks something like this:
int strcmp(const char* string1, const char* string2)
{
while(*pString1++ == *pString2++)
{
if(*pString1 == 0) return 0;
}
return *pString1 - pString2;
}
My question is that wouldn't this increment the pointers passed into strcmp? In the following example it seems like it would trash the pointers and cause invalid stuff to happen.
const char* string1 = "blah";
const char* string2 = "blah";
const char* string3 = "blah";
if(strcmp(string1, string2) {doSomething();}
// Won't this make string1 = "" because it incremented the pointer to the end?
else if (strcmp(string1, string3) {doSomethingElse();}
Sorry I'm just confused because it seems like if I pass a pointer into strcmp, I shouldn't expect that pointer to suddenly hold an empty string. It seems like strcmp should take const char* const. Am I totally misunderstanding something?
Your misunderstanding is this: Arguments are passed by value (copy), but you seem to think they are passed by reference.
You could get your expected behaviour by declaring the parameters to strcmp as references, like this:
int strcmp(const char*& string1, const char*& string2)
No, the pointers string1 and string2 are local to the function (passed by value). Any changes made to them are not visible to the caller.
The pointer itself is passed by value, so although it's a pointer to something, changing it does change the local declaration only.
To be able to modify the pointer itself from the inner scope of the function you would need to have a pointer to pointer to char.
The pointers are passed by value, strcmp is using copies of the ones you send in, so the original ones aren't touched.
First, the classical obfuscated implementation of strcmp is even
simpler:
int
strcmp(char const* s1, char const* s2)
{
while ( *s1 ++ == *s2 ++ )
;
return *s1 - *s2;
}
(I would hope that no one would actually write code like this in
practice.)
As for your actual question: C++ (and C, since this is really a C
question) pass arguments by value, so any pointer that strcmp gets is
a copy; it can't possibly modify any of the pointers in the calling
code. All making the parameters char const* const would mean is that
strcmp couldn't modify its local copies of the pointers.
C++ passed parameters to functions "by value". Consider this code:
void f(int i) { i = 7; }
...
int j = 0;
f(j);
assert(j == 0);
The variable j is unrelated to the variable i. Indeed, i local to the function f. It is initialized with a copy of of j. Changes to i are never communicated to j.
Now consider this code:
void f(char *i) { i = i + 1; }
...
char *j = "Hello";
f(j);
assert(*j == 'H');
Similarly, i is initialized with a copy of j. Changes to i are never communicated back to j.
Note: One can force parameters to be initialized "by reference" thusly:
void f(int& i) { i = 7; }
...
int j = 3;
f(j);
assert(j==7);
In this case, rather than being initialized with a copy of j, i is bound to a j. But this only applies if you have & in the declaration.
Try this, your will find that they are totally different pointer.
What cause you misunderstand is that they point to the same area
#include <iostream>
using namespace std;
int strcmp2(char const *s1, char const *s2)
{
cout << "In strcmp" << endl;
cout << &s1 << " " << &s2 << endl;
cout << endl;
}
int main()
{
char a[100];
char b[100];
cout << "In main function" << endl;
cout << &a << " " << &b << endl;
cout << endl;
strcmp2(a, b);
}