help with function to concatenate strings (C++)

Page 2 - Seeking answers? Join the AnandTech community: where nearly half-a-million members share solutions and discuss the latest tech.

h4ever

Member
Aug 30, 2013
163
0
0
I received suggestion to create new type Path which is char array limited to 260 chars.

Code:
#include <array>
typedef std::array<char,_MAX_PATH> Path;
extern class Setts
{
    char path [_MAX_PATH];  //Path to INI

public:
    Setts();~Setts();
    Path getTempFileName(const Path &fileName);
} setts;

Setts::~Setts(){}

Path Setts::getTempFileName(const Path &fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat(path, "\\");
    strcat(path, fileName);
    return path;
}
But problem here is that this causes many errors because rest of the project (functions, conditions, and similar) depends on char[_MAX_PATH]. For example GetCurrentDirectory needs to have result in
LPTSTR not in char array... So how to avoid all these errors?
What do you suggest?
 

h4ever

Member
Aug 30, 2013
163
0
0
I thought it should be better to use
typedef char Path [_MAX_PATH]; for compatibility reasons . However

why I got error function Setts::getTempFileName returns array?

Code:
typedef char Path [_MAX_PATH]; 
Path  Setts::getTempFileName(
const Path &fileName)  
{     
GetCurrentDirectory(_MAX_PATH, path);     
strcat(path, "\\");     
strcat(path, fileName);     
return path; 
}
 

Tweak155

Lifer
Sep 23, 2003
11,449
264
126
I thought it should be better to use
typedef char Path [_MAX_PATH]; for compatibility reasons . However

why I got error function Setts::getTempFileName returns array?

Code:
typedef char Path [_MAX_PATH]; 
Path  Setts::getTempFileName(
const Path &fileName)  
{     
GetCurrentDirectory(_MAX_PATH, path);     
strcat(path, "\\");     
strcat(path, fileName);     
return path; 
}

Because it returns a char array? Also I don't know how you put a const as a parameter, let alone a function as a parameter.

