C++ discussion (was "Arduino Question")

Go To Last Post
64 posts / 0 new

Pages

Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

continuing the discussion from
https://www.avrfreaks.net/index.p...

This UART interrupt code for C++ is an unbuffered UART ISR. It overloads the "display" function (if my jargon is right). A ring-buffered version uses the code, below, to derive a buffered "display", again overloading. And something similar for UART input.

What I see missing in this ISR is the customary UART transmit interrupt- where the transmit ISR pulls the next byte from the ring buffer and sends it to the chip, then dismisses the interrupt. If there are no more bytes in the buffer, the ISR customarily sets a flag to tell the non-interrupt code that it must later store the first byte in the hardware to cause the first interrupt; then clear the flag.

the code
m_readyToTx(true);

seems to set a flag that the ISR occurred due to transmit complete, but the ISR didn't pull the next byte and send to hardware. Or did it.

All this arcane code, overloading, etc. for OOP, to me yields very non-obvious code and invisible actions. This seems contrary to what I like to code: blatantly obvious what's happening so I (or others) can understand the code a year later. Gee, I don't even like C macros for the same reason!

But I will press on, with help from you guys, and hope others can benefit.

/*	
*	Uart.cpp */

#include "Uart.hpp"
#include 

static UART* s_uart[1];

// Create a UART with no buffers
UART::UART(uint32_t baud, FuncPtru08 rx_func) :
	DISPLAY(),
	m_readyToTx(true),
	m_rx_func(rx_func)
{
	s_uart[0]=this;

	// enable transmit, receive and interrupts
	outb(UCR, BV(RXCIE)|BV(TXCIE)|BV(RXEN)|BV(TXEN));
	SetBaudRate(baud);
	
	sei();
}


void UART::display(uint8_t c){
	// wait for the transmitter to be ready
	while(!m_readyToTx)
		{};


	// send byte
	m_readyToTx = false;
	outb(UDR, c);

	// set ready state to FALSE
	//m_readyToTx = false;

	// the byte will be sent in the background
}

// UART Transmit complete
UART_INTERRUPT_HANDLER(SIG_UART_TRANS)
{
	UART* uart=s_uart[0];


	uart->transmitComplete();
}



void UART::transmitComplete(){

	// indicate transmit complete, back to ready
	m_readyToTx = true;
}



// UART Receive Complete Interrupt Handler
UART_INTERRUPT_HANDLER(SIG_UART_RECV)
{
	// get received char
	uint8_t c = inb(UDR);

	UART* uart = s_uart[0];

	uart->receiveComplete(c);

}

