avr-c++ micro how-to

Last post
93 posts / 0 new

Pages

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

Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:

#include 

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}

That's almost all. Almost because if you are using gcc 4.x and newer (I didn't check it with older versions) and you want to use templates, virtual inheritance and so on you must define some additional functions, which is not used now by compiler, but must be present to satisfy linker:

__extension__ typedef int __guard __attribute__((mode (__DI__)));

extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);

Please be sure to define these functions exactly as I showed, I other case gcc could crash during compilation (segmentation fault!), and for sure your program WILL BE NOT working.
Implementation is as follow (very important too):

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

And last thing, if you use pure virtual functions you must define another function:

extern "C" void __cxa_pure_virtual(void);

and implementation:

void __cxa_pure_virtual(void) {};

This function is never called in normal operation. The only time this function may get called is if the application calls a virtual function while the object is still being created, which gives undefined behavior. So implementation is not very important for us.
With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.

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

Brilliant!

Attention moderators! Sticky candidate?

"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]

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

At the very least I thought Tomasz ought to repost this as a tutorial in the Tutorial Forum so it's doesn't get "lost"

 

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

Also, someone put the term "CPlusPlus" in it so that it can be found by the search function. Oh look, someone just did :)

Regards,
Steve A.

The Board helps those that help themselves.

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

I don't have any of the cxa stuff. I never heard of it. My virtual functions aren't pure though.

The only problem I have with virtual functions is they use a huge amount of RAM and quite a bit of program memory also.

I'm currently using gcc version 4.1.2.

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

These array handlers may be useful too:

void * operator new[](size_t size) 
{ 
    return malloc(size); 
} 

void operator delete[](void * ptr) 
{ 
    free(ptr); 
} 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

except the spurious semicolons that generate errors in pedantic + ansi mode,

int __cxa_guard_acquire(__guard *g) {return !*(char *)(g);};
void __cxa_guard_release (__guard *g) {*(char *)g = 1;};
void __cxa_guard_abort (__guard *) {};

,
you just made a top grade post.

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?

BTW in order to help newbies finding the g++ and make quicker, here is my example of Project Options/External tools that worked for me:
I:\WinAVR-20071221\bin\avr-g++.exe
I:\WinAVR-20071221\utils\bin\make.exe

The last trap is in the fact that by default printf is not supporting float numbers. However because the C++ projects can be complex, it is wise to go to Project Options/Libraries section, you might want to include
libprintf_flt
libscanf_flt
libc
libm
libobjc
but NOT libprintf_min, libscanf_min

BTW I remember the problem, when a simple code

int main()
{
	DDRC=0xFF;
	for(;;)
	{
		PORTC=0xFF;
		_delay_us(1);
		PORTC=0x00;
		_delay_us(1);
	}
}

...was not working just because I have been instancing a static class object in one of include files. It took me the whole night to find the problem, hopefully my suspicions pointed onto global objects very early. The funny part was, that everything worked when the project was big. Once I have simplified (!!!) main() function to the code above, it stopped working (freeze before main). I have hunted down the statically instantiated class in one of includes, and moved it as static object to main().
This time, however, it started complaining about lacking __cxa_guard_acquire, __cxa_guard_release.
So remember, when you make static class object in global scope, without providing these functions, the code will fail silently, depending on the actual size of the project and many other factors.

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

kbosak wrote:

I would also add '-fno-exceptions' and maybe '-ansi --pedantic -Wall' to avoid shooting ourselves in the foot. g++ AVR is uncharted minefield. Any other flags to include?

These will help with the code size.

-ffunction-sections 
-Wl,--gc-sections 

http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=64513

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

TFrancuz wrote:
Hi everybody,
a couple of months ago I started with AVR and c++. It's rather painful adventure, but now most of things seems to work. So I decided to share my little experience, maybe it will be useful for you.
First thing – setup. I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work. Remember that if you want to debug your application you need rather to turn off code optimization (-O0). In other case debugging is extremely hard thing to do and confusing. Final compilation can be done with any optimization options.
Next thing to do is to define new and delete operators:

#include 

void * operator new(size_t size);
void operator delete(void * ptr);

and implementation:

void * operator new(size_t size)
{
  return malloc(size);
}

void operator delete(void * ptr)
{
  free(ptr);
}

That's almost all.
... (abridged) ...

With all this things defined I was able to compile my c++ programs without any problems, and I wish the same to you.
Greetings,
Tomasz.

This is pretty impressive (I thought I knew a thing or two about C++, but "guard"s are a new one on me).

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

One thing I think you have missed, though, is that delete operators are supposed to safely do nothing if they're passed a NULL pointer. So your sample implementation of delete should look like this:

void operator delete(void * ptr)
{
  if (ptr)
    free(ptr);
}


This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.
BTW for nitpickers that like excess safety, the code should be:

