Board index » cppbuilder » How to point my pointers

How to point my pointers


2004-01-05 04:40:58 AM
cppbuilder35
Although I wrote a lot of useful (to me) programs, I still struggle regulary
with pointers. Perhaps a explanation to some of my questions could resolve
this for once and for ever.
1. Why do I get so often "suspicious pointer" warnings while my program
seems to work fine.
2. char mystring[80]; reserve 80 bytes space for mystring.
char * mystring[80]; to me seems to do the same.
What's the difference.
Am I rigtht, I have to refer to the first as "mystring" and to the
second as "&mystring" if I need the data. If both can store the same
data, what is the reason to choose the one or the other.
3. char mydata[2048]; How do I point a structure to a arbitrary place in
this block of data and read (or write) the data types.
Chris.
 
 

Re:How to point my pointers

"Chris" < XXXX@XXXXX.COM >wrote in message
Quote
1. Why do I get so often "suspicious pointer" warnings while my program
seems to work fine.
Because you are probably misuing the pointers as far as the code goes,
although the end result is the desired effect anyway. It is hard to tell
for sure without seeing your actual code that is causing the warning.
Quote
2. char mystring[80]; reserve 80 bytes space for mystring.
char * mystring[80]; to me seems to do the same.
No, it does not do the same thing.
Quote
What's the difference.
The first is an array of 80 actual characters.
The second is an array of 80 pointers to characters, they are not the
characters themselves like the first is.
Quote
Am I rigtht, I have to refer to the first as "mystring" and to
the second as "&mystring" if I need the data.
That depends on what kind of data you want to store and how you want to
access it. Again, please show an actual code example.
Quote
If both can store the same data
They do not.
Quote
3. char mydata[2048]; How do I point a structure to a arbitrary
place in this block of data
char *ptr = &mydata[index];
Gambit
 

Re:How to point my pointers

"Chris" < XXXX@XXXXX.COM >writes:
Quote
1. Why do I get so often "suspicious pointer" warnings while my program
seems to work fine.
The key word you need to consider is "seems". Things may look to be
working correctly but can still be silently corrupting memory.
Invalid conversions or "suspicious" conversions are problems, because
the compiler knows typical problems and any of its warnings should be
taken seriously, unless you completely understand why it is warning,
what you're doing, and why the warning is worth ignoring. (In which
case, you should do something to disable it only for that code.) You
really want to have builds with no warnings at all, so if you ever get
one you don't accidently ignore it.
So why do you get this? I don't know, you'll have to show some code
that causes it and we can point it out.
Quote

2. char mystring[80]; reserve 80 bytes space for mystring.
char * mystring[80]; to me seems to do the same.
What's the difference.
#include <iostream>
#include <typeinfo>
#define explain(T) \
std::cout << "Your type is: " << typeid(T).name()\
<< " which is " << sizeof(T) << " bytes"\
<< std::endl;\
int main()
{
char mystr[80];
char * mystr2[80];
explain(mystr);
explain(mystr2);
}
Here is the output I get on g++:
Your type is: A80_c which is 80 bytes
Your type is: A80_Pc which is 320 bytes
If you read this, it's an encoding for saying for the first line:
"your type is an array of 80 characters taking 80 bytes" Since a
character is 1 byte and you have 80 of them, then that explains the
size.
The second line says "your type is an array of 80 pointers to
characters, taking 320 bytes". Here, your array is of pointers to
characters, and a pointer is 4 bytes. 80 pointers at 4 bytes each is
320 bytes.
For a visual difference:
char[3]:
+---+---+---+
| A | B | C |
+---+---+---+
char * [3]:
+----------------+----------------+----------------+
| <4-byte addr>| <4-byte addr>| <4-byte addr>|
+------/---------+------|---------+-----\----------+
/ | \
/ | \
+---+ +---+ +---+
| A | | B | | C |
+---+ +---+ +---+
Quote
Am I rigtht, I have to refer to the first as "mystring" and to the
second as "&mystring" if I need the data. If both can store the same
data, what is the reason to choose the one or the other.
No, the physical layout is very different. EACH element of the array
holds the address of a single character in the 2nd approach. You'd
have to do something like this to use:
char mystr1[3] = {'a', 'b', 'c'};
char mystr2[3];
mystr2[0] = new char('a');
mystr2[1] = new char('b');
mystr2[2] = new char('c');
Then accessing them is different too:
char ch1 = mystr1[0];
char ch2 = *mystr2[0];
And you can't forget to delete the data either.
Quote
3. char mydata[2048]; How do I point a structure to a arbitrary place in
this block of data and read (or write) the data types.
You'd use placment new. I'd suggest that if you're having problems
with pointer basics that you not use such techniques until you have a
better understanding of how it works. Low level pointer manipulation
is a major source of bugs and is extremely error-prone.
Hope this helps.
--
Chris (TeamB);
 

