Author Topic: Pointer declartion (non-volatile memory) initialization (volatile memory)  (Read 1216 times)

0 Members and 1 Guest are viewing this topic.

Offline zer0c00lTopic starter

  • Contributor
  • Posts: 27
  • Country: us
Consider a struct with the following data members

Code: [Select]
struct Data
{
   unsigned int  count;
   const char   *Name;
};

A variable of type Data is created later in the code

Code: [Select]
PERSISTENT(struct Data log);
where PERSISTENT() maps variable to the battery backed SRAM memory space

When *Name is later assigned to in the code
Code: [Select]
log.Name = "Sensor1"; where does the character string Sensor1 gets stored. The pointer *Name is stored in battery backed SRAM, but does the string it points to gets stored in MCU memory?. If that is the case if the MCU is restarted the string gets lost, but the pointer (stored in battery backed SRAM) still points to that address which is empty now. Would that be the case?

 

Online helius

  • Super Contributor
  • ***
  • Posts: 3786
  • Country: us
Re: Pointer declartion (non-volatile memory) initialization (volatile memory)
« Reply #1 on: November 23, 2020, 12:29:43 am »
The string is a literal part of the code, so the usual thing that happens is to put it in program ROM, or flash. However, if this compiled code is being loaded by some method other than running out of ROM, such as a bootloader or debugger probe, it could be stored in RAM.

If you had assigned log.Name to a non-literal, it would be in RAM as you described. The compiler cannot know the size of the string eventually assigned to the pointer, so it cannot allocate space for it in battery-backed RAM, of course.
 
The following users thanked this post: zer0c00l

Offline Nominal Animal

  • Super Contributor
  • ***
  • Posts: 8349
  • Country: fi
    • My home page and email address
Re: Pointer declartion (non-volatile memory) initialization (volatile memory)
« Reply #2 on: November 23, 2020, 03:25:08 am »
Whether log.Name points to RAM or Flash after log.Name = "Literal"; , can actually be manipulated by the C linker, especially if using ELF-based tools.  This is because string literals are stored in a specific ELF section, typically rodata.strx.y, and the linker can choose where it actually ends up; typically rodata.

What helius wrote above, matches basically all hosted environments (those where you write normal C application code).

In the Arduino environment, depending on the core (AVR or one of the 32-bit ARMs), one can change this easily.  For example, log.Name = F("Literal"); ensures the string is in Flash, whereas normally log.Name = "Literal"; causes the string literal to be in RAM.

A better option is to use an enum ("enumeration constant") instead.  For example,
Code: [Select]
typedef  enum {
    DATA_NAME_UNKNOWN = 0,
    DATA_NAME_FOO,
    DATA_NAME_BAR,
    DATA_NAME_WHOTSITS,
    DATA_NAME_NOMINAL,
    DATA_NAME_ANIMAL,
    DATA_NAME_IS,
    DATA_NAME_STUPID,
    DATA_NAME_ETC,
    DATA_NAME_MAX = DATA_NAME_ETC
}  data_name;
typedef  int  data_type;

struct data {
    data_type  count;
    data_name  name;
};
If you don't assign any specific values to the enums, the compiler will assign one in ascending order.  In the code, they are equivalent to the integer constant values assigned to them. It is common to have the first one (or "invalid"/"unused" or similar) as zero, and a maximum as the last one, so that one can check if e.g. int i matches a known enum: if (i >= 0 && i <= DATA_NAME_MAX) { /* Within valid range */ } else { /* Outside valid range */ }.

Furthermore, if you use a variable of some enum type as the argument to switch(), most C compilers will warn you if you forget one of the constants (and do not have a default: case).  Very useful, don't you agree?



In some C library code, you'll see enums defined thus:
Code: [Select]
enum {
    FOO = 1,
#define FOO FOO
    BAR,
#define BAR BAR
    BAZ,
#define BAZ BAZ
};
In C, enums are an integer type, and can be used in expressions without any explicit casts.  The reason why one would define a preprocessor macro with the same name as an enum constant, is that that way, the library user can check if a constant is known via #if defined(BAR) ... #endif .  This is very useful for modular portable code, which can check if features are available at compile time or not.
 
The following users thanked this post: zer0c00l


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf

 

-->