if(ptr!=NULL)
{
    free(ptr);
}

because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.

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

Quote:
because (oh there are long and useless discussions about that) NULL dont have to be 0 numerically.
Actually NULL has to be 0 in C++ (and many C++ programmers avoid using NULL).

http://www.research.att.com/~bs/bs_faq2.html#null
/Lars

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

kbosak wrote:

This is a surprise to me. I always believed since 1990 that free(NULL) is always OK, even if I almost never wrote code using this. http://www.winehq.org/pipermail/wine-patches/2006-October/031544.html
says:
ANSI-C Standard:
----------------
The ANSI standard ANSI X3.159-1989 "Programming Language C." specifies
that free(NULL) is a no op.
"free deallocates the space pointed to by p: it does nothing if p is NULL."
Quoted from "The C Programming Language" second edition by Kernighan and
Ritchie with the subtitle "ANSI C".

This would indicate that your protection is superfluous.

Wualll, I'll be darned. This is one of those superstitious "safety measure" habits that reinforce themselves; like wearing a Shriners hat to ward off flying squirrel attacks. You wear the hat, and voilla! no squirrels! After awhile, the two seem to be correlated. No particular harm done, but you DO look silly..

I'd always assumed that free()ing NULL was bad medicine, and even have dim recollection of crash dumps from our embedded code when it tried to do so (but we used an extremely old compiler). Anyway, I thought the safety of delete-ing NULL pointers was unique to C++.

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

Quote:
and many C++ programmers avoid using NULL

I am sorry but this is void* argument.
Most programmers are not compiler developers and most compiler developers don't care aboutev erything the Standard says, not to mention about being familiar with avr-g++.

There is more than that:

malloc(0)

in practice behaves like

new ptr[0]

The trick is that C++

new ptr[0]

is standard sanctioned: returning NONNULL, properly aligned pointer for a single element!

malloc(0)

returning nonnull may or may not be standard.
This helps implementing some dynamic data structures, I believe.
http://gcc.gnu.org/ml/libstdc++/2005-02/msg00167.html
"
The standard defines that allocators
(and operator new) may be asked for zero bytes. They must return an
address different from any other address that they have returned that
haven't since been released. (That disallows returning 0.) Most
implementations treat a call to operator new(0) identically to operator
new(1).
"

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

The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

It's only when you want to dynamically "churn the heap" that it is required. To put it another way, if the equivalent C program would use malloc and free, then your C++ program would also use them, via new and delete.

Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset. Actually I question if it has any purpose in embedded programs that run on PCs, but I do it just because it's "good practice".

On an AVR, just "new" everything at startup and run with what you have until the end of time or reset/powerdown, whichever comes first.

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

Quote:
Balancing each new with a delete is considered good practice in programs that run on PCs, but it serves no purpose on AVR programs where there is no shutdown except a hardware reset.

Sorry, short-sighted idea. In fact many efficient linear algebra algorithms require special handling of sparse matrices for max speed. This calls for dynamic data structures. In order to keep implementation of those data structures clean, dynamic memory allocation is necessary. This is the major benefit of using C/C++ over FORTRAN in scientific programming. Using advanced linear algebra/geometry/fitting/optimization algoritms is very popular in many areas, just to mention GPS receivers. GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

Let's put it this way: you can get rid of malloc and free completely. But one day, you will write a complex data structure, that uses fixed memory pool. Next day you will find that in runtime this structure hides 20% of innovatory code and 80% of code that immitates malloc's functionality.

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

kbosak wrote:
Sorry, short-sighted idea.

So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.

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

steve17 wrote:
kbosak wrote:
Sorry, short-sighted idea.

So you are saying that any C programmer that doesn't include malloc and free in all his programs is short-sighted?

All I'm saying is C++ doesn't need malloc and free any more than C programs. If a program needs it, use it. Otherwise don't. Of course if you have excessive program memory then it doesn't matter. I rarely find myself in that situation though.


I was commetning this:
Quote:
The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

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

OT:

Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.

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

Broxbourne wrote:
OT:
Quote:
GPS receivers tend to run on ARM7, but simpler versions can easily run on AVR.

That is a somewhat misleading statement. Definition of 'simpler' and 'easily' required.

You can use Student-Lockroom programming to achieve the result.

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

Quote:
You can use Student-Lockroom programming to achieve the result.

Thanks, I didn't know that.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
###############################################################################
# Makefile for the project cpptest
###############################################################################

## General Flags
PROJECT = cpptest
MCU = atmega128
TARGET = cpptest.elf
CC = avr-g++.exe

## Options common to compile, link and assembly rules
COMMON = -mmcu=$(MCU)

## Compile options common for all C compilation units.
CFLAGS = $(COMMON)
CFLAGS += -Wall   --pedantic  -fno-exceptions  -Wl,--gc-sections  -ffunction-sections     -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -ansi 
CFLAGS += -MD -MP -MT $(*F).o -MF dep/$(@F).d 

