|
It is not rubbish, in my test (VS2012 ). It is pointer to the C1 object, having the same address of its first data member (m_Data ) in this simple case, so everything goes right (of course if you insert, before m_Data , another member variable, for instance an int , the sprintf gets some garbage).
In the linked MSDN page they indded suggest to explicitely cast the CString object when used as sprintf parameter.
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
Interesting. I used VS2010 Express, and copying OP's code, it copies the entire object onto the stack, thus the 'pointer' is garbage. When I use a cast it pushes the address of the object onto the stack and works as it should. More testing required ...
|
|
|
|
|
See my answer to OP below.
|
|
|
|
|
Well I have noticed,
VC 2012 has different parsing and scanning rules than earlier versions. The question is: Did the rules change in the standard, or was it incorrectly implemented by Microsoft.
Bram van Kampen
|
|
|
|
|
OK, I finally figured it out. CString is a bit more of a sophisticated class, and will not use a fixed length buffer for its data. It uses a dynamically allocated one, and as long as that is the first data item in the class definition, the sprintf call will work; although it is luck rather than anything else. You can check this out with the following code:
class C1
{
public:
C1()
{
m_Data = (char*)malloc(100);
sprintf(m_Data,"C1 class");
}
operator char *() { return m_Data; }
private:
char* m_Data;
};
When you now use the object without the cast, it just copies the object's data onto the stack, and since this data is a pointer to the actual text it all works as you expect. But be aware that this may have unintended consequences, so always use the cast when you want this behaviour.
|
|
|
|
|
However, I don't see the difference on my system (that is it works with m_Data as provided in the OP).
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
Definitely different for me, it only worked with the modified code.
|
|
|
|
|
And apparently the 'strange case' is mine.
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
Well it can't be just you, there must be something else that is not obvious that happens in your compiler. I only managed to work out what was happening on my system by getting the assembler listing from the compiler, so maybe your version of the compiler is different from the two I used.
|
|
|
|
|
Richard MacCutchan wrote: although it is luck rather than anything else
The class has been that way for a very long time because I remember being mystified by exactly the same thing a long, long time ago.
I think when I looked at source for the class it was also set up in such a way that there was in fact basically one data member (there was some tricky code going on.) So even if you used it in the middle everything still works.
Because of that I wonder if there has been a deliberate effort to insure that behavior (versus luck.)
|
|
|
|
|
I thought this was done on pupose on CString for this very reason... (not sure if you mean the luck part referring to CString)
|
|
|
|
|
Albert Holguin wrote: I thought this was done on pupose on CString for this very reason... (not sure if you mean the luck part referring to CString)
Yes that is what I meant - I was supposing that it was possible that it was planned that way from the start.
|
|
|
|
|
Cool! thank you very much Richard.
|
|
|
|
|
Hello
I am a beginner.
i follow dialog split tutorial.
But,
after move the split bar, split bar wasn't refresh.
plz help me
|
|
|
|
|
You should post your note at the very tutorial page, or, at least, post here a link of such tutorial.
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
Hi,
i am confused about the return value of the clock_getres functions. I am running on custom hw with armv4 cpu and kernel version 2.6.26.
I get values 7812500 (nanoseconds) for CLOCK_REALTIME and CLOCK_MONOTONIC.
Can i trust that the resolution of gettimeofday (uses CLOCK_REALTIME?) calls is ~7.8ms? Does the CPU clock speed affect this value?
Regards
ele lont
|
|
|
|
|
Most time functions have a resolution that is about on this order of magnitude. I've read somewhere that on most current systems the resolution is about 10-20ms, but 7.8ms sounds entirely reasonable too. And no, CPU speed doesn't matter.
Note that there are also functions for high-res time measurement. There is plenty of info about it on the web
GOTOs are a bit like wire coat hangers: they tend to breed in the darkness, such that where there once were few, eventually there are many, and the program's architecture collapses beneath them. (Fran Poretto)
|
|
|
|
|
You should. However you could also make a test.
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
|
|
|
<pre lang="text">
Could someone please help me to find my bug.
This is C++ code "running" on Arduino.
It compiles and runs ,but...
I am using a struct to define / collect data which belong together.
The bug is when I enter a character array (using pointer) into the structure variable, also a character array.
The actual variable I am having problem with is ctextPrompts. I am sure there will be more, but this is the first bug.
It is entered properly - verified by test code immediately after - see TOK here note.
However, when I initialize next member of the struture cTextEntry - it wipes out the ctextPrompts.
Initializing next structure member ctextEmulate puts ctextEmulate characters into ctextPrompts.
This is my first attempt to utilize pointers and structure and I MUST have done something really stupid to cause this bug.
I am using LCD to debug the code.
Since the rest of the code works as expected I am pretty sure it is not a "memory" issue, I do verify the size of available RAM on initialization.
I doubt it is a Arduino compiler issue, just plain wrong usage of pointers which I just do not see.
I do apologize for the long code, but I feel it would help to see the debbuging attempts I have made so far.
Thanks for your help.
Cheers
Vaclav
PS While testing I am using both pointer (*) and indexing [0] with same results
</pre>char
*ctextEntry[] ={
" ", " "," " };
// emulating data
char *ctextEmulate[] = { // emulate entries
"14260123 ", // start frequency
"14360000 ", // end frequency
"10000 ", // step frequency
"1 ", // step speed
"1 ", // 0 single shot 1 repeat
"Option" //
}; // temporary not completed
char *ctextPrompts[] ={
"Start frequency ","End frequency ","Step frequency ","Step speed ","Single / Repeat","Optional "};
typedef struct DataRecordTAG
{
char *cPrompts[]; // prompt text
char *cEmulate[]; // emulate input
char *cEntry[]; // response
char cTEST;
int iIndex;
}
DataRecord;
DataRecord Record[DATA_STRUCT]; // variable
int igRecordIndex = 0; // global access to records
.......
void InitializeRecords(void)
{
// changed to global igRecordIndex igRecordIndex
// igRecordIndex
// initialize prompts and some test entries
int iPromptIndex = 0;
for(igRecordIndex = 0; igRecordIndex != DATA_STRUCT ; igRecordIndex++) // fence post error Optional missing
{
Record[igRecordIndex].iIndex = igRecordIndex; //test index not really needed
/* TOK
#ifdef FLOW_LCD
lcd.clear();
lcd.print("Record[igRecordIndex].iIndex"); //too long
lcd.setCursor(0,1);
lcd.print(Record[igRecordIndex].iIndex); // too long
delay(DELAY_LCD);
#endif
*/
#ifdef FLOW_LCD
TOK verified
lcd.clear();
lcd.print("cPrompts empty ");
lcd.setCursor(0,1);
lcd.print(*Record[0].cPrompts);
delay(5*DELAY_LCD);
#endif
// prompt bug
*Record[igRecordIndex].cPrompts = ctextPrompts[igRecordIndex];
//ReadRecords();
#ifdef FLOW_LCD
TOK here
lcd.clear();
lcd.print("cPrompts entered");
lcd.setCursor(0,1);
lcd.print(*Record[0].cPrompts);
delay(5*DELAY_LCD);
#endif
/*
// BUG writes over previous record how ??
for(int i = 0; i < DATA_STRUCT; i++)
{
#ifdef FLOW_LCD
lcd.clear();
lcd.print("igRecordIndex");
lcd.setCursor(0,1);
lcd.print(igRecordIndex);
delay(DELAY_LCD);
lcd.clear();
lcd.print("Record[i].cPrompts");
lcd.setCursor(0,1);
lcd.print(*Record[i].cPrompts);
delay(5*DELAY_LCD);
#endif
}
// BUG writes over previous record how ??
*/
/* TOK
#ifdef FLOW_LCD
lcd.clear();
lcd.print("Record[igRecordIndex].cPrompts"); //too long
lcd.setCursor(0,1);
lcd.print(*Record[igRecordIndex].cPrompts); // too long
delay(DELAY_LCD);
#endif
*/
Record[igRecordIndex].cEntry[0] = ctextEntry[igRecordIndex]; // [DIGITS]
#ifdef FLOW_LCD
BUG now the cPrompts is empty
lcd.clear();
lcd.print("cText entered");
lcd.setCursor(0,1);
lcd.print(*Record[0].cPrompts);
delay(5*DELAY_LCD);
#endif
*Record[igRecordIndex].cEmulate = ctextEmulate[igRecordIndex]; // emulate input
#ifdef FLOW_LCD
BUG the cPrompts contains ctextEmulate - index 0
lcd.clear();
lcd.print("ctextEmulate entered");
lcd.setCursor(0,1);
lcd.print(*Record[0].cPrompts);
delay(5*DELAY_LCD);
#endif
/* TOK
#ifdef FLOW_LCD
lcd.clear();
lcd.print("Emulate "); //too long
lcd.setCursor(0,1);
lcd.print(Record[igRecordIndex].cEmulate); // too long
delay(DELAY_LCD);
#endif
*/
}
igRecordIndex = 0;
ReadRecords();
for(;;);
/* TOK
#ifdef FLOW_SERIAL
Serial.println("Prompts initialized DONE ");
#endif
#ifdef FLOW_LCD
lcd.clear();
lcd.print("Prompts initialized DONE ");
delay(DELAY_LCD);
#endif
*/
}
|
|
|
|
|
Quote: *Record[igRecordIndex].cPrompts = ctextPrompts[igRecordIndex];
What are you doing with this line?
THESE PEOPLE REALLY BOTHER ME!! How can they know what you should do without knowing what you want done?!?!
-- C++ FQA Lite
|
|
|
|
|
Initializing the struct member cPrompts (char array) from ctextPrompts (char array).
According to next verification code it works.
But than things go crazy as described.
|
|
|
|
|
There maybe be several bugs, but I believe you should remove the []:
ypedef struct DataRecordTAG
{
char *cPrompts;
char *cEmulate;
char *cEntry;
char cTEST;
int iIndex;
}
|
|
|
|