Pastey start of memstruct docs
- Posted by mattlewis (admin) Jul 08, 2011
Memory Structures
Introduction
Writing Euphoria code to interact with the operating system or external libraries often requires communicating via data structures stored in memory. In addition to using peeks and pokes to read and write to memory locations, Euphoria programmers can also define structures that can be used to more easily read and write values from and into memory.
The conventions used are similar to those found in the C programming language, since that's the way the most commonly encountered structures are defined and meant to be used. This is meant to provide a familiar syntax to those who already know C, and also to make it easy to define and use memory structures.
Basic Syntax
There are two keywords for defining memory structures: memstruct and memunion. They are similar, except a memstruct is a way to define a data structure that may contain many different, distinct elements, while a memunion (just like a union in C) is a way to refer to the same locations in memory in different ways (e.g., either as an integer or as a floating point number).
Within a memstruct or memunion, different elements are defined using names for data types along with some data type modifiers.
memstruct
memstruct is used to declare a memory based structure to be used by a Euphoria program. The format is similar to other declarations:
memstruct foo int a unsigned int b pointer int c end foo
Normal scope rules apply to memstruct definitions, and so they can be local, export, public or global. The members are laid out in memory sequentially, though based on their sizes, Euphoria may add some space in between members, just like a C compiler would.
The size of a memstruct may be determined at runtime using sizeof().
memstructs may contain other memstructs or pointers to other memstructs.
memunion
A memunion is like a memstruct, except that the various data members of a memunion are all located in the same place. A memunion, like a union in C, provides different ways to interpret the same location in memory.
memunion conversion int i float f double d end memunion
The size of a memunion may be determined at runtime using sizeof().
char
A char is a data type that is 1 byte long. Elements of type char are considered to be signed by default. The range of a signed char is -128 to 127. An unsigned char has a range of 0 - 255. They can only be declared inside of a memstruct or memunion.
memstruct char_types char c -- signed by default, -128 - 127 unsigned char uc -- 0 - 255 signed char sc -- -128 - 127 end memstruct
short
A short is a data type that is 2 bytes long. Elements of type short are considered to be signed by default. The range of a signed short is −32,768 to 32,767. An unsigned short has a range of 0 - 65,535. They can only be declared inside of a memstruct or memunion.
memstruct char_types short s -- signed by default, −32,768 to 32,767 unsigned short us -- −32,768 to 32,767 signed short ss -- −32,768 to 32,767 end memstruct
int
An int is a data type that is 4 bytes long. Elements of type int are considered to be signed by default. The range of a signed int is −2,147,483,648 to 2,147,483,647. An unsigned int has a range of 0 - 4,294,967,295. They can only be declared inside of a memstruct or memunion.
memstruct char_types int i -- signed by default, −2,147,483,648 to 2,147,483,647 unsigned int ui -- 0 - 4,294,967,295 signed int si -- −2,147,483,648 to 2,147,483,647 end memstruct
long
A long (can also be long int) varies in size based on the platform. On Windows and 32-bit Unix like operating systems, a long is 4 bytes, or the same size as an int. On 64-bit Unix-like operating systems, a long is 64-bits, or the same size as a long long.
long long
A long long (can also be long long int) is an integer that is 8 bytes (64-bits) in size. By default, it is signed (−9,223,372,036,854,775,808 to 9,223,372,036,854,775,807). An unsigned long long varies from 0 to 18,446,744,073,709,551,615.
object (memstruct)
An object, in a memstruct or memunion, is an integer the same size as a Euphoria object, and is also the same size as a pointer. By default, it is signed, but can be declared unsigned.
float
A float is a 32-bit floating point number, just like those used by atom_to_float32 and float32_to_atom.
double
A double is a 64-bit floating point number, just like those used by atom_to_float64 and float64_to_atom. This is the size of floating point numbers used by 32-bit Euphoria.
long double
A long double is an 80-bit floating point number, just like those used by atom_to_float80 and float80_to_atom. This is the size of floating point numbers used by 64-bit Euphoria. Although they only use 80 bits, in memstructs they require 16 bytes of storage for alignment purposes.
eudouble
A eudouble is a platform independent floating point data type. On 32-bit Euphoria, a eudouble is the same size (64-bits) as a double. On 64-bit Euphoria, it is 80 bits, the same size as a long double.
pointer
Data members may have the pointer modifier prepended to their declaration. This signifies that the memstruct contains a pointer to that type of element, rather than the element itself.
signed
Integer data types may be signed or unsiged. The default is to be signed, but this can be made explicit by using the signed modifier.
unsigned
Integer data types may be signed or unsiged. The default is to be signed, but to use an unsigned integer type, use the unsigned modifier.
Using memstructs
To use a memstruct requires a pointer to the memory where the structure is stored. This can be created by allocate(), or as the result of a call to an external library. No type information is ever stored with the pointer. Instead, the memory may be manipulated using a dot notation, where the name of the memstruct follows the pointer, and the names of data elements
Example:
include std/machine.e memstruct point int x int y end memstruct memstruct rect point upper_left point lower_right end memstruct atom my_rect = allocate( sizeof( rect ) ) my_rect.upper_left.x = 50 my_rect.upper_left.y = 100 my_rect.lower_right.x = 125 my_rect.lower_right.y = 150 ? my_rect.lower_right.x -- outputs 125
1. Comment by Vinoba Jul 08, 2011
It would be nice to further elaborate on the use of "these things" for simpletons like me.
Actually I have begun to realize the need and use of "these things". I don't know if you have studied the practical aspects of Windows which addresses a finite amount of memory (?3 GB). Many computer come today with 16GB or more. Instead of letting Bill Gates play "Dog in the manger" with this memory, you should take control of it and define ways of communicating between HIS memory and your memory. PAE is one URL I discovered- I have a couple more URLs stored, but can't access them right away. I WAS going to use the instructions therein inc combination with PEEK and POKE to create something - I don't know what!.......Vinoba.
http://en.wikipedia.org/wiki/Physical_Address_Extension
http://ubuntuforums.org/showthread.php?t=855511
2. Comment by Insolor Jul 10, 2011
If these types (char,int etc.) will be usable outside of structs? Something like this:
atom i = allocate(sizeof(int)) i.int = 123465 -- was poke4(i,123465)