## Assembly specific flags
ASMFLAGS = $(COMMON)
ASMFLAGS += $(CFLAGS)
ASMFLAGS += -x assembler-with-cpp -Wa,-gdwarf2

## Linker flags
LDFLAGS = $(COMMON)
LDFLAGS +=  -Wl,-Map=cpptest.map


## Intel Hex file production flags
HEX_FLASH_FLAGS = -R .eeprom

HEX_EEPROM_FLAGS = -j .eeprom
HEX_EEPROM_FLAGS += --set-section-flags=.eeprom="alloc,load"
HEX_EEPROM_FLAGS += --change-section-lma .eeprom=0 --no-change-warnings


## Include Directories
INCLUDES = -I"I:\ATMEGA\ATMEGA128\..\..\WinAVR-20071221\avr\include\avr" 

## Libraries
LIBS = -lc -lm -lprintf_flt -lscanf_flt 

## Objects that must be built in order to link
OBJECTS = cpptest.o 

## Objects explicitly added by the user
LINKONLYOBJECTS = 

## Build
all: $(TARGET) cpptest.hex cpptest.eep cpptest.lss size

## Compile
cpptest.o: ../../cpptest.c
	$(CC) $(INCLUDES) $(CFLAGS) -c  $<

##Link
$(TARGET): $(OBJECTS)
	 $(CC) $(LDFLAGS) $(OBJECTS) $(LINKONLYOBJECTS) $(LIBDIRS) $(LIBS) -o $(TARGET)

%.hex: $(TARGET)
	avr-objcopy -O ihex $(HEX_FLASH_FLAGS)  $< $@

%.eep: $(TARGET)
	-avr-objcopy $(HEX_EEPROM_FLAGS) -O ihex $< $@ || exit 0

%.lss: $(TARGET)
	avr-objdump -h -S $< > $@

size: ${TARGET}
	@echo
	@avr-size -C --mcu=${MCU} ${TARGET}