If you are returning an array, you need to either return a pointer to the array or the address (I don't remember which). At least I think...

I don't know why you're making this so complicated.
 

h4ever

Member
Aug 30, 2013
163
0
0
If you are returning an array, you need to either return a pointer to the array or the address (I don't remember which). At least I think...

Well, good, this helped.

Code:
Path* getTempFileName(const Path &fileName);
Path* Setts::getTempFileName(const Path &fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat(path, "\\");
    strcat(path, fileName);
    return path;
}
Last three errors concerns of the line
Code:
return path;
in the function above.
error C2440: 'return' :cannot convert from 'Path' to 'Path (*)'
the next two errors are because of this error, they are in the assignment part. cannot convert parameter 1 from 'const char [13]' to 'const Path (&)'

I think that this is incorrect use of the pointer.
 

h4ever

Member
Aug 30, 2013
163
0
0
I better paste it here complete:

settings.h:

Code:
#include <stdlib.h>
#include <iostream>
#include <array>
typedef char Path [_MAX_PATH]; 

extern class Setts
{
    Path& path;    //Path to INI

public:
    Setts();~Setts();

    Path& getTempFileName(const Path &fileName);
    bool load();

    Path& BasePath;
    Path& ScenPath;

    Path& TempPath;
    #define DEL_TEMP_ON_EXIT 1;

    Path& logname;
    
    bool intense;

} setts;
settings.cpp:
Code:
#include <windows.h>
#include "settings.h"
#include <stdio.h>

Setts::~Setts(){}

Path& Setts::getTempFileName(const Path &fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat(path, "\\");
    strcat(path, fileName);
    return path;
}

bool Setts::load()
{
   TempPath = getTempFileName("scendata.tmp");
    logname = getTempFileName("ats_cache.log");
  
    return (result == ERROR_SUCCESS);
}
Do you see the lines:

Code:
   TempPath = getTempFileName("scendata.tmp");
    logname = getTempFileName("ats_cache.log");
This prints error:
'Setts::getTempFileName' : cannot convert parameter 1 from 'const char [13]' to 'const Path (&)'
Reason: cannot convert from 'const char [13]' to 'const Path'
There is no context in which this conversion is possible
error C2664: 'Setts::getTempFileName' : cannot convert parameter 1 from 'const char [14]' to 'const Path (&)'
Reason: cannot convert from 'const char [14]' to 'const Path'
There is no context in which this conversion is possible
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
What does it mean?

cannot convert parameter 1 from 'const char [14]' to 'const Path (&)'

or if I remove the const before Path:cannot convert parameter 1 from 'const char [14]' to 'Path (&)'

There is declaration like this:
Path& TempPath;
and definition:
TempPath = getTempFileName("scendata.tmp");

Is this problem of different types between function argument and the TempPath?
But they look they are both same tyoes.
Path &fileName ... or Path& fileName should be same type as Path& TempPath;

That's why I'm confused.

OR

maybe just "scendata.tmp" and Path& TempPath are different types because the first is string. But how to convert the string "scendata.tmp" into the Path& ?
 
Last edited:

code65536

Golden Member
Mar 7, 2006
1,006
0
76
I have read about pointers. I think you mean to learn not to teach.
No, I meant teach. Instructors who teach C/C++ classes, books that teach C/C++ programming. They inevitably all start with having their students or readers use <iostream>, cout/cin, and teaching them to do classes without teaching them about pointers, which in case I haven't emphasized enough, is something that one must fully understand.

Can you tell me why the following is correct?
Code:
char* Setts::getTempFileName(const char* fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat_s(path, _MAX_PATH, "\\");
    strcat_s(path, _MAX_PATH, fileName);
    return path;
}

Can you tell me the difference between
Code:
char foobar1[MAX_PATH];
char* foobar2 = new char[MAX_PATH];
char* foobar3 = malloc(MAX_PATH);
std::array<char,_MAX_PATH> foobar4;

And what am I doing when I do
Code:
char foo[MAX_PATH];
char* bar = foo;

And what's the difference between (hint: it's a trick question)
Code:
// snippet 1
char foo[MAX_PATH];
char a = foo[5];

// snippet 2
char foo[MAX_PATH];
char* bar = foo;
char a = bar[5];

// snippet 3
char foo[MAX_PATH];
char* bar = foo;
char a = *(bar + 5);

// snippet 4
char foo[MAX_PATH];
char a = *(5 + foo);
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
I am not going to use char* or
Code:
std::array<char,_MAX_PATH> Path;
This is because of compatibility with the rest of the project. I want the function return type
Code:
char[_MAX_PATH]

It looks to me simpler to use the strcat function. This is how I decided to do it.

What is the solution of last problem. Is it that I need to convert the function parametr before it is passed into function into char[_MAX_PATH]? I believe yes, but I need help how to do it. How can I convert between char array type and string gimme link, pls
 
Last edited:

code65536

Golden Member
Mar 7, 2006
1,006
0
76
I am not going to use char*. This is because of compatibility with the rest of the project. I want the function return type char[_MAX_PATH]
Then you don't understand how pointers and strings work in C and how they are related.

I hope this doesn't come across as condescending, but please, you need to read up about pointers and strings in C. (Not C++ library strings, but classic C strings.) If you can answer the "what's the difference" questions I posed above, then you'll be in good shape.

(And to get you started, pointers and arrays in C/C++ are very, very closely related; two different syntax to manipulate the same underlying thing. Know how they are related and why in some places you use array syntax and in others, you use a pointer syntax. Then you'll understand why the return syntax must be char* and why char[n] wouldn't even make sense. Don't try to do algebra until you've mastered arithmetic.)
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
Can you tell me why the following is correct?
Code:
char* Setts::getTempFileName(const char* fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat_s(path, _MAX_PATH, "\\");
    strcat_s(path, _MAX_PATH, fileName);
    return path;
}
It's clear that you limit the char array in the function strcat_s so it cannot make memory leak. It returns value accessed by pointer.

Can you tell me the difference between
Code:
char foobar1[MAX_PATH];
char* foobar2 = new char[MAX_PATH];
char* foobar3 = malloc(MAX_PATH);
std::array<char,_MAX_PATH> foobar4;
foobar1 will keep value
foobar2 will keep value referenced by pointer and memory will be allocated for the value
foobar3 am not familiar with the function malloc, but it's clear it will allocate memory for the value, result is value referenced by pointer
foobar4 is array of characters having access to methods of array class


And what am I doing when I do
Code:
char foo[MAX_PATH];
char* bar = foo;
you refer to value of foo


And what's the difference between (hint: it's a trick question)
Code:
// snippet 1
char foo[MAX_PATH];
char a = foo[5];
foo is not defined, so you are trying to access undefined element of the char array.


Code:
// snippet 2
char foo[MAX_PATH];
char* bar = foo;
char a = bar[5];
I am not sure what this means. On third line bar will keep reference to foo, so foo will be accessed when you will refer it on 4th line. But a contains copy of the 6th element of the bar.