void UART::receiveComplete(uint8_t c){

	// if there's a user function to handle this receive event
	if(m_rx_func)
	{
		// call it and pass the received data
		m_rx_func(c);
	}
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Does this mean that C++ for Linux or Windows (or is that C# for system software?) uses some proprietary/custom kludge for ISRs?

As I see it: No. Those systems face the same principal problem. When an interrupt is generated it can not, in general, be known which object should be passed via the this-pointer.

So they either must go with the solution with an "all-static object", or combine C and C++ (e.g. as in your code).

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Does this mean that C++ for Linux or Windows (or is that C# for system software?) uses some proprietary/custom kludge for ISRs?

How many end users ever actually provide an ISR in Windows/Linux code? To do it in Linux (and this is true in Windows too) the code must run at ring 0 which means it is part of the kernel. In Linux this is achieved with an insmod/modprobe'd driver or the code is actually built into the kernel tree itself and the kernel is rebuilt. If you pull the source of Linux you are going to be very hard pressed to find ANY C++ being used in it. And certainly not for interrupt handlers. Now maybe in the "hidden world" of Windows kernel things are different and the kernel is in C++ not C and I imagine it's built with MSVC++ and I guess that for their own purposes M$ may have added mechanisms to that compiler if they felt the need (after all they own both the kernel and the compiler!). Anyone who's recently used the M$ DDK for Windows (it's ~20 years since I last did!) will know whether developer supplied ISRs in .drv and .sys files can be done in C or C++. Perhaps they can enlighten us but I'm guessing most DDK work is still done in C not C++.

PS I originally posted this to the original thread but just realised it was more appropriate here so I moved it.

PPS after a bit of googling around it appears that vmirqd.zip towards the bottom of this page contains a Windows IRQ handler in C++

http://www.techsoftpl.com/vxd/sa...

I cannot follow it so don't know whether this solves the issue you are trying to resolve here :cry: :?

BTW see also:

http://www.osronline.com/article...
(follow the link to the M$ .doc file - it is VERY interesting - though note it was written in 2004)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Now maybe in the "hidden world" of Windows kernel things are different and the kernel is in C++ not C

For the windows "kernel", I'd speculate that it's in C. The UI might be partly in C++, though..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

For the windows "kernel", I'd speculate that it's in C

Me too. We may be up to version 7 but I'll bet the core is pretty much similar to when M$ made the switch from Win16 to Win32 in Windows 3 back in the late 80's. It's the same reason that the Linux kernel is all in C - the majority of the core is decades old.

Wonder if anyone can think of a protect mode operating system who's core isn't decades old? QNX? No. Symbian? No. OSX? No. Android? No.

I imagine, unless a new OS has been written for new silicon in the last decade the cores are all going to have been done in C yonks ago. I cannot think of an OS that fits that bill.

So maybe AVR ISRs in C++ are at the bleedin' edge in fact? ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

I'll bet the core is pretty much similar to when M$ made the switch from Win16 to Win32 in Windows 3 back in the late 80's.

I bet the core that started out as Win16 is pretty dead by now. Last time it was rehauled was in Windows ME.

W2K, XP, Vista and beyond stems from the NT "track". Not much in common with the W95 "kernel" if I am well informed.

But, yes, the NT kernel was also definitively C. C++ was in it's infancy or, maybe early teens, when NT was constructed.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

But, yes, the NT kernel was also definitively C

Yes even that dates from 1993. So a mere 18 years old. While C++ was around I doubt it was being used much for systems rather than application engineering at that time. Even that M$ document from 2004 is very wary about using C++ as any more than a "super C" with stronger syntax checking and that was 11 years after the release of NT 3.1

I guess it is true that the big selling point for Vista was that it had "completely rewritten kernel" and that's why all the XP drivers had to be re-engineered. So I guess there's a chance that the Vista and "7" kernel's may have more C++ content.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So- in my quest to learn C++ for apps that use interrupt driven I/O - where I have 100% of all the source code (that's the way I do things)...
I recalled that I have an AVR Teensy I and Teensy II board. Did a bunch of C code for them. Spectacular little inexpensive goodies they are.

http://www.pjrc.com/teensy/teens...
and that Paul, the brains behind Teensy has a an absolutely brilliant integration of the Teensy bootloader (USB based) and the Audino 2.2 IDE.
Reading a little- tried it. Worked first try. Gotcha is that you must use his "Beta Test 0.93" version to work with the current Arduino release.

So now I'll explore how ISRs are done in the Arduino libraries. I hope it's properly done and not some hacks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

So now I'll explore how ISRs are done in the Arduino libraries. I hope it's properly done and not some hacks.

See HardwareSerial.cpp for an example:

inline void store_char(unsigned char c, ring_buffer *rx_buffer)
{
  int i = (rx_buffer->head + 1) % RX_BUFFER_SIZE;

  // if we should be storing the received character into the location
  // just before the tail (meaning that the head would advance to the
  // current location of the tail), we're about to overflow the buffer
  // and so we don't write the character or advance the head.
  if (i != rx_buffer->tail) {
    rx_buffer->buffer[rx_buffer->head] = c;
    rx_buffer->head = i;
  }
}

#if defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)

SIGNAL(SIG_USART0_RECV)
{
  unsigned char c = UDR0;
  store_char(c, &rx_buffer);
}

SIGNAL(SIG_USART1_RECV)
{
  unsigned char c = UDR1;
  store_char(c, &rx_buffer1);
}

SIGNAL(SIG_USART2_RECV)
{
  unsigned char c = UDR2;
  store_char(c, &rx_buffer2);
}

SIGNAL(SIG_USART3_RECV)
{
  unsigned char c = UDR3;
  store_char(c, &rx_buffer3);
}

#else

#if defined(__AVR_ATmega8__)
SIGNAL(SIG_UART_RECV)
#else
SIGNAL(USART_RX_vect)
#endif
{
#if defined(__AVR_ATmega8__)
  unsigned char c = UDR;
#else
  unsigned char c = UDR0;
#endif
  store_char(c, &rx_buffer);
}

#endif

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So... Unless you edited a surrounding classs out there Cliff, it seems that Arduino uses non-class-member functions for ISRs. It's more or less plain C.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It's more or less plain C.

That would seem to be the size of it. ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good. No bloat then.. :wink:

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

No bloat then

Well I was going to say that calling the same function from four ISR()s was not exactly "bloat proof" but at least the author had the good sense to put the destination routine in the same .cpp file as the ISRs themselves so it *should* be ale to see that it doesn't need to push/pop the entire machine state in each case - then again this is Arduino and they clearly don't care about large/bloaty code ;-)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You do understand that my comment was tongue-in-cheek I hope, Cliff?

