3

I know that the global variable is stored in memory, and the local variable is saved in the stack, and the stack will be destroyed after each use.

But I do not know how an array is saved in memory. I tried to declare a global array:

  int tab[5]={10,9,12,34,30};

and at the end I read the contents of the memory, I mean, that after the execution of the code, I read the contents of the memory, (e.g I'm working on a microcontroller, and I know where the data is saving) when I declare a global variable for example a = 10; and when I read the contents of the memory I find the value 10 in the memory, but I do not find the content of the table that is 10,9,12,34,30

I want to understand where the array content is it save in memory?

I work on Aurix Infineon, and I use Hightec as a compiler, I execute my code directly on the aurix, I read the memorition like this:

const volatile unsigned char * mem_start = 0xd0000000;
#define size ((ptrdiff_t) 0xfff)
unsigned char bufferf [size];
code ();
main(){
    ... 
    for (int e = 0; e < sizeof (bufferf); e ++) 
        bufferf [e] = * (mem_start + e); // read memory
}
Rbn
  • 69
  • 8
  • I found in the memoir all the variable declared in global, but I did not find the table and its contents in the memory. What did you mean? How did you check? – Christina Jacob Jun 19 '19 at 13:16
  • What do you mean by *did not find the table and its contents in the memory*? – GalAbra Jun 19 '19 at 13:16
  • 5
    I'm not really sure what you are asking, but this might be helpful: [A program uses different regions of memory for static objects, automatic objects, and dynamically allocated objects](https://stackoverflow.com/questions/52855674/a-program-uses-different-regions-of-memory-for-static-objects-automatic-objects). – Lundin Jun 19 '19 at 13:16
  • I mean, that after the execution of the code, I read the contents of the memory, (e.g I'm working on a microcontroller, and I know where the data is saving) in I declare a global variable for example a = 10; when I read the contents of the memory I find the value 10 in the memory, but I do not find the content of the table that is 10,9,12,34,30 – Rbn Jun 19 '19 at 13:22
  • 2
    Normally, arrays are stored in the same area of memory as any other variable type defined at the same point in the program source. If it is a global or static array, it will be stored in the data segment; if it is local to a function (and not static) it will be stored on the stack. – Jonathan Leffler Jun 19 '19 at 13:23
  • Also a good overview : [Difference between static memory allocation and dynamic memory allocation](https://stackoverflow.com/questions/8385322/difference-between-static-memory-allocation-and-dynamic-memory-allocation) – Sander De Dycker Jun 19 '19 at 13:27
  • 1
    Also, is there some code that uses the array? It could be optimized away if it is not used. (And even if it is used, the optimizer might still not store it in a way you would expect, if it can produce the same result in other ways.) – Arkku Jun 19 '19 at 13:33
  • 1. What microcontroller are you using? 2. What compiler are you using? 3. How are you executing the program? 4. How are you viewing the memory? –  Jun 19 '19 at 13:35
  • @David I work on Aurix infineon, and I use Hightec as a compiler, I execute my code directly on the aurix, I read the memorition like this: const volatile unsigned char * mem_start = 0xd0000000; #define size ((ptrdiff_t) 0xfff) unsigned char bufferf [size]; code (); main(){ ... . .. .. for (int e = 0; e – Rbn Jun 19 '19 at 13:42
  • 1
    @Rbn As a quick observation, even if we disregard the undefined behaviour there, if the entire size of usable memory is indeed `size`, then `char bufferf[size]` cannot possibly fit in there together with `int e` and everything else. Also, why would you need to copy it into the `bufferf`, when you could just use `mem_start[e]` directly? On the other hand, if `size` is not the size of the entire memory, then you are not reading the entire memory… – Arkku Jun 19 '19 at 13:49
  • 1
    (Also, if `bufferf` is stored in the same memory as whatever you are searching for, and there isn't enough memory for both – which there can't be if `size` is the total available memory size – you may well overwrite whatever you are searching for by writing to `bufferf`, which may overlap with it due to lack of space.) – Arkku Jun 19 '19 at 13:53
  • Where does `0xd0000000` come from? –  Jun 19 '19 at 16:56
  • 1
    For one thing you're reading memory as bytes but your array is ints, so there will be extra zero bytes in memory. Have you printed the address of the array and looked there? – Lee Daniel Crocker Jun 19 '19 at 17:45
  • @Lee Daniel yes c true it has many zero when I read the memory, what can I do to avoid that – Rbn Jun 20 '19 at 08:43
  • @Arkku Yes you are right, but how can I read and display the memory without the print in a buffer – Rbn Jun 20 '19 at 08:51
  • @Rbn If `size` is the size of the memory and it starts at `mem_start`, then `mem_start` itself is already a pointer to an array of `size` bytes, so you can use `mem_start` exactly as you would use `buffer_f` (with the exception that `sizeof mem_start` is not `size`, but since you already know `size`, it doesn't matter). – Arkku Jun 20 '19 at 10:01

3 Answers3

1
global variable is stored in memory, and the local variable is saved in the stack

This is false.

Global variables are sometimes kept in registers, not only in static memory.

If the function is recursive the compiler may choose to use the stack or not. If the function is tail recursive it is no need to use the stack as there is no continuation after the function returns and one can use the current frame for the next call.

There are mechanical methods to convert the code in continuation passing style and in this equivalent form it is evaluated stackless.

There are lots of mathematical models of computation and not all use the stack. The code can be converted from one model to other keeping the same result after evaluation.

You got these informations from books written in the 70s, 80s and in the meantime the process of evaluation of code was much improved (using methods that were theoretical in the 30s but nowadays are implemented in systems).

alinsoar
  • 15,386
  • 4
  • 57
  • 74
  • Thank you for your quick reply does that mean I can run my code without using the stack? – Rbn Jun 19 '19 at 13:35
  • 2
    @Rbn this means that in thinking your code you should not care if the compiler will use the stack or not. – alinsoar Jun 19 '19 at 13:36
1

The answer to the question of where arrays, or indeed any variables, are stored depends on whether you are considering the abstract machine or the real hardware. The C standard specifies how things work on the abstract machine, but a conforming compiler is free to do something else on the real hardware (e.g., due to optimization) if the observable effects are the same.

(On the abstract machine, arrays are generally stored in the same place as other variables declared in the same scope would be.)

For example, a variable might be placed in a register instead of the stack, or it might be optimized away completely. As a programmer you generally shouldn't care about this, since you can also just consider the abstract machine. (Admittedly there may be some cases where you do care about it, and on microcontrollers with very limited RAM one reason might be that you have to be very frugal about using the stack, etc.)

As for your code for reading the memory: it cannot possibly work. If size is the size of the memory available to variables, you cannot fit the array bufferf[size] in that memory together with everything else.

Fortunately, copying the contents of the memory to a separate buffer is not needed. Consider your line bufferf[e] = *(mem_start + e) – since you can already read an arbitrary index e from memory at mem_start, you can use *(mem_start + e) (or, better, mem_start[e], which is exactly equivalent) directly everywhere you would use bufferf[e]! Just treat mem_start as pointing to the first element of an array of size bytes.

Also note that if you are programmatically searching for the contents of the array tab, its elements are ints, so they are more than one byte each – you won't simply find five adjacent bytes with those values.

(Then again, you can also just take the address of tab[0] and find out where it is stored, i.e., ((unsigned char *) tab) - mem_start is the index of tab in mem_start. However, here observing it may change things due to the aforementioned optimization.)

Arkku
  • 41,011
  • 10
  • 62
  • 84
  • thank you very much you helped me too much, you helped me understand things and gave me ideas – Rbn Jun 20 '19 at 13:21
0

This program may get you closer to what you want:

int tab[] = {10, 9, 12, 34, 30};

// Used to get the number of elements in an array
#define ARRAY_SIZE(array) \
    (sizeof(array) / sizeof(array[0]))

// Used to suppress compiler warnings about unused variables
#define UNUSED(x) \
    (void)(x)

int main(void) {
    int *tab_ptr;
    int tab_copy[ARRAY_SIZE(tab)];
    tab_ptr = tab;
    UNUSED(tab_ptr);
    for (int index = 0; index < ARRAY_SIZE(tab_copy); index++) {
        tab_copy[index] = tab[index];
    }
    return 0;
}

I don't have the Hightec environment to test this, nor do I have an Aurix to run it on. However, this may give you a starting point that helps you obtain the information you desire.

It looks like the Infineon Aurix is a 32-bit little-endian machine. This means that an int will be 32-bits wide and the first byte will store the first 8 bits of the value. For example, the value 10 would be stored like this:

0a 00 00 00

If you try to read this memory as char, you will get 0x0a, 0x00, 0x00, and 0x00.

  • you can explain to me more what is it doing this code, I did not understand these 2 linens #define ARRAY_SIZE(array) \ (sizeof(array) / sizeof(array[0])) #define UNUSED(x) \ (void)(x) – Rbn Jun 20 '19 at 13:24