Code:
 // snippet 3
char foo[MAX_PATH];
char* bar = foo;
char a = *(bar + 5);
This code is does similar thing as above because you access 6th element of the foo but this is by reference (4th line).


Code:
  // snippet 4
char foo[MAX_PATH];
char a = *(5 + foo);
a will refer to 6th element of the char array foo.
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
I still need help with the error

C2664: 'Setts::getTempFileName' : cannot convert parameter 1 from 'const char [13]' to 'Path (&)'

It's clear that const char [13] is the string "scendata.tmp" with null on the end of it.
But it is not clear to me how can I convert it because it is in the argument of the function.

Also these two errors are not clear to me when I got them in Visual Studio Express>
error C2106: '=' : left operand must be l-value
and
error C2664: 'strcat' : cannot convert parameter 2 from 'Path (*)' to 'const char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

The first is when I remove reference operator from the argument filename and the second is when I exchange reference operator from the argument for dereference operator. Why I cannot use Path when it is type char array ...same as const char array in the function argument....
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
I was hoping that, after reading up about this, you would come to realize that in C, arrays are pointers. Let me say that again: arrays are pointers. Arrays are just a special use case of pointers. In C, there are really just two general types of data: pointers, and non-pointers; arrays are nothing more than a common use case of pointers--so common that they created some syntax to make things look a bit cleaner--but at the end of the day, you're just playing with pointers.

When you have the following in a function:
Code:
char foo[50];
This is essentially equivalent to:
Code:
char *foo = alloca(50);

The most important part is that the "foo" in "char foo[50];" is a pointer. You think of it as an array, and there is array syntax in use here, but it is just a pointer. Which was the point of my final question (the one that's a trick question): that there is no difference between those 4 snippets, that those 4 snippets do the same thing (yes, the 6th byte is uninitialized random data, but that wasn't the point; the point that I was driving at is that arrays are pointers and array access brackets and pointer dereference operators do the same thing).

This is why when you want to create a pointer that points to an integer, you use
Code:
int bar;
int *foo = &bar;
But with arrays, you use
Code:
char bar[50];
char *foo = bar;
Note the lack of the address-of operator in the second case. Why? Because bar is already a pointer--it already is a memory address.

So, if we consider
Code:
char foobar1[MAX_PATH];
char* foobar2 = new char[MAX_PATH];
char* foobar3 = malloc(MAX_PATH);
std::array<char,_MAX_PATH> foobar4;

The difference is that the first creates a pointer and allocates MAX_PATH characters to it on the stack, which means it's automatically freed when you leave the scope of the function. The second does the exact same thing, except memory is allocated on the heap instead of on the stack (memory has to be freed manually). The third does the same as the second, except malloc() is classic C and can be used in either C or C++ whereas "new" is a new syntax that works only in C++. And the final one is an entirely different beast because it's a C++ STL class and is completely unlike any of the other three.

In my first question, the correctness isn't because of strcat_s (that's just good programming practice), but because it uses char * in both the function parameters and the return. Which it does because arrays are pointers and while pointer syntax is always valid when dealing with arrays, the specialized array syntax is used only in special circumstances. Specifically, the the number of bytes/elements in brackets is used for allocation. So when you declared path[_MAX_PATH], the part in brackets served to tell the compiler how many bytes in your class to allocate as memory for path. But once that memory has been allocated, and you're just returning the address to that chunk of memory, you aren't allocating any more, and the [] syntax makes no sense.
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106
There is a tiny difference between arrays and pointers though in the pointer math. Consider the difference of these:
Code:
void foo( int arr[][7] ) {
  std::cerr << foo[3][3] << '\n';
}

void bar( int ** ptr ) {
  std::cerr << ptr[3][3] << '\n';
}
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
There is a tiny difference between arrays and pointers though in the pointer math.

Indeed. But that is still just syntactic sugar to let the compiler know how much to offset by when you use array-style dereference. You either specify the 7 in a declaration to help the compiler, or you can specify the 7 manually if using a pointer derefernce (e.g., *(ptr + 3 + 3 * 7)). At the end of the day, arrays are still just pointers coated with (useful) syntactic sugar. I'm not saying "death to array syntax"; I'm saying "know that arrays are sugar-coated pointers and all the implications that come with that".
 

h4ever