Meanwhile I've found some material on C++ and ISRs. Last time I spoke (posted) before thinking, and it didn't go well. This time I'll swap those activities. My brain is not so fast anymore but hopefully you'll hear more eventually..

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Indeed, the currently proliferated Ardino libraries have a UART handler that does interrupt driven, buffered UART receive. But the UART transmit in not interrupt driven and does not buffer. Wow, the transmit routine is simply a busy-loop on UART data register empty.

Wow, that busy-loop would screw up a lot, in many applications.

The Arduino volunteer author for that code says by email that well, it's OK. Who cares?

well, given it's all freeware, who's to complain!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Ah, in my quest to learn C++ interrupt handlers... I found that the standard Arduino UART code (serial class) uses a busy-loop for UART transmit rather than interrupt driven/buffered output. Not so hot.

Enclosed, is the UART class from Paul TeensyAVR (http://www.pjrc.com/teensy). It does buffered TX and RX. Nice clean code for me to use an example.
You can download from his web site the Arduino support for Teensy 1 and Teensy 2 and in that is the "HardwareSerial" cpp and .h of which I speak.

On the Teensy hardware, the Auduino library's "serial" class is mapped to the USB port on the Teensy, as a virtual COM port on the PC side.
The hardware UART1 is a different class, on the Teensy's.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I saw this in C++ and wondered if anyone here can guess as to what the heck it is. The square brackets in this context are new to me.

getFrameData()[1] 

my quest with C++ continues. I've gotten some code to run. But as I look at it, gee, it is obtuse, abstract and dumb, as compared to vanilla C. I took some buffered UART I/O code, interrupt driven, from C. Warped its functions into a c++ class, made c++ functions and data hiding. Then after a lot of hours, figured out how to get the the C ISR to work with the c++ class instance. Then I did a timer interrupt routine and a C++ class for it, with a tick count accessible to both C and C++.

I compared the asm code for the timer to increment a ticker that's volatile/static in C and one that's volatile but in the c++ class. One instruction larger in c++, if the class is static (compile time). Now, I coded the timer class to be created at run time with new() which calls malloc. And changed the tick count increment, and calls to the class member functions to use a pointer to the instance of the class. This done, the code grew by one more asm instruction, due to the double-indirection: one to get the address of the class and one more to get the data element within the class.

Without using compiler magic of inheritance and overloaded functions and operators, the code size isn't any larger than the equivalent C code using structures, where a function pointer is in the stuct along with variables. With a small memory micro, I'm not sure it makes sense to try for the aforementioned compiler magic in c++. But what I've done is, yes professor, object oriented I guess.

(I'm using IAR, not GCC).

But I press on, as c++ for small micros is popular, and I will not give in (yet) to old fogey-ness.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I would assume that the getFrameData function is doing one of two things, either returning a pointer to an array or returning an object ( or object reference ) that overloads the subscripting operator ( [] )... a FrameData object perhaps. Either way it is doing just what would be expected from C, accessing data in the "frame data" at a specified index ( assuming of course that this isn't a case of misapplying operator overloading, in which case it could be doing ANYTHING! ).

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hmm. C++ and overloading. The more I see of it, the less I like it. It is nice, applied to concatenate strings in an expression like str1 = str2 + str3
where the + operator does magic in the string class.

But really, as a C++ newbie, I see some really too-cute use of operator and function overloading.

I can't get used to the idea that one can look at code, as in the example in the prior post, and not know what it does. There's no standard syntax. Yuck.

Or I'm a fogey.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Almost any language allows you to use it badls.

For operator overloading the choice of what to overload and which operator to overload should be done so that it is "natural". Overloading "+" for string concatenation is the most obvious example.

For function overloading the clearness should come out of the names and types of the function and the parameters.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
getFrameData()[1]

Can we see more of the context of that particular syntax? Is that an entire statement? (; missed I guess?) or is that part of an assignment or what?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The code is in an mbed online library for the XBee. There are several XBee libs there; the one in question is authored by Mr. Suga. It appears that the item in square brackets is some overloading/contortion saying that the function returns the [nth] byte of a data frame. Wow, how would one figure out this?

uint16_t ZBTxStatusResponse::getRemoteAddress() {
    return  (getFrameData()[1] << 8) + getFrameData()[2];
}

I see declarations for getFrameData() with void arguments and with a byte value. Don't see any tricks with the []
like

virtual uint8_t getFrameData(uint8_t pos);
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Locate the prototype for getFrameData(). What does it return? That is what the [] operator operates on, so that type should have an [] operator.

EDIT: I would not be surprised if it returned a pointer (e.g. uint8_t*), which is used as an array.

I did a small C test/demo. Here's a mockup function returning a pointer to chars in some buffer:

char * getChars()
{
    static char theChars[] = "Some characters";
    return theChars;
}

Now, what would you get if you did

    char theChar = getChars()[2];

? And What does the [] operator operate on in this case?

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Now, what would you get if you did

    char theChar = getChars()[2];

?

Quote:
And What does the [] operator operate on in this case?

This is the question. I'll keep looking for a func prototype that has [] within it; didn't find it in the header file for that class. But I am a novice at C++ and overloading.

(though I do well at overloading at meals)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Now, what would you get if you did

    char theChar = getChars()[2];

?


The subscript has nothing to do with the function call. I like to think of the return value as "replacing" the function call. In Johan's example, the return value is a char * - just a standard C string. The result is the same as if you used the subscripting operator on the string directly. Another way to look at it would be to expand the code to each level of operation.

char * theString = getChars();
char theChar = theString[2];

Now, assuming the string "Some characters" from the previous example, we just find index two ( "Some characters" ) and theChar == 'm'. Nothing different from C, no magic involved.

Returning to the original question, the getFrameData() function must return either a type that has an overloaded subscripting operator or ( more likely given the function name ) a pointer to the data in a frame ( very likely unit8_t * or char * ). An integer return value is not possible because integers have no subscripting operator support and C++ does not allow you to overload POD types.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I looked at the xbee.cpp/h source but didn't see any overloaded operators. It may be in the source code that holds the ZBTxStatusResponse class (which I can't seem to find).

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:
I'll keep looking for a func prototype that has [] within it
Operator overloading is defined (within a class definition) using the operator keyword, e.g.:
int operator[](int i) { return a[i]; }

I suspect that the earlier conjecture about the function returning a pointer is spot on.

Don Kinzer
ZBasic Microcontrollers
http://www.zbasic.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

JohanEkdahl wrote:

    char theChar = getChars()[2];

Or
char theChar = 2[getChars()];

(you wrote somthing like that a couple of months ago). It's standard c too. No C++ magic at all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

one way to create C++ interrupt object is like this. not the best but give you an idea.

// implement a singleton object
class intobj {
public:
   intobj(); // contructor (ctor)
   virtual ~intobj(); // destructor (dtor)
static void isr(void); // ISR handler
...
   void RealHanhler(voi);

private:
static intobj *g_selfobj; // this is single global instance
   intobj *pOtherintobj; // if daisy chain require
....
};

in .cpp code

// single self instance of your int object
static intobj::g_selfobj = NULL;

// ctor
intobj::intobj():
   pOtherintobj(NULL)
{
   if (g_selfobj)
   {
       // previous instance exists, save it
       pOtherintobj = g_selfobj;
   }

   g_selfobj = this; // save the new instance
}

// dtor
intobj::~intobj()
{
   // restor previous obj
   if (g_selfobj == this)
      g_selfobj = pOtherintobj;
   // else management code to release daisy chained obj.  
}

static intobj:isr(void)
{
   if (g_selfobj)
      g_selfobj->RealHandler();
}

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
uint8_t* XBeeResponse::getFrameData() {
    return _frameDataPtr;
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Code:
char * getChars()
{
static char theChars[] = "Some characters";
return theChars;
}

Now, what would you get if you did
Code:
char theChar = getChars()[2];
? And What does the [] operator operate on in this case?

you'll get compilation error.

operator does not operate on method. It operates on object. Second your is a normal function not a class method.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Now, what would you get if you did
Code:
char theChar = getChars()[2];

...

you'll get compilation error.

No, you won't. The above code is equivilant to

char theChar = (getChars())[2];

Which ends up as something like,

char theChar = ( ( char * ) p )[2];

Which is perfectly valid ( and normal ) code.

This all works just the same regardless of whether it is a class ( static ) method, instance method, or free function.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ah yes, you are right, my mistake. getChars() returns a pointer to an object so the casting is valid. It would be an error if getChars() does not return a pointer.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh man, that code is too abstract for my current state of mind! Dear Lord, with all this overloading, how can anyone understand what was done a year later?

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

There is no overloading at all in that statement, it is just straight C.

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Using the overloaded operator [] instead probable would have made it more readable.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As atomicdog said, this may have actually been a time when operator overloading would have been preferable from a readability point of view ( I am not sure it would have improved understandability however ). This is ( has been ) a case where standard C syntax that is unknown has caused quite a bit of trouble ( the subscripting visually attached to a function call ) where nothing mysterious is, in fact, happening. The advantage ( in this case ) to overloading the subscripting operator would be that instead of,

response.getFrameData()[2]

you would only have,

response[2]

As a "response" is a set of data bytes there is no ambiguity about what the subscripting should do. True, with the ability to overload operators the programmer could do something stupid instead of the obvious, but that is no different than some of the syntax abuses I have seen in pure C ( especially related to excessively nested macros, or improper naming).

Though this was not, in fact, a case of operator overloading, the point of operator overloading is not to make the implementation of the library code more understandable. In fact, it is to make its use more understandable. Many of C++'s more advanced syntactic features make the initial implementation more complex, but make the final use cleaner. Thus, it makes the code easier for the user to use, but it does make it more difficult for those not well versed in the idioms and syntax to understand from an implementation point of view.

Based on this I can answer the question "how does can anyone understand what was done a year later?" If overloading is done properly ( again, this is not a case of overloading, and this argument holds just as well for other C++ syntactic constructs ) the function of the overloading is precisely what is logical. If a function is overloaded to take int, float, string and object parameters, its function must be the same except for specialized handling of the passed in type, otherwise - you are right - it is impossible to understand after time has passed. But how would that differ from plain C with functions that have similar names and wildly different functions? Similarly, overloading operators should only be done in such a way that the result is "the expected". For the subscript operator that means that it should act like an array; for arithmetic operators, there are other requirements that should be met. If overloading is done correctly, it is no more difficult to understand the function of overloaded functions or methods than it is with the multiply-named functions of C. Initialization is initialization, addition is addition and clear is clear - C++ says that you should not have to worry about the details in understanding the program at first glance.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

My point with the example was that the notation

   func()

is fully valid C. The subject is not overloading. The subject is "what does the [] operator operate on". For some reason Steve has decided in his mind that it "is tied" to the function. It is not.

What if I did

   char * p = GetChars();
   char c = p[2];

No trouble with that, I hope? That is just a two-line equivalent of my first C example.

And definitively no overloading.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

yeah, you have prove the point of readability of the code. Not only syntax but naming as well. My mistake was that I read getChars() so in my mind was a char not a string. I did pay attention to the rest, although you did put an 's' to the function. If the function was named getString then I would have been less confusing.

How many time any of you had go back to read your own code after a long while and say "why the hell did I do that" or "what did I want to do here" ...

It's come down to code readability, no matter the language. Whether C, Pascal, Ada, etc... you can messed up quite easily as the code grow bigger and bigger.

One thing I know by experience, spaghetti code in procedural programming, you can still able to understand it. Spaghetti object code, you'll be lost in that jungle.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh, come on! I posted the complete definition of the GetChars() function. The return type is absolutely clear from that. Anything can be confusing if you don't read it all.

Quote:
One thing I know by experience, spaghetti code in procedural programming, you can still able to understand it. Spaghetti object code, you'll be lost in that jungle.

Congratulations. Understanding ones personal abilities is always a plus.

But all this is beside the point, which was:

1) The notation function()[] that stevech stumbled upon probably has nothing to do with operator overloading.

2) I constructed the C example to show that the notation stevech stumbled upon can be done in C also, and C has no operator overloading.

3) I contructed the second, alternative, code snippet to try to show what was really going on.