{smallsort}

Re:How to point my pointers

Hi!
Chris wrote:
Quote
Although I wrote a lot of useful (to me) programs, I still struggle regulary
with pointers. Perhaps a explanation to some of my questions could resolve
this for once and for ever.
If I wanted to visit you, would you ...
a) give me a copy of your house
b) tell me where you live
?
case a)
You build up a new house in front of me. I can walk into it, break
the light bulbs and windows, paint the walls, set off a fire, ... you
wouldn't care, since you still have your original house.
case b)
You tel me where you live. I can walk to your (only) house, and ...
Quote
2. char mystring[80]; reserve 80 bytes space for mystring.
This is a bunch (80) of houses (char). Here you have 80 fresh houses.
Quote
char * mystring[80]; to me seems to do the same.
This is a bunch (80) of addresses (char*). Here you can store the
locations of 80 different houses.
Quote
Am I rigtht, I have to refer to the first as "mystring" and to the
second as "&mystring" if I need the data.
No. Because they don't store the same data. The first is a row of
houses, the second is an addressbook.
Quote
3. char mydata[2048]; How do I point a structure to a arbitrary place in
this block of data and read (or write) the data types.
You can tell the compiler "hey, there is a penthouse at index 713", but
you know there isn't (its only a bunch of char). Thus it will likely
introduce bugs.
Now:
char c; //makes a char
char *pc; //does not make a char
pc = new char; //makes a new char
delete pc; //destroys the char
pc = &c; //saves address of c
If 'c' was your house, they you would give me a copy of 'pc', so that I
know where you live.
I hope it helps.
Frank
 

Re:How to point my pointers

Did read all replies carefully and learned bit by bit from them. I took
the time to check some of my code and with my increasing notion
found some disturbing mistakes.This is what I now make of the
example below (please correct me if necessary).
On this example where I get a "Suspicious pointer conversion"
warning on the return statement, do I have it right that I return a pointer
to a local char array that will be released after return ? That the
function works, but only because the memory is not yet overwritten ?
Probably because I use the string data only once, right after the call ?
char * dest_str ( char * source_str )
{
unsigned char strbuf[256];
strcpy(strbuf,source_str);
// do my thing on strbuf
return(strbuf);
}
The reason not to "do my thing" on the source string is because I want to
keep it unaltered. After I made the "strbuf" variable global, the warning
disappeared. In the case below I don't get a warning on the return.
I return a pointer to a string, made by the function somewhere in memory
which seems to be legal. If so, is this string ever in memory untill I close
the program. If so, and I call the function twenty times, is memory freed
for the old assignment every time I assign a new string to this pointer ?
char * getStringFromClipboard()
{
int ok = OpenClipboard(NULL);
char * strbuf;
HANDLE hData = GetClipboardData( CF_TEXT );
strbuf = (char*)GlobalLock( hData );
GlobalUnlock( hData );
CloseClipboard();
return strbuf;
}
I realize now, it's very dangerous to ignore compiler warnings.
I'm afraid I have a lot of code to check :-).
Thanks,
Chris
Remy Lebeau (TeamB) < XXXX@XXXXX.COM >schreef in
berichtnieuws XXXX@XXXXX.COM ...
Chris Uzdavinis (TeamB) < XXXX@XXXXX.COM >schreef in berichtnieuws
XXXX@XXXXX.COM ...
Frank Birbacher < XXXX@XXXXX.COM >schreef in berichtnieuws
XXXX@XXXXX.COM ...
 

Re:How to point my pointers