Member
Aug 30, 2013
163
0
0
code65536:
Sure, there is a lot of good information in your last post. In the pointers tutorial I read there is notice about [] a and dereference operator * works very similar but they did not say explicitly that arrays are pointers and they work the same. But that make sense when array chars are declared as
Code:
char* foo;
I did not realize that presence of the asterix in declaration clearly says that the char array is always a pointer... But in the case that it is declared as char[] one could not realize it until you realize that [] and * are working the same.

Did somebody told this to you when you first time read about pointers, strings and arrays in C/C++? Or did you find it yourself without somebody to tell you?

But still I cannot solve the problem with the parameter.

This is what I have:

header file:

Code:
#include <stdlib.h>
#include <iostream>
#include <array>
typedef char Path [_MAX_PATH]; 

extern class Setts
{
    Path* path;
public:
    Setts();~Setts();
    bool load();
    Path* getTempFileName(Path *fileName);
    Path* BasePath;
    Path* ScenPath;
    Path* TempPath;
    Path* logname; // Log
    
    bool intense;

} setts;

And the definition:
Code:
#include "settings.h"
#include <stdio.h>
Setts::~Setts(){}

Path* Setts::getTempFileName(Path *fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat(path, "\\");
    strcat(path, fileName);
    return path;
}

bool Setts::load()
{
    TempPath = getTempFileName("scendata.tmp");
    logname = getTempFileName("ats_cache.log");
    return (result == ERROR_SUCCESS);
}

Now I get these errors:

error C2664: 'GetCurrentDirectoryA' : cannot convert parameter 2 from 'Path (*)' to 'LPSTR'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

error C2664: 'strcat' : cannot convert parameter 1 from 'Path (*)' to 'char *'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast

I see that the functions expects char or LPSTR, but it's not clear to me how to refer them correctly. When I try

Code:
    GetCurrentDirectory(_MAX_PATH, *path);
    strcat(*path, "\\");
    strcat(*path, *fileName);
    return *path;

So same problem.
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
I did not realize that presence of the asterix in declaration clearly says that the char array is always a pointer.
It doesn't.

I never had an example that said "char * foo[50];"

Using [] in a declaration implies the asterisk. If you use an asterisk and [], then you are creating a pointer to a pointer.

Code:
// foo is a character pointer pointing an a block with 50 bytes allocated
char foo[50];

// bar is a character pointer pointing at nothing
char *bar;

// baz is a character pointer pointing at the exact same chunk of memory allocated for foo
char *baz = foo;

Note I didn't use the asterisk for foo, and I didn't use [] for bar or baz.

Your code should look something like:
Code:
[blah blah blah]

    char path[_MAX_PATH];

[blah blah blah]

    char* getTempFileName(char *fileName);

[blah blah blah]

path is an array that you're allocating inside your class. getTempFileName is a function that returns the address of an array of characters (in this case, the address of path).

Did somebody told this to you when you first time read about pointers, strings and arrays in C/C++? Or did you find it yourself without somebody to tell you?
No, I was not taught this when I first learned C++ over 15 years ago. I was pushed right into using C++, which I, again, think is a terrible idea. C++ really should only be used by people who fully understand C, because C++ improved upon C mostly by adding truckloads of syntactic sugar that obfuscates much of the foundation. I especially hate C++ references because they don't make things easier or cleaner and instead make implicit things that really ought to be explicit, thus making it far easier to make mistakes (again, without making it easier or cleaner to code). And it was confusing at first, so I stopped, read up on C (without the C++), and things just made so much more sense.

And I'll say again: Programming is not a search for the right incantation. You must fully understand every bit of your code, and I don't mean, "what does this line do?", but "what does this asterisk mean, what does it do, and why am I using it?". And C++ is a mess of a language that muddles a lot of these finer details. Yet somehow the CS educational community got it into their heads that people should start with C++. Yea, I'm all for teaching object orientation and classes, but not like this.
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
Then it has no solution and I can discard the function. I dont want use char*, because the origin was
Code:
 char variable [_MAX_PATH]

When I cannot pass Path into the function because incompatibility with GetCurrentDirectory and strcat so what the use of
Code:
typedef char Path [_MAX_PATH];
is for?
When I cannot limit the char array in the function than it's better to skip the fucking function.
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
There really is no point in having that typedef.

And one of the implications of arrays being just pointers is that there is no enforcement on the length. [_MAX_PATH] simply allocates 260 characters to the path. That's all; it doesn't carry any form of enforcement of that limit. There is nothing inherent to stop you from going over that allocation and crashing. It is up to you to observe and enforce these limits in the code. This is why you pass _MAX_PATH to GetCurrentDirectory so that it can respect that limit when it's doing its work. That's why you pass _MAX_PATH to strcat_s, so it can observe that limit when it's doing its work.
 