## Clean target
.PHONY: clean
clean:
	-rm -rf $(OBJECTS) cpptest.elf dep/* cpptest.hex cpptest.eep cpptest.lss cpptest.map


## Other dependencies
-include $(shell mkdir dep 2>/dev/null) $(wildcard dep/*)
#include 
#include 

// C++  helpers /////////////////////
#include 
void * operator new(size_t size);
void operator delete(void * ptr); 
void * operator new(size_t size)
{
	return malloc(size);
}
void operator delete(void * ptr)
{
	free(ptr);
}
__extension__ typedef int __guard __attribute__((mode (__DI__)));
extern "C" int __cxa_guard_acquire(__guard *);
extern "C" void __cxa_guard_release (__guard *);
extern "C" void __cxa_guard_abort (__guard *);
int __cxa_guard_acquire(__guard *g)
{
	return !*(char *)(g);
}
void __cxa_guard_release (__guard *g)
{
	*(char *)g = 1;
}
void __cxa_guard_abort (__guard *)
{
}
extern "C" void __cxa_pure_virtual(void);
void __cxa_pure_virtual(void)
{
}
//////////////////////////////////////

class CCCP
{
	float a;
	float b;
public:
	CCCP()
	{
	}
	CCCP(float aarg)
	{
		a=aarg;
	}
};

static CCCP * cccp=NULL;
static CCCP cccp_static(1.2);//This doesn't work

int main()
{
	//cccp=new CCCP();//This doesn't work
	DDRC=0xFF;
	for(;;)
	{
		PORTC=0xFF;
		_delay_ms(50);
		PORTC=0x00;
		_delay_ms(50);
	}
	return 0;
}
Build started 23.6.2008 at 16:25:05
avr-g++.exe -I"I:\ATMEGA\ATMEGA128\..\..\WinAVR-20071221\avr\include\avr"  -mmcu=atmega128 -Wall   --pedantic  -fno-exceptions  -Wl,--gc-sections  -ffunction-sections     -DF_CPU=16000000UL -Os -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enu
ms -ansi -MD -MP -MT cpptest.o -MF dep/cpptest.o.d  -c  ../../cpptest.c

../../cpptest.c:51: warning: 'cccp' defined but not used
avr-g++.exe: --gc-sections: linker input file unused because linking not done
avr-g++.exe -mmcu=atmega128 -Wl,-Map=cpptest.map cpptest.o    -lc -lm -lprintf_flt -lscanf_flt  -o cpptest.elf
avr-objcopy -O ihex -R .eeprom  cpptest.elf cpptest.hex
avr-objcopy -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O ihex cpptest.elf cpptest.eep || exit 0
avr-objdump -h -S cpptest.elf > cpptest.lss

AVR Memory Usage
----------------
Device: atmega128

Program:     900 bytes (0.7% Full)
(.text + .data + .bootloader)

Data:         18 bytes (0.4% Full)
(.data + .bss + .noinit)


Build succeeded with 1 Warnings...
Archive member included because of file (symbol)

i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
                              i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o (exit)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
                              cpptest.o (__do_clear_bss)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
                              cpptest.o (__do_global_ctors)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
                              i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o) (__tablejump__)
i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                              cpptest.o (malloc)

Allocating common symbols
Common symbol       size              file

__brkval            0x2               i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
__flp               0x2               i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)

Memory Configuration

Name             Origin             Length             Attributes
text             0x00000000         0x00020000         xr
data             0x00800060         0x0000ffa0         rw !x
eeprom           0x00810000         0x00010000         rw !x
fuse             0x00820000         0x00000400         rw !x
lock             0x00830000         0x00000400         rw !x
signature        0x00840000         0x00000400         rw !x
*default*        0x00000000         0xffffffff

Linker script and memory map

Address of section .data set to 0x800100
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
LOAD cpptest.o
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libprintf_flt.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libscanf_flt.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libm.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a
LOAD i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a

.hash
 *(.hash)

.dynsym
 *(.dynsym)

.dynstr
 *(.dynstr)

.gnu.version
 *(.gnu.version)

.gnu.version_d
 *(.gnu.version_d)

.gnu.version_r
 *(.gnu.version_r)

.rel.init
 *(.rel.init)

.rela.init
 *(.rela.init)

.rel.text
 *(.rel.text)
 *(.rel.text.*)
 *(.rel.gnu.linkonce.t*)

.rela.text
 *(.rela.text)
 *(.rela.text.*)
 *(.rela.gnu.linkonce.t*)

.rel.fini
 *(.rel.fini)

.rela.fini
 *(.rela.fini)

.rel.rodata
 *(.rel.rodata)
 *(.rel.rodata.*)
 *(.rel.gnu.linkonce.r*)

.rela.rodata
 *(.rela.rodata)
 *(.rela.rodata.*)
 *(.rela.gnu.linkonce.r*)

.rel.data
 *(.rel.data)
 *(.rel.data.*)
 *(.rel.gnu.linkonce.d*)

.rela.data
 *(.rela.data)
 *(.rela.data.*)
 *(.rela.gnu.linkonce.d*)

.rel.ctors
 *(.rel.ctors)

.rela.ctors
 *(.rela.ctors)

.rel.dtors
 *(.rel.dtors)

.rela.dtors
 *(.rela.dtors)

.rel.got
 *(.rel.got)

.rela.got
 *(.rela.got)

.rel.bss
 *(.rel.bss)

.rela.bss
 *(.rela.bss)

.rel.plt
 *(.rel.plt)

.rela.plt
 *(.rela.plt)

.text           0x00000000      0x37e
 *(.vectors)
 .vectors       0x00000000       0x8c i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x00000000                __vectors
                0x00000000                __vector_default
 *(.vectors)
 *(.progmem.gcc*)
 *(.progmem*)
                0x0000008c                . = ALIGN (0x2)
                0x0000008c                __trampolines_start = .
 *(.trampolines)
 .trampolines   0x0000008c        0x0 linker stubs
 *(.trampolines*)
                0x0000008c                __trampolines_end = .
 *(.jumptables)
 *(.jumptables*)
 *(.lowtext)
 *(.lowtext*)
                0x0000008c                __ctors_start = .
 *(.ctors)
 .ctors         0x0000008c        0x2 cpptest.o
                0x0000008e                __ctors_end = .
                0x0000008e                __dtors_start = .
 *(.dtors)
                0x0000008e                __dtors_end = .
 SORT(*)(.ctors)
 SORT(*)(.dtors)
 *(.init0)
 .init0         0x0000008e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x0000008e                __init
 *(.init0)
 *(.init1)
 *(.init1)
 *(.init2)
 .init2         0x0000008e        0xc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 *(.init2)
 *(.init3)
 *(.init3)
 *(.init4)
 .init4         0x0000009a       0x1a i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x0000009a                __do_copy_data
 .init4         0x000000b4       0x10 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
                0x000000b4                __do_clear_bss
 *(.init4)
 *(.init5)
 *(.init5)
 *(.init6)
 .init6         0x000000c4       0x16 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
                0x000000c4                __do_global_ctors
 *(.init6)
 *(.init7)
 *(.init7)
 *(.init8)
 *(.init8)
 *(.init9)
 .init9         0x000000da        0x8 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 *(.init9)
 *(.text)
 .text          0x000000e2        0x4 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
                0x000000e2                __vector_22
                0x000000e2                __vector_28
                0x000000e2                __vector_1
                0x000000e2                __vector_32
                0x000000e2                __vector_34
                0x000000e2                __vector_24
                0x000000e2                __vector_12
                0x000000e2                __bad_interrupt
                0x000000e2                __vector_6
                0x000000e2                __vector_31
                0x000000e2                __vector_3
                0x000000e2                __vector_23
                0x000000e2                __vector_30
                0x000000e2                __vector_25
                0x000000e2                __vector_11
                0x000000e2                __vector_13
                0x000000e2                __vector_17
                0x000000e2                __vector_19
                0x000000e2                __vector_7
                0x000000e2                __vector_27
                0x000000e2                __vector_5
                0x000000e2                __vector_33
                0x000000e2                __vector_4
                0x000000e2                __vector_9
                0x000000e2                __vector_2
                0x000000e2                __vector_21
                0x000000e2                __vector_15
                0x000000e2                __vector_29
                0x000000e2                __vector_8
                0x000000e2                __vector_26
                0x000000e2                __vector_14
                0x000000e2                __vector_10
                0x000000e2                __vector_16
                0x000000e2                __vector_18
                0x000000e2                __vector_20
 .text          0x000000e6        0x0 cpptest.o
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .text          0x000000e6        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .text          0x000000e6      0x1fc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x000000e6                malloc
                0x00000236                free
                0x000002e2                . = ALIGN (0x2)
 *(.text.*)
 .text.__cxa_guard_acquire
                0x000002e2       0x14 cpptest.o
                0x000002e2                __cxa_guard_acquire
 .text.__cxa_guard_release
                0x000002f6        0x8 cpptest.o
                0x000002f6                __cxa_guard_release
 .text.__cxa_guard_abort
                0x000002fe        0x2 cpptest.o
                0x000002fe                __cxa_guard_abort
 .text.__cxa_pure_virtual
                0x00000300        0x2 cpptest.o
                0x00000300                __cxa_pure_virtual
 .text._Z41__static_initialization_and_destruction_0ii
                0x00000302       0x24 cpptest.o
 .text._GLOBAL__I__Znwj
                0x00000326        0xe cpptest.o
 .text._ZdlPv   0x00000334        0x6 cpptest.o
                0x00000334                operator delete(void*)
 .text._Znwj    0x0000033a        0x6 cpptest.o
                0x0000033a                operator new(unsigned int)
 .text.main     0x00000340       0x30 cpptest.o
                0x00000340                main
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .text.libgcc   0x00000370        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .text.libgcc   0x00000370        0xc i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
                0x00000374                __tablejump__
                0x00000370                __tablejump2__
                0x0000037c                . = ALIGN (0x2)
 *(.fini9)
 .fini9         0x0000037c        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
                0x0000037c                exit
                0x0000037c                _exit
 *(.fini9)
 *(.fini8)
 *(.fini8)
 *(.fini7)
 *(.fini7)
 *(.fini6)
 *(.fini6)
 *(.fini5)
 *(.fini5)
 *(.fini4)
 *(.fini4)
 *(.fini3)
 *(.fini3)
 *(.fini2)
 *(.fini2)
 *(.fini1)
 *(.fini1)
 *(.fini0)
 .fini0         0x0000037c        0x2 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 *(.fini0)
                0x0000037e                _etext = .

.data           0x00800100        0x6 load address 0x0000037e
                0x00800100                PROVIDE (__data_start, .)
 *(.data)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 .data          0x00800100        0x0 cpptest.o
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .data          0x00800100        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .data          0x00800100        0x6 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x00800102                __malloc_heap_start
                0x00800104                __malloc_heap_end
                0x00800100                __malloc_margin
 *(.data*)
 *(.rodata)
 *(.rodata*)
 *(.gnu.linkonce.d*)
                0x00800106                . = ALIGN (0x2)
                0x00800106                _edata = .
                0x00800106                PROVIDE (__data_end, .)

.bss            0x00800106        0xc load address 0x00000384
                0x00800106                PROVIDE (__bss_start, .)
 *(.bss)
 .bss           0x00800106        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o
 .bss           0x00800106        0x8 cpptest.o
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_exit.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_clear_bss.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_ctors.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/avr5\libgcc.a(_tablejump.o)
 .bss           0x0080010e        0x0 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
 *(.bss*)
 *(COMMON)
 COMMON         0x0080010e        0x4 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5\libc.a(malloc.o)
                0x0080010e                __brkval
                0x00800110                __flp
                0x00800112                PROVIDE (__bss_end, .)
                0x0000037e                __data_load_start = LOADADDR (.data)
                0x00000384                __data_load_end = (__data_load_start + SIZEOF (.data))

.noinit         0x00800112        0x0
                0x00800112                PROVIDE (__noinit_start, .)
 *(.noinit*)
                0x00800112                PROVIDE (__noinit_end, .)
                0x00800112                _end = .
                0x00800112                PROVIDE (__heap_start, .)

.eeprom         0x00810000        0x0
 *(.eeprom*)
                0x00810000                __eeprom_end = .

.fuse
 *(.fuse)
 *(.lfuse)
 *(.hfuse)
 *(.efuse)

.lock
 *(.lock*)

.signature
 *(.signature*)

.stab           0x00000000      0x414
 *(.stab)
 .stab          0x00000000      0x414 i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o

.stabstr        0x00000000       0x5f
 *(.stabstr)
 .stabstr       0x00000000       0x5f i:/winavr-20071221/bin/../lib/gcc/avr/4.2.2/../../../../avr/lib/avr5/crtm128.o

.stab.excl
 *(.stab.excl)

.stab.exclstr
 *(.stab.exclstr)

.stab.index
 *(.stab.index)

.stab.indexstr
 *(.stab.indexstr)

.comment
 *(.comment)

.debug
 *(.debug)

.line
 *(.line)

.debug_srcinfo
 *(.debug_srcinfo)

.debug_sfnames
 *(.debug_sfnames)

.debug_aranges
 *(.debug_aranges)

.debug_pubnames
 *(.debug_pubnames)

.debug_info
 *(.debug_info)
 *(.gnu.linkonce.wi.*)

.debug_abbrev
 *(.debug_abbrev)

.debug_line
 *(.debug_line)

.debug_frame
 *(.debug_frame)

.debug_str
 *(.debug_str)

.debug_loc
 *(.debug_loc)

.debug_macinfo
 *(.debug_macinfo)
OUTPUT(cpptest.elf elf32-avr)
LOAD linker stubs

After noticing some problems with my larger project, moved back to make to retest simpler code. With all our modifications, the code always hangs! I am surprised. I have tested the code some half a year ago. Creating global instances of classes works only if there are lots of code... Then it works. It means the classes are instantiated in some magic memory areas, overlapping innocent global variables (?).
I have retested so many other details, optimisation options etc. What went wrong?

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

Proposal: alternatively, since our program in G++ for AVR is fully single-threaded by nature, we can define -fno-threadsafe-statics instead of defining __cxa_guard_acquire and friends.

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

kbosak wrote:
Proposal: alternatively, since our program in G++ for AVR is fully single-threaded by nature, we can define -fno-threadsafe-statics instead of defining __cxa_guard_acquire and friends.

That is bad assumption, one can write multi-threaded C++ AVR programs, and even without threads there is a possibility of for recursion involving ISRs. If such situations can occur in our program __cxa_guard_acquire and friends would need to protect against this.

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

Quote:
That is bad assumption, one can write multi-threaded C++ AVR programs, and even without threads there is a possibility of for recursion involving ISRs. If such situations can occur in our program __cxa_guard_acquire and friends would need to protect against this.
True, but note that the __cxa_guard* implementation above is a minimum (dummy) implementation - it does not add any thread safety.
/Lars

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

I think fno-threadsafe-statics is a good solution for a default setting since a lot of programs written for AVR aren't multi-threaded. The only way I see this effecting an ISR is if someone is calling a function in the ISR in which case they could compile that one function without fno-threadsafe-statics and then write their own __cxa_guard* functions. I suppose there are more cases but I think needing __cxa_guard* is more of a special case.

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

TFrancuz wrote:
I use AVR Studio, which is almost working with c++. Almost, because you must manually in project->Configuration options->Custom options set instead of avr-gcc avr-c++.exe to compile any of your c++ files. Just changing the extension to cpp/hpp doesn't work.

Correct me if I'm wrong, but it seems to me that if I create my source file with an upper case C extension instead of lower case AVR-GCC will compile as C++ without the editing mentioned above.

I'm not sure if renameing from .c to .C will work. The file must probably be created with upper case from the beginning.

JHJ

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

You probably need to "remove file(s) from project..", rename to .C and the "add existing source file(s)..." to be sure that Studio makes the right decision about invoking the C++ compiler but otherwise, yes, it sounds like that would be the easy answer.

Cliff

(previously there's been reports of folks having problems the other way round where they've inadvertently used a MAIN.C or something in Studio and ended up getting C++ warnings - so it should work)

 

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

clawson wrote:
You probably need to "remove file(s) from project..", rename to .C and the "add existing source file(s)..." ...

Yes, because Studio refuses changing the extension.

Quote:
... to be sure that Studio makes the right decision about invoking the C++ compiler

No, Studio will still call avr-gcc.
avr-gcc itself makes the decision to use the C++-compiler due to the file name (.C) on the command line.

Stefan Ernst

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

Quote:
No, Studio will still call avr-gcc.
avr-gcc itself makes the decision to use the C++-compiler due to the file name (.C) on the command line.

Thanks for stating the obvious but I know that - the whole point here was to prevent the need to edit the field in Studio where it invokes avr-gcc.exe

 

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

Hmmm, I don't understand but then I don't use AVR Studio to do my builds.

For the record, I find files ending in .cpp get compiled as if they were C++ files, and files ending in .c are compiled as C files.

I never tried .C and I never heard of .hpp, just .h.

My makefile calls avr-gcc.exe

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

Upon converting my code to the C++ project i came across 1 warning about my custom lcd characters:

static const PROGMEM unsigned char customCharacters[] =
{
	//Character 0
	0b00000,
	0b01110,
	0b10001,
	0b11111,
	0b10001,
	0b10001,
	0b01110,
	0b00000,

	//Character 1
	0b00000,
	0b11111,
	0b10000,
	0b10000,
	0b10000,
	0b10000,
	0b11111,
	0b00000
};

Gives: "warning: only initialized variables can be placed into program memory area"

Any thoughts?

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

It's a known bug: http://www.avrfreaks.net/index.php?name=PNphpBB2&file=viewtopic&t=57011&highlight=warning+initialized

Also, doing a web search with the error message will give you links to other reports about that as well as a link to the bug report on the avr-gcc bug tracker.

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

I think I've just found another gotcha in AVR Studio, which hopefully some people may find useful?. (It took me a few hours of Google searching and guessing before I hit on the idea of what was going wrong).

Apparently AVR Studio doesn't support .CPP files. The files need to be called ".c" and not ".cpp" (even though the code in the file is C++).

When CPP files are used, the AVR Studio (V4.14 build 589) fails to generate compile instructions in the makefile for the object file, e.g. it looked like this in the makefile...
## Compile
##Link

But when the .CPP files were renamed to .C it then generated a makefile that looked like this (and compiled ok)...
## Compile
Wire.o: ../Wire.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

ArrayDisplay.o: ../ArrayDisplay.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

LCD1.o: ../LCD1.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

lcd.o: ../lcd.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

twi.o: ../twi.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

VirtualScreen.o: ../VirtualScreen.c
$(CC) $(INCLUDES) $(CFLAGS) -c $<

##Link

In hindsight, its very easy when you know that's what you have to do, but I've not seen it mentioned anywhere, not to call files CPP (which is what I usually use for other non-avr compilers like PC etc.).

I don't know if this is a bug or by design, but anyway, I thought this may help someone? ... (It would have helped me! :P).

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

I'll speculate:

AVR Studio is not case sensitive, and thus recognices both .c and .C as a file type that it thinks it can handle.

WinAVR/avr-gcc on the other hand IS case sensitive as it stems from the GNU/U*ix world, and there are three file types that I've seen used for C++ source files: .C (not to be confused with .c), .cpp and .cxx .

Thus AVR Studio thinks of your source files as C sources, but then passes them to avr-gcc which treats them as C++ source files. (The test you can make is to try to place C++ code in a .c source file, add it to Studio and see what happends. I'll bet that avr-gcc will spit it out.)

Although the approach you have taken seems to work it has the disadvantage that you can not set specific compiler flags for C++ sources different from those you set for C sources (unless you specify them for each file individually). In this sense AVR Studio does not support C++. If you will need special treatment for C++ sources then there is no other way that I know of than to write your own makefile and feed that to AVR Studio.

Here's some gcc documentation that seem to support my speculation:

Quote:
C++ source files conventionally use one of the suffixes `.C', `.cc', `.cpp', `.CPP', `.c++', `.cp', or `.cxx'[...]. GCC recognizes files with these names and compiles them as C++ programs even if you call the compiler the same way as for compiling C programs [...]

And when you are ready for it, learning make is actually not that hard. The documentation is very good: http://www.gnu.org/software/make/manual/

HTH!

"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]

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

I recently faced a situation were I needed a Singleton-like (http://en.wikipedia.org/wiki/Singleton_pattern) object.

template< uint8_t BitNo >
ProtocolHandler< BitNo > &	ProtocolHandler< BitNo >::Machine( )
{
	static ProtocolHandler< BitNo >	machine;
	return	machine;
}

When compiling such code, I was taunted by this error:

Quote:
undefined reference to `atexit'

After some googling, I found this thread:
http://www.embeddedrelated.com/usenet/embedded/show/88449-1.php

Wich provides an easy solution that I want to share here to complete the "micro howto".

///	MCU would never "exit", so atexit can be dummy.
extern "C" void	atexit( void ) { }

And if I am here to collaborate, there are two other functions that can be usefull if one wants to avoid AVR-libc dynamic memory management concerns:

/// Placement new for allocating the object inside a given memory buffer.
void *	operator new( size_t, void * const buff )		{	return	buff;	}

/// Placement delete called automatically on "placement new" failure.
void	operator delete( void * p, void * const buff )	{	}

Quote:
The use of the C++ delete operator in an AVR program is generally a waste of memory, and so is using malloc and free.

I don't think so.
Dynamic memory management is just meant to avoid memory waste.
In situations were the processing is predictive enough and memory consumption is high, I can control when my data is going to use memory, instead of leaving them in RAM all the time - this data can even not fit, so the management is a must.
Of course the management system takes a little memory for itself, but it is generally a small portion of the heap (unless one plan to use the heap for allocating several single bytes, what is definitely not wise...)

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

If the equivalent C program would benefit from using dynamic memory allocation, then the C++ program would also. But I've not encountered any embedded programs where that was the case.

Malloc and free use the heap a little less efficiently and inclusion of the malloc and free code also uses a considerable amount of program memory.

There is nothing in C++ that requires malloc and free, although it might seem that way. That's because most C++ programs run on PCs, where malloc and free are readily available, and most C++ programs are not embedded and do make good use of dynamic memory.

Some people recommed not dynamically allocating and freeing of memory while an embedded program is running. Maybe the heap software today is good enough, but that wasn't always the case.

I worked on a large and expensive embedded program that ran on PCs and had around 45 threads. We could run most of the software on our desktop machines but the customer, the Department of Defense, got ruggedized machines with a compact PCI chassis.

The rule was to allocate all memory at startup, and delete everything at shutdown. The shutdown thing was for the convenience of the programmers. The customer shut it down by powering it off. We used malloc and free, via new and delete, because there was no reason not to do so. These funcions were there and there was plenty of memory. But again, we only used them at startup and shutdown.

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

Not wanting to appear dumb - just starting out on my first serious C++ project - but what is 'Student-Lockroom' programming?

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

Do you have a reference to "Student-Lockroom programming" -- Google only brings up this thread.

Thanks.

Dr. David Harris
OpenLCB Development Team
openlcb.org

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

Dear freaks

any body has a sample project in c++.containing all of stuff like makefile and main c file.
please post it.

I love Digital
and you who involved in it!

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

Quote:
main c file

Why the need for a main C file? As you can't create and use C++ objects from C code this will add an extra layer of calls to the code.

The somewhat simplified truth is that C++ can call C but not the other way around. The slightly more complicated version is: If your main is in a C source file it has "C linkage". It can call a function in a C++ file but that called function also has to have C linkage (which you get by using the extern "C" language construct). This function in turn can create and use C++ objects.

I seems you want a small C/C++ demo, and having a main in C rather than C++ only makes that demo more complicated.

Could you do with a project with a main function in a C++ file?

"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]

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

i mean the c++ main file sorry for that.all i want is a simple c++ demo.

I love Digital
and you who involved in it!

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

This will blink the LED on my Olimex P40 board.

Attachment(s): 

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

thnaks a lot!

I love Digital
and you who involved in it!

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

hey.. i've got a cuestion.. does the c++ compiler support the implicit convertions for integrated types like strings, integers, etc..? For example, when a function argument should be a string, and i pass it a integer, can the convertion be done by the compiler?

Thanks

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

Quote:

For example, when a function argument should be a string, and i pass it a integer, can the convertion be done by the compiler?

Assuming that you by string mean a char * then the answer is no. This is not a pecularity of the avr-gcc compiler. This is how the C++ language is defined.

"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]

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

JohanEkdahl wrote:
Quote:

Assuming that you by string mean a char * then the answer is no. This is not a pecularity of the avr-gcc compiler. This is how the C++ language is defined.

Thanks for the answer.. I'm using the c++.exe file to compile my program instead of avr-gcc.exe (just like TFrancuz says at the fist comment)so it's c++ language(i guess.. :roll: ), and it still doesn't work.. so, is there a way to make it able to work with implicit convertions?

..thanks

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

hey.. has anybody had a problem with strings (char *)? 'cause i'm trying strlen, strcat and itoa.. and they just dont work!!!! maybe there's something i'm doing wrong

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

Quote:

and they just dont work

Shows as small a program as you possibly can that demonstrates them not working as far as you are concerned.

 

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

Quote:

so it's c++ language(i guess.. Rolling Eyes ), and it still doesn't work..

It does not matter if it is C or C++. There is no implicit conversion from int to char * in neither language. What makes you think there is?

And AFAIK the language is determined by the filename extension of the source file. Not that it matters in this case, though. You can easily determine if the compiler thinks it is a C or a C++ file that you are sending to it. Just throw a very simple class into it, eg

class Test
{
public:
   int i;
};

and if it barfs over that then it is C, not C++. There are other methods, including testing if CPLUSPLUS (or some such, I really don't recall and don't have the energy to search the correct preprocessor symbol name out) is defined.

"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]

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

Johan,

I want to drive my Jeep to Tahiti, but Jeeps get pretty poor gas mileage and I'm afraid I won't be able to make it from California to Hawaii so can you tell me how to flag down tankers along the way?

Smiley

FREE TUTORIAL: 'Quick Start Guide for Using the WinAVR C Compiler with ATMEL's AVR Butterfly' AVAILABLE AT: http://www.smileymicros.com

Pages