"Chris" < XXXX@XXXXX.COM >wrote in message
Quote
On this example where I get a "Suspicious pointer conversion"
warning on the return statement, do I have it right that I return
a pointer to a local char array that will be released after return ?
Yes. The array will go out of scope when the function returns, thus the
caller will end up with an invalid pointer.
Quote
That the function works, but only because the memory is not yet
overwritten ?
Correct. Your array is created on the stack of the calling thread, and the
stack is a fixed block of memory that exists for the lifetime of the calling
thread. So the memory for the array will physically exist, but there is no
guarantee that the data inside that memory will remain valid for any length
of time once it goes out of scope.
Quote
The reason not to "do my thing" on the source string is
because I want to keep it unaltered.
Then you should have to the function accept an alterable buffer as another
parameter, and then have the function fill in the buffer as needed, ie:
char* dest_str( const char* source_str, char* buffer, int buffersize )
{
strncpy(buffer, source_str, buffersize);
// do my thing on the buffer
return buffer; // not required, only for convenience
}
Quote
In the case below I don't get a warning on the return.
No, you wouldn't. But what you are doing is still not correct. As soon as
you unlock the memory object, you have no guarantee that someone else won't
come along afterwards and alter, or even free, the memory. You should only
work with the memory while you still have it locked. That ensures that
noone else can touch it until you finally unlock it, ie:
char* getStringFromClipboard( char* buffer, int buffersize )
{
bool bOk = false;
if( OpenClipboard(NULL) )
{
HANDLE hData = GetClipboardData( CF_TEXT );
if( hData )
{
char* strbuf = (char*)GlobalLock( hData );
if( strbuf )
{
strncpy( buffer, strbuf, buffersize );
bOk = true;
GlobalUnlock( hData );
}
}
CloseClipboard();
}
if( bOk )
return buffer;
return NULL;
}
Gambit
 

Re:How to point my pointers

"Chris" < XXXX@XXXXX.COM >writes:
Quote
On this example where I get a "Suspicious pointer conversion"
warning on the return statement, do I have it right that I return a pointer
to a local char array that will be released after return ? That the
function works, but only because the memory is not yet overwritten ?
Probably because I use the string data only once, right after the call ?

char * dest_str ( char * source_str )
{
unsigned char strbuf[256];

strcpy(strbuf,source_str);
// do my thing on strbuf

return(strbuf);
}
This is really problematic code, because the caller cannot--ever--use
the return value in a defined manner. The result is pointing to the
stack frame that no longer exists, and dereferencing that pointer will
have undefined behavior. (Giving you what you expect is one
incarnation of undefined behavior, but it could just as easily give
you something completely different.) Any undefined behavior like this
is always a serious bug.
Quote
The reason not to "do my thing" on the source string is because I want to
keep it unaltered.
Then do this:
size_t dest_str(
char const * source_str,
char * dest_str,
size_t dest_len)
{
size_t bytes = strncpy(dest_str, source_str, dest_len);
dest[dest_len-1] = '\0';
// do my thing on strbuf
return bytes;
}
This way you have the caller provide a source string, an destination
character array and a length, and it'll write into the destination
array.
Notice, if a source is to be treated as read-only, it should always be
a const parameter (like I changed source_str to be.)
A better way, though, if possible, is to just return a string object,
or fill in a user-provided string (reference).
Quote
After I made the "strbuf" variable global, the warning
disappeared.
That is fraught with its own different kinds of problems. For
example, calling your function twice will have the 2nd invocation
overwrite the first invocation's results.
Quote
In the case below I don't get a warning on the return.
I don't know about the Windows API, but I'm always leary of code that
casts data with C-style pointers. Also, be sure that you own the
memory returned from the windows call your you might have another
problem similar to your previous one. (And you still have the problem
of the caller potentially leaking the result if he forgets to release
the resource correctly.)
--
Chris (TeamB);
 

Re:How to point my pointers

"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
Quote
size_t bytes = strncpy(dest_str, source_str, dest_len);
strncpy() returns a char* that points to the destination buffer. It does
not return a size_t.
Quote
I don't know about the Windows API, but I'm always leary of
code that casts data with C-style pointers.
GlobalLock() returns a void*, so some kind of cast is needed, whether C- or
C++- style.
Gambit
 

Re:How to point my pointers

"Remy Lebeau \(TeamB\)" < XXXX@XXXXX.COM >writes:
Quote
"Chris Uzdavinis (TeamB)" < XXXX@XXXXX.COM >wrote in message
news: XXXX@XXXXX.COM ...

>size_t bytes = strncpy(dest_str, source_str, dest_len);

strncpy() returns a char* that points to the destination buffer. It does
not return a size_t.
Ah, you're right. I mixed that up with another function, I think
sprintf, excpet sprintf returns an int, not a size_t.
Is it worth mentioning that I didn't sleep well last night? :)
--
Chris (TeamB);
 

Re:How to point my pointers

Hi!
Chris Uzdavinis (TeamB) wrote:
Quote
Is it worth mentioning that I didn't sleep well last night? :)
<looking at the simley>does this make you happy?
*g*
Frank