I will try to make myself even clearer by doing away with chars and arrays in a third example involving only ints. Here goes, steve:

Say you have a function

int GetInt()
{
   return 42;
}

and you then do

int anInt = GetInt()+7;

Now, you would not go hunting for a function GetInt that also has a '+' involved with it, no?

My point is the + is an operator acting on what the function returns. Likewise, in the earlier example the [] is an operator operating on what GetChars() returns.

Do you follow me now, stevech?

EDIT: Corrected typo.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

Last Edited: Sat. Feb 12, 2011 - 05:51 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
The advantage ( in this case ) to overloading the subscriptingoperator
response[2]

But how is this better than:

response(2)

Quote:
i
nt anInt = GetInt+7;

Now, you would not go hunting for a function GetInt that also has a '+' involved with it, no?

No, not with that line of code ;)

Regards,
Steve A.

The Board helps those that help themselves.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If the pointer was public the author could have accessed the pointer directly without overloading (even though that's generally considered bad OOP style). The overloaded [] operator would allow access to protected/private variables since it's basically a member function of the class. I'm not sure if that counts as bad OOP style since it looks like the pointer is being accessed directly even though it really is through a function.

protected:
    // pointer to frameData
    uint8_t* _frameDataPtr;
uint16_t ZBTxStatusResponse::getRemoteAddress() {
    return  (_frameDataPtr[1] << 8) + _frameDataPtr[2];
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

No, not with that line of code Wink

Fixed.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Can I be a complete noob (and yes I know I should search!) but while I've got you all here can I ask what are the best texts for a reasonably competent C programmer to transition to C++ (yet again)?

Cliff

(all the better if they're all on Amazon so I can make a composite order)

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff!

I my mind, transitioning from C to C++ is not merely a syntax/semantics thing. It is a shift of paradigm. Alas, I have not stumbled over any book that leads you on the path from procedural programming in C to object-oriented programming in C++.

Anyway..

I actually haven't read it, but if Bruce Eckel's "Thinking in C++" is of the same quality as his "Thinking in Java" then it's decent to quite good. The good thing is that you can download a electronic copy of the book without loosing your honesty. Go here: http://www.mindview.net/Books/TI... .

I've had the intention to d/l and browse those two volumes for quite a while now. Might as well d/l right now..

Bjarne Stroustrup's book is not recommended as a tutoring text, if you ask me.

I've had my eyes on these ones too:
http://www.amazon.com/Primer-4th...
http://www.amazon.com/C-Primer-P...
,but haven't gotten around to ordering any of them.

And once again - the notation

func(params)

is not specific to C++ (it is valid plain old C). In stevech's original problem operator overloading might have been involved, but not necessarily.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

It is a shift of paradigm. Alas, I have not stumbled over any book that leads you on the path from procedural programming in C to object-oriented programming in C++.

Oh I've done that when I taught myself Java - it's learning the syntax that I need help with.
Quote:

is not specific to C++ (it is valid plain old C)

Yup, I realise that now - though you'd agree it's "unusual" (which is why I mistakenly presumed it was C++ specific). Personally I think the author should be shot as it adds nothing to the readability/maintainability of the code. It's the sort of thing to save for the annual obfuscation contests.

PS Thanks for the book recommendations.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Cliff!

Not recommendations, as in "I think they are good". All are books that I have had the intention to actually check out for quite some time.

As of January 15, 2018, Site fix-up work has begun! Now do your part and report any bugs or deficiencies here

No guarantees, but if we don't report problems they won't get much of  a chance to be fixed! Details/discussions at link given just above.

 

"Some questions have no answers."[C Baird] "There comes a point where the spoon-feeding has to stop and the independent thinking has to start." [C Lawson] "There are always ways to disagree, without being disagreeable."[E Weddington] "Words represent concepts. Use the wrong words, communicate the wrong concept." [J Morin] "Persistence only goes so far if you set yourself up for failure." [Kartman]

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I learned quite a bit of my C++ syntax from the "C++ Black Book" by Steven Holzner. It does the job for syntax just fine, but I found it lost relevance quickly; instead, I find that I reach for "The C++ Standard Library Reference" ( Josuttis ) or "Standard C++ IOStreams and Locales" ( Langer and Kreft ). Then there's always the standard, of course, and the related technical reports that outline the "whys" of the syntax. I've actually found that my memory for the syntax is better if I understand it better.

Though, having listed these, I guess I would have to say that I have not found a book that I feel is an excellent introduction to C++ syntax - either the books are entry-programmer-level books that miss syntax, or they are overly terse with the expectation of prior C++ knowledge - the black book is something of a compromise.

Edit - regarding response(2) vs response[2]:

@Koshchi
I was, of course, assuming that "response" was an object, an instance of a class. It would contain the response data and bound operations on that data. Therefore, the function syntax would require overloading of the () operator. I'm not sure what the understood semantics would be for turning a response frame into a function. With overloading [], for the second option, the semantics are much more obvious - accessing a sub-unit. In the end, if it comes down to the difference of response.get(2) and response[2], I would choose overloading the subscripting operator every time.

Martin Jay McKee

As with most things in engineering, the answer is an unabashed, "It depends."

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
My point is the + is an operator acting on what the function returns. Likewise, in the earlier example the [] is an operator operating on what GetChars() returns.

Yes, I follow that getChar() + 7; is an expression in C or C++. I am surprised that the default use of [] as in getchar() [7]; is addition. Wouldn't there have to be code to create such an arcane, obtuse and deceptive use of [] as an operator?


My lifetime of asm and C in team software engineering has me predisposed to absolutely avoid code that isn't self-documenting and obvious. I even dislike over-use of C macros. If one of my subordinates did a lot of code with obtuse operator overloading, as an old fogey, I'd can the person, in preference to those that don't use cute code tricks. We're employed to work efficiently and remember that 2/3 of software life cycle costs are after design and coding.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

My lifetime of asm and C in team software engineering has me predisposed to absolutely avoid code that isn't self-documenting and obvious. I even dislike over-use of C macros. If one of my subordinates did a lot of code with obtuse operator overloading, as an old fogey, I'd can the person, in preference to those that don't use cute code tricks. We're employed to work efficiently and remember that 2/3 of software life cycle costs are after design and coding.

100% with you. Same mind set as you. Always tell my sub to make it readable so when you go back to it in a year are so, you still understand the code you wrote. That is not to say someone else has to work with it when you moved on to another project. The clearer the code is, the less you have write documentation for it, the less time you have to spend to explain it.

One of the first thing they teach you in C programming is to avoid use macro as possible. In C++ object programming also tell you to not to use macro at all.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

stevech wrote:
Quote:
My point is the + is an operator acting on what the function returns. Likewise, in the earlier example the [] is an operator operating on what GetChars() returns.

Yes, I follow that getChar() + 7; is an expression in C or C++. I am surprised that the default use of [] as in getchar() [7]; is addition. Wouldn't there have to be code to create such an arcane, obtuse and deceptive use of [] as an operator?
I think you misunderstand what Johan was saying. The [] operator isn't being used for addition. It's just the plain old boring c/c++ array sub-scripting square brackets.

Pages