1

I am trying to safe some program space by trying to reduce the count strings in progmem. So i started to put all stings which are needed multiple times into a file with a namespace:

#include <avr/pgmspace.h>
#ifndef __PSTRINGS__
#define __PSTRINGS__
namespace p_strings
{
//golbal
const char right_arrow[] PROGMEM = ">";
const char procent[] PROGMEM = "%";
const char start[] PROGMEM = "Start";
const char speed[] PROGMEM = "Speed: ";
//... more here
}
#endif

I am using the strings by including them into the file where i need them and for example call Display::out_p(1, 0) << p_strings::right_arrow;. Which reads the byte out of the progmem and put them at the right position of the display. But if i look into the .Iss i see that they are still included multiple times into the ASM.

000000a8 <_ZN9p_stringsL5startE>:
      a8:   53 74 61 72 74 00                                   Start.
...
000000de <_ZN9p_stringsL5startE>:
      de:   53 74 61 72 74 00                                   Start.

So i guess this isnt the right solution to safe storage.

My questions now are:

  1. Why does it still included (in the asm) multiple times? (Maybe some preaty simple failur of my thinking)
  2. How to i create "something" which prevents this? (Do i need somehow a class which i pass as reference?)

If more information is needed let me know.

bemeyer
  • 6,154
  • 4
  • 36
  • 86
  • 1
    As written in the question, I'd expect that to give you linker errors for duplicate symbols. Are the declarations inside a nameless namespace inside `namespace p_strings` (or declared `static`)? (By the way: `__PSTRINGS__` is a reserved symbol that you're not supposed to use unless you're a standard library or compiler.) – Wintermute Apr 07 '15 at 08:57
  • The file is like included in the question above. They are not static just const inside of a namespace in global space. I dont use __ PSTINGS __. Yes they are inside of a nameless namespace inside of the p_string namespace if i understand that right – bemeyer Apr 07 '15 at 08:59
  • I tried making them static which did not change anything of the outcome. – bemeyer Apr 07 '15 at 09:05
  • 1
    Your include guard declares a `__PSTRINGS__` macro, but that is just a timebomb that may explode with the next compiler update -- the error would look different if it were the cause. The nameless namespace has the same effect as declaring them static. Anyway, http://stackoverflow.com/questions/1433204/how-do-i-use-extern-to-share-variables-between-source-files-in-c should answer this in great detail. – Wintermute Apr 07 '15 at 09:10
  • Thanks alot. Ill change the guard for sure. didnt see it. Lets see if i can get it work. – bemeyer Apr 07 '15 at 09:11
  • link time optimizations will do that for you. – sbabbi Apr 07 '15 at 10:24
  • It doesn't. It's optimize with o3 and it is still multiple times in the asm. – bemeyer Apr 07 '15 at 12:14

1 Answers1

1

In C++, a const variable has internal linkage by default (as if it was static)—which normally means that each translation unit (each .cpp file) gets its own copy. This may very well be why you're seeing them multiple times.

What you'd want to do is declare the variables as extern, and then define them in exactly one source file.

Angew is no longer proud of SO
  • 167,307
  • 17
  • 350
  • 455
  • No, they're not static by default. That's a consequence of the nameless namespace OP didn't put into the code in the question but mentioned in the comments. – Wintermute Apr 07 '15 at 09:21
  • 1
    @Wintermute OK, it's not static by default, but it *does* have internal linkage by default. C++11 3.5/3: "A name having namespace scope has internal linkage if it is the name of ... a variable that is explicitly declared `const` or `constexpr` and neither explicitly declared `extern` nor previously declared to have external linkage." – Angew is no longer proud of SO Apr 07 '15 at 10:19
  • So what I have todo is as already mentioned to declare them external in the namespace and declare them once in a cpp and just use them as I do? – bemeyer Apr 07 '15 at 12:13
  • 1
    @BennX That should be it. `extern` declaration in the header, definition in one `.cpp` file. – Angew is no longer proud of SO Apr 07 '15 at 12:17
  • @BennX It needs to be `extern const char right_arrow[]` in the header as well, and needs to be inside the namespace in the `.cpp` file. – Angew is no longer proud of SO Apr 07 '15 at 12:56
  • yea already noticed thanks. To use the PROGMEM it need to be: `extern PROGMEM const char right_arrow[];`and in the cpp `const char p_strings::right_arrow[] = ">";` Thanks! – bemeyer Apr 07 '15 at 12:57