The section “Using a Segment Variable” on page 81 describes dynamic allocation of based data using the run-time library functions. Microsoft C/C++ also allows you to statically declare data that is based in a specified segment.
There are three ways to specify that data is declared in a particular segment: by specifying a named segment, by using a segment variable, and by using the address of another variable.
Data Stored in a Named Segment
You can specify a named segment that a variable is to be stored in by using the __segname keyword and a string literal. Note that the syntax for this is the same as that used to base a pointer on a named segment. For example,
/* Compile in Small Model */
#include <stdio.h>
#include <malloc.h>
char __based(__segname(“_CODE”)) mystring[] = “A code-based string.\n”;
int __based(__segname(“_CODE”)) myint = 12345;
void main()
{
printf( “%Fs %d”, (char __far *)mystring, myint );
}
The variable mystring is declared as an array of characters based in the code segment. The variable myint is an integer that is also based in the code segment.
Note that the small-model version of printf would treat mystring as a near pointer. The F in the format specifier %Fs forces the function to treat mystring as a far pointer, and the cast to char __far* coerces the address to four bytes.
One reason for placing data in your code segment is that you are using the small memory model and your default data segment is full. Rather than move up to the compact memory model, which makes all data pointers far, you can move some data into the code segment, if you have room there.
You can also name your own segments. For example,
char __based(__segname(“MYSEGMENT”)) otherstring[] = “Another based string.\n”;
This declaration creates a new segment called MYSEGMENT and places the string there. You can reference data in that segment using far pointers or pointers based on that named segment.
If the segment names ends in _TEXT, the compiler marks that segment as a code segment, making it a read-only segment.
Data Based on a Segment Variable
You can also declare data that is based on a segment variable. Data declared this way is stored at a location determined at run time. This is useful if you want to make some variables relocatable. When you move the block of memory containing the variables, you can simply assign a new value to the segment variable. This lets you access the variables by name, rather than by using pointers.
The following example demonstrates how to declare data based on a segment variable:
// FILE1.C
char __far c;
__segment segvar;
main()
{
segvar = (__segment)&c;
foo();
.
.
.
// relocate segment, assign new value to segvar
.
.
.
foo();
}
// FILE2.C
extern __segment segvar;
extern char __based(segvar) c;
foo()
{
c = 1; // can refer to c, no matter where it is
}
The compiler uses the segment value stored in segvar whenever c is accessed in FILE2.C.
Data Based on the Address of Another Variable
You can also allocate data in the same segment as another based variable. To do this, cast the address of the variable to the __segment data type. Note that this is the same syntax used to base a pointer on the segment in which a variable is stored. For example,
int __based(__segname(“MYSEGMENT”)) myint1;
int __based((__segment)&myvar1) myint2;
The variable whose segment is being used must itself be based on a named segment.