But why would you want to?
It would be incorrect since a pointer to an array is not convertible to a pointer to a pointer. You would need to have a pointer in main point to the first element of buf, and then pass the address of that pointer... or just change the function signature to pass the pointer by reference.Originally Posted by King Mir
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
You're right. I had it like that first, then thought it wouldn't be needed. Fixed it now.
It is too clear and so it is hard to see.
A dunce once searched for fire with a lighted lantern.
Had he known what fire was,
He could have cooked his rice much sooner.
Thanks for the kind help.
I worked it out with this solution:
Reference to an array: int (&arr)[mysize];
I wanted to avoid dynamic allocation because I was having trouble freeing it, it kept on crashing even after I copied the allocated buffer to a static buffer.
Using Windows 10 with Code Blocks and MingW.
Why not post your working code?Originally Posted by Ducky
Personally, I don't often see references to arrays being used, and I don't see how it would solve your problem in this thread since you are doing pointer arithmetic. In fact, if I'm pressed for a good use of a reference to an array, I would probably give the one where it is used to return sizeof the array from a function template.
Look up a C++ Reference and learn How To Ask Questions The Smart WayOriginally Posted by Bjarne Stroustrup (2000-10-14)
You are right I didnt need the reference after all.
The problem was before that when I passed a dynamic buffer to the function I didnt get back the data modified in the function.
But with a static buffer I dont seem to need to pass by reference.
Maybe you can find some simplification to it. Thanks.
Code:int main() { char buf[260]; ReceiveDataWithHeader(Socket, Buf); cout << "iReceived " << Buf << endl; } // size of data in header int ReceiveDataWithHeader(SOCKET Socket, char Buf2[260]) { bool iGetSize = 1; short iReceived = 0; unsigned long DataSize=0, TotalSize=1; unsigned long Total=0, Digits=0; char * pch; char * Buf = Buf2; while(TotalSize) { iReceived = recv(Socket, Buf, 32, 0); cout << "iReceived " << Buf << endl; cout << "iReceived " << iReceived << endl; if(iReceived > 0) { if(iGetSize) Total += iReceived; else TotalSize -= iReceived; if(iGetSize) { pch = strchr(Buf,'$'); // if recieved DataSize if (pch!=NULL) { pch[0] = '\0'; // got DataSize DataSize=atoi(Buf); cout << "DataSize " << DataSize << endl; Digits = GetNumberOfDigits(DataSize); cout << "Digits " << Digits << endl; // NumberOfDigits + $ + DataSize TotalSize = Digits + 1 + DataSize; cout << "TotalSize " << TotalSize << endl; // substruct all that we got until now TotalSize -= Total; // remove 0 pch[0] = '$'; // dont come here anymore iGetSize = 0; } } Buf += iReceived; cout << "TotalSize " << TotalSize << endl; } else if ( iReceived == 0 ) { printf("ReceiveDataWithHeader Connection closed\n"); return 1; } else { ReportError("ReceiveDataWithHeader"); return 1; } } strcpy(Buf, "\0"); Buf -= DataSize; // go back to the beginning strcpy(Buf2, Buf); return 0; }
Last edited by Ducky; 06-18-2012 at 01:53 PM.
Using Windows 10 with Code Blocks and MingW.
I think you could still work with the string class. You can make a string out of the data in buf and the length of the data after the recv() call. If you have to call any other networking functions with C-strings as arguments, just call string::copy() beforehand. That's about as simple as it becomes.
Buf2 is already a pointer, so you do not need Buf. You should also pass the buffer by reference, so you can query its real size to avoid buffer overflows.
I do not know which parameter to recv that is the buf size, but make sure buf can hold at least that much!
Either use sizeof in recv or use static asserts to ensure buffer size is greater than what you pass to recv.
>> You should also pass the buffer by reference, so you can query its real size to avoid buffer overflows.
Whereas I just rely on constants and calculation where possible. You could pass in the size of the buffer as another argument. The method that you recommend requires templates to make the buffer flexible in size, it also is completely impossible to use with dynamic memory, so in more general situations it is impractical. I don't like those kinds of problems. On the other hand, I can shrug it off as a garbage in, garbage out kind of issue.
>> I do not know which parameter to recv that is the buf size, but make sure buf can hold at least that much!
Then perhaps you shouldn't comment. I know it's not a C standard function, so you don't know it but in this case his usage is more than fine.
Last edited by whiteflags; 06-18-2012 at 05:06 PM.
@Elysia
Buf2 is already a pointer, so you do not need Buf.
Buf2 is an array not a pointer hence I cant have pointer arithmetics on it. Thats why I added char * Buf.
whiteflags I think you could still work with the string class.
I could and I started to transform the code but im not sure that it would result in a smaller and simpler code. Not worth the hassle.
I dont wanna go there but C++ functions aren't any handier than the C versions.
Nothing but to split the buffer into three tokens I would need three times more code than what I have already.
You can prove me wrong inside my code if you feel like it though.
Using Windows 10 with Code Blocks and MingW.
@Elysia Buf2 is already a pointer, so you do not need Buf.
Buf2 is an array not a pointer hence I cant have pointer arithmetics on it. Thats why I added char * Buf.
@whiteflags I think you could still work with the string class.
I could and I started to transform the code but im not sure that it would result in a smaller and simpler code. Not worth the hassle.
I dont wanna go there but C++ functions aren't any handier than the C versions.
Nothing but to split the buffer into three tokens I would need three times more code than what I have already.
You can prove me wrong inside my code if you feel like it though.
Using Windows 10 with Code Blocks and MingW.
>> I dont wanna go there but C++ functions aren't any handier than the C versions.
You won't offend me so easily.
>> Nothing but to split the buffer into three tokens I would need three times more code than what I have already.
It's late so don't try to plug this in.
From what I can see, this services your needs. You could make it more C++ like but in controlled environment, I can understand the opinion that anything more is fluff.Code:token = buffer.substr(0,buffer.find('$')); // This is just the first pass, you can track the starting point with a variable // In fact, you could put the find step on an earlier line and make that easier. dataSize = atoi(token.c_str()); // Use like normal // buffer is not changed by this code
I think I'm ready for bed.
Last edited by whiteflags; 06-19-2012 at 12:48 AM. Reason: sleep induced mistakes
If you use dynamic memory, use std::vector. Then use its .size() member.
I didn't say it was not fine. You missed my point. The point is that the size is hard coded and the size of the buffer is hard coded. That is just ripe for problems and errors.
Imagine some day when Ducky increases the recv bytes arg to some higher number and some other day decides that the buf is too big.
Heck, just imagine having some big buffer and multiple functions using it. It's just bound to be some day when the size of the buffer may be decreased while the buffer size params in the recv calls are the same, or the other way around, that the buffer is the same, but the recv buf size parameter is increased.
That's a buffer overflow. If you're lucky, it will crash. If you're unlucky, you won't notice it.
So the best thing to do is to get the compiler to help us catch such a regression at compile time.
That's why I'm telling these things. You can do it multiple ways, just make sure you do it.
I know you want to be right, but you aren't. Buf2 is a pointer.
Output:Code:#include <iostream> #include <typeinfo> void foo(char buf[256]) { std::cout << "foo: buf[256] type: " << typeid(buf).name() << "\n"; } int main() { char buf[256]; std::cout << "main: buf[256] type: " << typeid(buf).name() << "\n"; foo(buf); return 0; }
main: buf[256] type: char [256]
foo: buf[256] type: char *
Besides, pointer arithmetic work on (C-)arrays, too.
>> If you use dynamic memory, use std::vector. Then use its .size() member.
Which is irrelevant.
>> That's a buffer overflow. If you're lucky, it will crash. If you're unlucky, you won't notice it.
>> So the best thing to do is to get the compiler to help us catch such a regression at compile time.
How do you know what's best? You could debug it like a normal person would when they change their own code. C++ is not one of those happy languages where if it compiles it automatically works. In fact I don't think there is a language like that. You still have to care about what happens in run time no matter what.
Explain HOW that's irrelevant.
Debug the code? Are you serious? That is a ridiculous argument.How do you know what's best? You could debug it like a normal person would when they change their own code. C++ is not one of those happy languages where if it compiles it automatically works. In fact I don't think there is a language like that. You still have to care about what happens in run time no matter what.
Debugging isn't meant to make sure the code works. It's meant to FIND what causes the bugs that prevents the coding from working.
Regression testing makes sure the code works. This is part of regression testing.
It also creates fewer bugs, and it decreases the likelihood of bugs escaping notice.
It does not, however, mean that you should rely ONLY on this. This is meant to be a tool to complement your arsenal, not replace it.