h4ever

Member
Aug 30, 2013
163
0
0
Still, there is error:

Code:
extern class Setts
{
    char path [_MAX_PATH];
public:
    Setts();~Setts();
    char* getTempFileName(char *fileName);
    bool load();
    char BasePath [_MAX_PATH];
    char ScenPath [_MAX_PATH];
    char TempPath [_MAX_PATH];
    char logname [_MAX_PATH];
    bool intense;

} setts;
Definition:

Code:
char* Setts::getTempFileName(char *fileName) 
{
    GetCurrentDirectory(_MAX_PATH, path);
    strcat_s(path, _MAX_PATH, "\\");
    strcat_s(path, _MAX_PATH, fileName);
    return path;

}
... bla bla ...
TempPath = getTempFileName("scendata.tmp");
logname = getTempFileName("ats_cache.log");
... bla bla ...

cannot convert from 'char *' to 'char [260]'
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
Um, think carefully about what the code is doing.

Do you know what exactly is being copied here?
Code:
TempPath = getTempFileName("scendata.tmp");

TempPath is essentially a pointer to a chunk of 260-character memory.

path is a pointer to a chunk of 260-character memory.

What your code above is trying to do is replace one pointer with another, but since TempPath is a special kind of pointer (one that already has a chunk of memory irrevocably associated with it), you get an error.

When you return path, you are returning a pointer. Remember, the CPU doesn't know what an array is. The CPU has no concept of arrays. So you must be explicit in telling the CPU what you want to do.

So what do you want to do? Do you want TempPath to point to a new chunk of memory (in this case, the chunk of memory associated with path)? In that case, TempPath should be declared as just a pointer without its own chunk of memory (char *TempPath) so that this kind of pointer assignment can work.

If, instead, you want TempPath to point to its very own separate chunk of memory and have the path copied into TempPath's chunk of memory, then you should keep TempPath declared as it is (char TempPath[_MAX_PATH]) and instead copy the data from one chunk to another.

I'm going to assume that you want to do the latter because the former isn't very useful. If so, instead of trying to copy a pointer to a pointer, you should be copying the memory contents that are being pointed to.
Code:
strcpy(TempPath, getTempFileName("scendata.tmp"));

Or, better yet, you can rewrite getTempFileName.

Code:
void Setts::getTempFileName(char *fileName, char* targetName, unsigned int targetLength) 
{
    GetCurrentDirectory(targetLength, targetName);
    strcat_s(targetName, targetLength, "\\");
    strcat_s(targetName, targetLength, fileName);
}

getTempFileName("scendata.tmp", TempPath, _MAX_PATH);

Notice how this is kinda similar to how GetCurrentDirectory works? GCD doesn't return a path, because returning a path is just returning a pointer. Instead, you provide GCD with a chunk of memory, and GCD copies its results into that chunk of memory you provide. Same thing here. This gets rid of the need for an intermediate path buffer.

Do you understand how and why this works?
 

h4ever

Member
Aug 30, 2013
163
0
0
Slow down.

What your code above is trying to do is replace one pointer with another,
Where exactly? Which command?

but since TempPath is a special kind of pointer (one that already has a chunk of memory irrevocably associated with it), you get an error

Do you speak about the kind of error that this code:
Code:
GetCurrentDirectory(_MAX_PATH, path);
strcat_s(path, _MAX_PATH, "\\");
strcat_s(path, _MAX_PATH, fileName);
Would it be like trying to count 260+260+260 but this is not equal to 260? Or the first and second line results in the problem of 260+260!==260 ?
It looks so. I thought that I will get only those chars which are before null \0 . So in the case that I have path "c:"+"\test" there should be 7 chars + \0 . So you say, that this command does not copy these chars, but only changes pointers to the chunk of 260? So no one of this commands could work? It could work only if the destination variable would be defined as "unlimited" char*.... Right?

If, instead, you want TempPath to point to its very own separate chunk of memory and have the path copied into TempPath's chunk of memory, then you should keep TempPath declared as it is (char TempPath[_MAX_PATH]) and instead copy the data from one chunk to another.

I'm going to assume that you want to do the latter because the former isn't very useful. If so, instead of trying to copy a pointer to a pointer, you should be copying the memory contents that are being pointed to.
Code:
strcpy(TempPath, getTempFileName("scendata.tmp"));
Or, better yet, you can rewrite getTempFileName.

