#include <stdio.h>
#include <string.h>
#include <conio.h>
#include <iostream>
using namespace std;
char a[21]; // If this is put inside the function unter -> junk output
char* b="";
void unter()
{
char *new_str = "";
strcpy(a, new_str);
char str_temp[10]="";
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
sprintf(str_temp,"%d",chnum);
b = strcat(a, str_temp);
b = strcat(b, "_from");
sprintf(str_temp,"%d",mynode);
b = strcat(b, str_temp);
b = strcat(b, "to");
sprintf(str_temp,"%d",neighbor1);
b = strcat(b, str_temp);
}
int main()
{
unter();
cout << a;
cout << b;
std::cin.get();
}
This is my code in C++. I'm not sure how the character array 'a' also has the same values as 'b'. And moreover, when I declare 'a'
char a[21];
inside function unter(), I'm getting some junk value for 'b'(as output). Care to explain how?
a is a char array and b is a pointer that points to a, so when printing them, they always print the same thing. When you move the declaration for a into unter, it is destroyed when unter returns, leaving b a dnagling pointer, so you get garbage when you print it.
b = strcat(a, str_temp);
is probably what's causing your issue, since the return value from strcat() is the first parameter that was passed to it, hence why you're seeing a and b becoming equal, since b is getting set to a in that call.
strcat() returns the result of the concatenation operation, so
b = strcat(a, str_temp);
results in b pointing to the array a[]. The subsequent strcat() operations effectively do the same, so the end result is that b points to a[] as you observe. If you declare a[] inside unter() it will have local scope to that function, with the result that the global variable b will point to random/undefined memory contents after you exit the call to unter().
It's mildly worth noting that you're doing a lot of work that could be accomplished more easily with
sprintf(a, "%d_from%dto%d", chnum, mynode, neighbor1);
You can do the whole concatenation and sprintf's in a single line.
char* b="";
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(str_temp,"%d_from%dto%d", chnum, mynode, neighbor1);
b = new char[strlen(str_temp)+1];
b = strcpy(b, str_temp);
}
Only funny thing is you must remember to delete b when you are done. The other option is using the a buffer and sprintf directly to it:
char a[21];
void unter()
{
int chnum =0, neighbor1=3, neighbor2=5, mynode=4;
char str_temp[21];
sprintf(a,"%d_from%dto%d", chnum, mynode, neighbor1);
}
When you define a inside the function, memory for the variable a is allocated on stack. This memory is destroyed when the function exits. Your pointer b is pointing to starting address of a. Now, if you try to access b outside the function, it is pointing to a memory location which is already destructed and contain garbage values. Basically, b becomes a dangling pointer.
If you declare a inside the unter() function, then it is only scoped inside that function. Attempt to print b from outside the function will print junk since it is pointing to a which is already destroyed.
This is a classic example of why you should always make sure to not to point to a local variable from a global one.
In addition to the other hints provided, you should take notice of the line
b = strcat(b, str_temp);
which seems rather inappropriate for b is merely defined as a char pointer to a single byte storage ("" defines an empty string, i.e. an array of chars with a single element containing '\0')
So when strcat appends to b, it creates a buffer overrun.
Edit:Actually I just noticed that b was assigned to point to a, (thanks to the line preceding the one mentionned) so that would then be ok, since a may have the room for this... It doesn't make sense however, to need the two variables.
Maybe what you do not understand, is that although strcat() returns a pointer, this return doesn't need to be "consumed", it is merely a convenience, for when we chain commands an such. In other words you can simply write:
strcat(a, str_temp);
Not requiring any char * b.
Related
Here is my program :
#include <cstring>
const int SIZE =10;
int main()
{
char aName [SIZE]; // creates an array on the stack
std::strcpy(aName, "Mary");
return 0;
}
This program is obviously useless, I am just trying to understand the behavior of the strcpy function.
Here is it's signature :
char * strcpy ( char * destination, const char * source )
so when I do :
std::strcpy(aName, "Mary");
I am passing by value the variable aName. I know that the aName (in the main) contains the address of the array.
So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?
I am asking this because it is very confusing to me. Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...
Thanks!
Whenever you encounter addresses it doesn't mean it will always point to memory allocated to heap.
You can assign the address of a variable to a pointer like this
int a=5;
int *myPtr= &a;
Now, myPtr is a pointer of type integer which points to the memory of variable which is created on stack which is a have value 5.
So, whenever you create a pointer and assign the (address of) memory using new keyword, it will allocate the memory on heap. So, if I assign the value like this it will be on stack
int *myPtr= new int[5];
So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?
Yes.
Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...
Yep, usually. But not always.
Pointers to non-dynamically-allocated things are fairly rare in C++, though in C it's more common as that's the only way to have "out arguments" (C does not have references).
strcpy is a function from C's standard library.
Maybe it would help to look at an example implementation of strcpy():
char* strcpy(char* d, const char* s)
{
char* tmp = d;
while (*tmp++ = *s++)
;
return d;
}
That's really all there is to it. Copy characters from the source to the destination until the source character is null (including the null). Return the pointer to the beginning of the destination. Done.
Pointers point to memory. It doesn't matter if that memory is "stack", "heap" or "static".
Function parameters are its local variables.
In this call
std::strcpy(aName, "Mary");
the two arrays (one that is created in main with the automatic storage duration and other is the string literal that has the static storage duration) are implicitly converted to pointers to their first elements.
So you may imagine this call and the function definition the following way
std::strcpy(aName, "Mary");
// …
char * strcpy ( /* char * destination, const char * source */ )
{
char *destination = aName;
const char *source = "Mary";
// …
return destination;
}
Or even like
char *p_to_aName = &aName[0];
const char *p_to_literal = &"Mary"[0];
std::strcpy( p_to_aName, p_to_literal );
// …
char * strcpy ( /* char * destination, const char * source */ )
{
char *destination = p_to_aName;
const char *source = p_to_literal;
// …
return destination;
}
That is within the function its parameters are local variable of pointer types with the automatic storage duration that are initialized by pointers to first characters of the passed character arrays
So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?
Yes. That is correct. Though I probably wouldn't call it a local variable. It is a parameter. Local variable usually means something like this:
int localVariable;
The word'parameter" is often associated with things like this:
int myFunction(int parameter) {
// use parameter some where...
}
The point is roughly the same though: it creates a variable that will go out of scope once the function exits.
I am asking this because it is very confusing to me. Whenever I have encountered addresses it usually was to point to a memory allocated on the heap...
Yes, this is the most common use case for them. But it isn't their only use. Pointers are addresses, and every variable has an address in memory regardless of whether it is allocated on the "heap" or "stack."
The use here probably because pointers to a char are commonly used to store strings, particularly on older compilers. That combined with the fact that arrays "decay" into pointers, it is probably easier to work with pointers. It is also certainly more backwards compatible to do it this way.
The function could have just as easily used an array, like this:
char * strcpy ( char destination[], const char source[ )
But I'm going to assume it is easier to work with pointers here instead (Note: I don't think you can return an array in C++, so I'm still using char *. However, even if you could, I would imagine it is still easier to work with pointers anyway, so I don't think it makes a lot of difference here.).
Another common use of pointers is using them as a way to sort of "pass by reference":
void foo(int * myX) {
*myX = 4;
}
int main() {
int x = 0;
foo(&x);
std::cout << x; // prints "4"
return 0;
}
However, in modern C++, actually passing by reference is preferred to this:
void foo(int & myX) {
myX = 4;
}
int main() {
int x = 0;
foo(x);
std::cout << x; // prints "4"
return 0;
}
But I bring it up as another example to help drive the point home: memory allocated on the heap isn't the only use of pointers, merely the most common one (though actually dynamically allocated memory has been mostly replaced in modern C++ by things like std::vector, but that is beside the point here).
I know that the aName (in the main) contains the address of the array.
You knew wrong. aName is an array. It contains the elements, not an address.
But when you use the name of the array as a value such as when passing it to strcpy, it is implicitly converted to a pointer to first element of the array (the value of a pointer is the memory address of the pointed object). Such implicit conversion is called decaying.
So is this assertion correct : strcpy creates a local variable called destination that has as value the address of the array aName that I have created on the stack in the main function?
This is correct enough. To clarify: It is a function argument rather than a local variable. But the distinction is not important here. Technically, it is the caller who is responsible for pushing the arguments onto the stack or storing them into registers, so it could be considered that main "creates" the variable.
Whenever I have encountered addresses it usually was to point to a memory allocated on the heap
Pointers are not uniquely associated with "heap". Pretty much any object can be pointed at, whether it has dynamic, static or automatic storage or even if it is a subobject.
I have a question regarding pointers. When I iterate through a char array using pointer to char array in function, original array stays the same, but when I do it in main function, I can't print char array.
I am new to pointers.
void f(char* a)
{
while (*a!=0) {
*(a++); // going through array
}
}
int main()
{
char* a1 = "test";
f(a1);
cout <<a1<<endl; // I can normally print out "test"
return 0;
}
But,
int main()
{
char* a1 = "test";
while (*a1!=0) {
*(a1++);
}
cout <<a1<<endl; // won't print anything
return 0;
}
So my question is, even though I am passing pointer to function, why is original array not modified?
Since you're incrementing the pointer a1, it points to the character '\0' at the end of the loop in main. Printing a null character prints nothing (empty string).
When you do this with a function, the pointer a is local is local to the function. It is modified within the function but is not changed in main. If you wanted similar results between the two examples, you would have to change the function to accept a reference parameter to the pointer:
void f(char * &a) { . . . }
f(a1);
won't modify your a1 after f exits
However
while (*a1!=0) {
*(a1++);
}
before cout
will make a1 to point to null character, so nothing gets printed
you're not changing a1 when you call your function. you're only changeing a copy of a1 that is passed into that function: a
But when you call a1++ in your main function, you are changing a1 and when it's finished, a1 will be 0 or '\0'
The difference is that in second case,a1 is pointing to \0 character after the loop exists. To see the same result in case of 1, receive pointer by reference.
void f(char* & a); // Valid in C++ only
The array a1 exists while the function main() is still active.
The address of a1 is passed to the function.
Such address is reserved to a1 because main() is still active.
Now, the variable a is a pointer whose initial value is a copy of a1, in the moment you do the call f(a1).
Take in account that a is a variable, and behaves like int, char, float, etc.
So, if you modify its "value" (that is, in this case, the memory address that a points to), the original address of a1 keeps untouched.
However, if you modify a member of a inside f():
a[0] = '!';
then the original array becomes: a1 equals to "!est".
The reason is that you are changing the content of the character held in the address of a (plus 0), which is (at the very start of execution of f()) the content of the address of a1 (plus 0).
Read more about pointers here
To be able to print the string in your second case, do this:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
char* a1 = "test";
char *ptr = a1; //create another pointer to a1
while (*ptr != 0) cout << *ptr++;
cout << endl << a1 << endl;
//You should get an output of the same string on 2 lines
return 0;
}
The formal parameter a in f is a different object in memory from the actual parameter a1 in main, so changing the value of a does not affect a1.
To mimic the behavior of the second snippet, you would have to pass a pointer to a1, like so:
void f( char **a )
{
while ( **a != 0 )
(*a)++; // increment the thing a points to
}
int main( void )
{
char *a1 = "test";
f( &a1 ); // pass a pointer to a1
cout << a1 << endl;
return 0;
}
In this code, we don't pass the value stored in a1 to f, we pass the address of a1. In f, we don't write to a, we write to *a, or what a points to.
You are using pass-by-value. (Everything in C++ is pass-by-value unless the function parameter is a reference type, i.e. has &, in which case it would be pass-by-reference.)
In pass-by-value, assignments to a parameter (and ++ is an assignment) do not have any effect on things outside the function.
Why this program only works when I initialize a and b.
I want to pass it without initializing a and b, for example:
numChange(10,15);
Is this possible ?
#include <iostream>
using namespace std;
void numChange(int *x,int *y)
{
*x = 99;
*y = 77;
}
int main()
{
numChange(10,15);
//int a=10;
//int b=15;
//numChange(&a,&b);
cout<<a<<" , "<<b<<endl;
return 0;
}
Because you have defined your function to receive pointers, but when you call that function you are trying to pass an int.
The compiler is expecting memory addresses and you are trying to pass constants.
It does not make sense, you are trying to do something like 10 = 99; 15 = 77;?
numChange(10,15);
//int a=10;
//int b=15;
It seems that you are hopping that a = 10 = 99 and b = 15 = 77;
If this was possible, it means that I could never (after the call of numChange(10,15);) make a variable to actually have the value 10 because 10 is "pointing" to 99 (is not).
Recall: a pointer is an integer containing a location in memory.
This:
int a, b;
...
a = b;
copies the integer stored at the memory location reserved for 'b' to
the memory location reserved for 'a'.
This:
int *a, b;
...
a = &b;
stores the location of 'b' in 'a'. Following it with this:
*a = 42;
will store 42 in the memory location stored in 'a', which is the
variable 'b'.
Now, let's look at your code. This:
void numChange(int *x,int *y)
tells the compiler that 'numChange' will be called with two
pointers--that is, memory addresses. This part:
*x = 99;
*y = 77;
then stores two integers at the locations given in 'x' and 'y'.
When you call:
numChange(10,15);
the arguments are integers instead of memory location. However under
the hood, memory locations are also integers so the compiler converts
the arguments to pointers. Effectively, it's doing this:
numChange((int *)10, (int*)15);
(It should issue a warning when this happens, since it's almost never
a good idea, but it will do it.)
Basically, your call to 'numChange' tells it that there are integer
variables at memory addresses 10 and 15, and 'numChange' carries on
and stores integers at those memory locations. Since there aren't
variables (that we know of) at those locations, this code actually
overwrites some other data somewhere.
Meanwhile, this code:
int a=10;
int b=15;
numChange(&a,&b);
creates two integer variables and then passes their addresses in
memory to 'numChange'. BTW, you don't actually need to initialize
them. This works too:
int a, b;
numChange(&a,&b);
What's important is that the variables are created (and the compiler
sets aside RAM for them) and that their locations are then passed to
'numChange'.
(One aside: I'm treating variables as always being stored in RAM.
It's safe to think of them this way but modern compilers will try to
store them in CPU registers as much as possible for performance
reasons, copying them back into RAM when needed.)
I'm sure this has been asked before, but a cursory google and stack overflow search didn't turn up the answer.
#include <stdio.h>
int main() {
char a[128][1024];
strcpy(a[0], "hello");
strcpy(a[1], "foo");
strcpy(a[2], "bar");
char **b = a;
printf("%s\n", a[0]); //same as printf("%s\n", a)
printf("%s\n", a[2]+1); //print from 2nd char of 3rd string
printf("%s\n", b); //same as printf("%s\n", a), makes sense
printf("%s\n", b[0]); //segfault???
}
First off, why is the last one a segfault? I'd expect same behavior as array a. How would I access the n-th string from b in a generalized way? What are the differences in treatment between a and b?
On a similar note, the way I understand it, a[n] is syntactic sugar for *(a+n). Is this correct, both for pointers and for arrays? Yet it seems getting different behavior for a and b.
Thanks!
char **b says “At the place where b points, b[0], there is a pointer to a char. And, if I use b[1], b[2],…, those are also pointers to char.”
In contrast char a[128][1024] says “a is 128 arrays of 1024 char.” When you do this, at the place where a is, there are no pointers. There are just char. In memory, it looks like 131,072 char in a row (128•1024 = 131,072).
When you assign char **b = a, assuming the compiler allows you to, you set b to be the address of a. When you use b[0], there should be a pointer there. But there is not. There are just char there. When you pass b[0] to printf, the compiler goes to where b points, loads several bytes as if they were a pointer, and passes the resulting value to printf. Then printf crashes, because the bytes point to some bad location.
A proper definition of b would be char (*b)[1024] = a;.
This
char **b = a;
is a type mismatch as a is char[][] which used without index is a char *.
You might like to switch an all compiler warning (on gcc this is doen via -Wall).
This line
printf("%s\n", b[0]);
dereferences a pointer to a pointer to character, that is an address value. Then it tries to print the address value value as a (0-terminated) string, what most likely is going to access random memory.
#include<stdio.h>
#include<string.h>
#include<iostream.h>
using namespace std;
int main()
{
const char *a="hello";
char *b;
strcpy(b,a);
cout<<b;
return 0;
}
This code theows memory exception . why ?
char* b is a pointer that is yet to be pointed at any memory... it simply holds a random address. You attempt to copy the content of a over the memory at that address. Instead, first point b at some memory - either a local array or from new char[].
char buffer[128];
char* b = buffer;
char* b = new char[128];
// use b for a while...
delete[] b; // release memory when you've finished with it...
// don't read/write data through b afterwards!
( or simply copy it directly into buffer :-) )
BTW, C++ has a <string> header that's much, much easier to use:
#include <string>
int main()
{
std::string s = "hello";
std::string t = s;
std::cout << t << '\n'; // '\n' is a "newline"
}
If you're writing new code, prefer std::string, but sooner or later you'll need to know about all that char* stuff too, especially when C++ code needs to interact with C libraries.
Exception is due to uninitialized,
char *b;
Either allocate b on stack as an array,
char b[SIZE];
Or allocate using new and later delete it. But the best way is,
std::string b;
b = a;
Here
char *b;
strcpy(b,a);
b is not initialized - using its value is undefined behavior. Even if using its value is okay on your platform it holds "whatever" address - copying a string onto "whatever address" is undefined behavior.
You have to allocate a memory block by any legal means and set b to start of that block. The block must be large enough to hold the string together with terminating null character.
b is uninitialised. It is a pointer, but it doesn't point anywhere (it holds NULL or a garbage value). strcpy tries to write to it, but it must have a pointer to write to. You must assign some chunk of memory to b before you can use it. Eg:
char *b = new char[20]; //dynamically allocate some memory
or
char b[20]; //allocate some memory on the stack
A few things are "wrong" with your code.
Use:
#include <iostream>
You're not using C++ strings.
std::string a = "hello";
std::string b = a;
If you insist on using strcpy(), please allocate some memory for b:
b = new char[strlen(a)];
// Your code here
delete[] b;
There's lots of memory to go around. No need to go about corrupting stuff.
You need to allocate memory (e.g. using malloc) for the destination before you can copy something there.
The char pointer b is initiaized to 0 when the program runs. So you can't copy anything to it.
If you want to copy a string, in C++ style, do this instead:
#include<iostream>
#include<string>
using namespace std;
int main()
{
string a = "hello";
string b = a;
cout << b << endl;
return 0;
}
strcpy(dest, source)
In your code b is your dest and it is not initialized. Even if you switch them around it will still crash because you have not allocated memory for b. The destination memory has to be pre-allocated.