I think I start to understand the difference in the function. This is really valuable for me and I appreciate that you explained it to me. Nobody explained till now.

Edit:
So no, you don't mean the function to copy strcat_s but to copy only the result of getTempFileName. So is there difference between strcat_s and strcat? strcat look needs not the argumenr of lenght. Sorry I'm tired, hard to think.
 
Last edited:

h4ever

Member
Aug 30, 2013
163
0
0
Code:
void Setts::getTempFileName(char *fileName, char* targetName, unsigned int targetLength) 
{
    GetCurrentDirectory(targetLength, targetName);
    strcat_s(targetName, targetLength, "\\");
    strcat_s(targetName, targetLength, fileName);
}

getTempFileName("scendata.tmp", TempPath, _MAX_PATH);
Notice how this is kinda similar to how GetCurrentDirectory works? GCD doesn't return a path, because returning a path is just returning a pointer. Instead, you provide GCD with a chunk of memory, and GCD copies its results into that chunk of memory you provide. Same thing here. This gets rid of the need for an intermediate path buffer.

Do you understand how and why this works?

I am not sure what this mean. Do you say the 2nd argument in your function will make save the result into TempPath and into logname? I don't understand how this works. The return of path in my function is wrong? It looks so. Because later in this command:

Code:
if (DEL_TEMP_ON_EXIT)
        DeleteFile(setts.TempPath);
I got this error:
error C2143: syntax error : missing ')' before ';'
error C2059: syntax error : ')'
warning C4390: ';' : empty controlled statement found; is this the intent?

I am not familar what is meanning of these errors (of sure I don't see any missing semicolon] but maybe my function returns incorrect type so the result is not char array referenced by pointer?

Note, that I did not updated my function yet.
 

code65536

Golden Member
Mar 7, 2006
1,006
0
76
Where exactly? Which command?
I quoted the code that I was referring to:
Code:
TempPath = getTempFileName("scendata.tmp");
TempPath is an array, which just means that it's a pointer irrevocably attached to a chunk of memory. When you try to set that equal to the results of getTempFileName, you are trying to replace the TempPath pointer with the pointer returned by getTempFileName which the compiler does not allow because TempPath already has its own chunk of memory that it cannot be separated from (since you declared it as an array).

The following is a simplified example.
Code:
char path[200];
// path is an array, which means that it's basically a special kind of pointer
// it is pointing to a 200-character chunk of memory

GetCurrentDirectory(200, path);
// note that GetCurrentDirectory DOES NOT RETURN THE RESULT!
// instead, you provide GCD with the address of a chunk of memory
// in other words, you provide it with a pointer--in this case, path
// GCD then *copies the results into the addressed pointed to by path*

strcat_s(path, 200, "blahblahblah");
// again, note that strcat_s DOES NOT RETURN THE RESULT! this is NOT like other
// languages where you concat strings by doing str = foo + bar, where foo and
// bar and joined and the results are returned and you can then do an = with it
// that stuff works in other languages because they do a ton of other crap
// hidden in the background to make that happen automagically
//
// strcat_s copies "blahblahblah" to the end of the string whose address is
// pointed to by path; a new string IS NOT CREATED; the amount of memory
// allocated to path REMAINS AT 200; the reason you tell strcat_s about that 200
// is so that it won't overflow it
//
// so if you have a 60-character string inside a 200-character buffer and you
// strcat a 30-character string to it, you now have a 90-character string
// inside that *same* 200-character buffer.


// Now consider the following:

char temp[200];
temp = path;
// this is WRONG, because temp is just a pointer (a special kind of pointer),
// and path is just a pointer, and when you have pointer1 = pointer2, the
// compiler makes pointer1 point to the same address as pointer2, but since
// temp is already pointing to its own address and is not allowed to point at
// any other address, this fails...

char *temp;
temp = path;
// this works, beacuse now temp is a "real" pointer, so it can point to any
// address you tell it to; in this case, BOTH temp and path will point to the
// SAME chunk of memory

char temp[200];
strcpy_s(temp, 200, path);
// this is different from the first example because you are not using =, so
// the compiler is not trying to replace temp with path, but instead it is
// copying the MEMORY pointed to by path into the MEMORY pointed to by temp
// here, you now have TWO copies of the path

I've said over and over, if you want to program in C/C++, you must (this is not optional) understand pointers. Not know what they are. But understand them and what they represent.
http://en.wikipedia.org/wiki/Pointer_(computer_programming)
 
Last edited:

mv2devnull

Golden Member
Apr 13, 2010
1,526
160
106