Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
C-sharp language specification.2004.pdf
Скачиваний:
14
Добавлен:
23.08.2013
Размер:
2.55 Mб
Скачать

Chapter 25 Unsafe code

1The order in which members are packed into a struct is unspecified.

2For alignment purposes, there can be unnamed padding at the beginning of a struct, within a struct, and at

3the end of the struct. The contents of the bits used as padding are indeterminate.

4When applied to an operand that has struct type, the result is the total number of bytes in a variable of that

5type, including any padding.

625.6 The fixed statement

7In an unsafe context, the embedded-statement (§15) production permits an additional construct, the fixed

8statement, which is used to “fix” a moveable variable such that its address remains constant for the duration

9of the statement.

10embedded-statement:

11

...

12

fixed-statement

13

fixed-statement:

14

fixed ( pointer-type fixed-pointer-declarators ) embedded-statement

15

fixed-pointer-declarators:

16

fixed-pointer-declarator

17

fixed-pointer-declarators , fixed-pointer-declarator

18

fixed-pointer-declarator:

19

identifier = fixed-pointer-initializer

20

 

21

fixed-pointer-initializer:

22

& variable-reference

23

expression

24Each fixed-pointer-declarator declares a local variable of the given pointer-type and initializes that local

25variable with the address computed by the corresponding fixed-pointer-initializer. A local variable declared

26in a fixed statement is accessible in any fixed-pointer-initializers occurring to the right of that variable’s

27declaration, and in the embedded-statement of the fixed statement. A local variable declared by a fixed

28statement is considered read-only. A compile-time error occurs if the embedded statement attempts to

29modify this local variable (via assignment or the ++ and -- operators) or pass it as a ref or out parameter.

30It is an error to use a captured local variable (§14.5.14.3.1), value parameter, or parameter array in a fixed

31statement.

32A fixed-pointer-initializer can be one of the following:

33The token “&” followed by a variable-reference (§12.3.3.27) to a moveable variable (§25.3) of an

34unmanaged type T, provided the type T* is implicitly convertible to the pointer type given in the fixed

35statement. In this case, the initializer computes the address of the given variable, and the variable is

36guaranteed to remain at a fixed address for the duration of the fixed statement.

37An expression of an array-type with elements of an unmanaged type T, provided the type T* is

38implicitly convertible to the pointer type given in the fixed statement. In this case, the initializer

39computes the address of the first element in the array, and the entire array is guaranteed to remain at a

40fixed address for the duration of the fixed statement. The behavior of the fixed statement is

41implementation-defined if the array expression is null or if the array has zero elements.

42An expression of type string, provided the type char* is implicitly convertible to the pointer type

43given in the fixed statement. In this case, the initializer computes the address of the first character in

44the string, and the entire string is guaranteed to remain at a fixed address for the duration of the fixed

45statement. The behavior of the fixed statement is implementation-defined if the string expression is

46null.

391

C# LANGUAGE SPECIFICATION

1For each address computed by a fixed-pointer-initializer the fixed statement ensures that the variable

2referenced by the address is not subject to relocation or disposal by the garbage collector for the duration of

3the fixed statement. [Example: If the address computed by a fixed-pointer-initializer references a field of

4an object or an element of an array instance, the fixed statement guarantees that the containing object

5instance is not relocated or disposed of during the lifetime of the statement. end example]

6It is the programmer's responsibility to ensure that pointers created by fixed statements do not survive

7beyond execution of those statements. [Example: When pointers created by fixed statements are passed to

8external APIs, it is the programmer’s responsibility to ensure that the APIs retain no memory of these

9pointers. end example]

10Fixed objects can cause fragmentation of the heap (because they can’t be moved). For that reason, objects

11should be fixed only when absolutely necessary and then only for the shortest amount of time possible.

12[Example: The example

13class Test

14{

15

static int x;

16

int y;

17

unsafe static void F(int* p) {

18

*p = 1;

19

}

20

static void Main() {

21

Test t = new Test();

22

int[] a = new int[10];

23

unsafe {

24

fixed (int* p = &x) F(p);

25

fixed (int* p = &t.y) F(p);

26

fixed (int* p = &a[0]) F(p);

27

fixed (int* p = a) F(p);

28

}

29}

30}

31demonstrates several uses of the fixed statement. The first statement fixes and obtains the address of a

32static field, the second statement fixes and obtains the address of an instance field, and the third statement

33fixes and obtains the address of an array element. In each case it would have been an error to use the regular

34& operator since the variables are all classified as moveable variables.

35The third and fourth fixed statements in the example above produce identical results. In general, for an

36array instance a, specifying &a[0] in a fixed statement is the same as simply specifying a.

37Here’s another example of the fixed statement, this time using string:

38class Test

39{

40

static string name

= "xx";

41

unsafe static void

F(char* p) {

42

for (int i = 0; p[i] != '\0'; ++i)

43

Console.WriteLine(p[i]);

44

}

 

45

static void Main() {

46

unsafe {

 

47

fixed (char* p = name) F(p);

48

fixed (char* p = "xx") F(p);

49

}

 

50}

51}

52end example]

53In an unsafe context array elements of single-dimensional arrays are stored in increasing index order,

54starting with index 0 and ending with index Length – 1. For multi-dimensional arrays, array elements are

392

Chapter 25 Unsafe code

1stored such that the indices of the rightmost dimension are increased first, then the next left dimension, and

2so on to the left.

3Within a fixed statement that obtains a pointer p to an array instance a, the pointer values ranging from p

4to p + a.Length - 1 represent addresses of the elements in the array. Likewise, the variables ranging from

5p[0] to p[a.Length - 1] represent the actual array elements. Given the way in which arrays are stored ,

6we can treat an array of any dimension as though it were linear. [Example:

7using System;

8class Test

9{

10

static void Main() {

11

int[,,] a = new int[2,3,4];

12

unsafe {

13

fixed (int* p = a) {

14

for (int i = 0; i < a.Length; ++i) // treat as linear

15

p[i] = i;

16

}

17

}

18

for (int i = 0; i < 2; ++i)

19

for (int j = 0; j < 3; ++j) {

20

for (int k = 0; k < 4; ++k)

21

Console.Write("[{0},{1},{2}] = {3,2} ", i, j, k,

22

a[i,j,k]);

23

Console.WriteLine();

24

}

25}

26}

27which produces the output:

28

[0,0,0] =

0

[0,0,1] =

1

[0,0,2] =

2

[0,0,3] =

3

29

[0,1,0] =

4

[0,1,1] =

5

[0,1,2] =

6

[0,1,3] =

7

30

[0,2,0] =

8

[0,2,1] =

9

[0,2,2] = 10

[0,2,3] = 11

31[1,0,0] = 12 [1,0,1] = 13 [1,0,2] = 14 [1,0,3] = 15

32[1,1,0] = 16 [1,1,1] = 17 [1,1,2] = 18 [1,1,3] = 19

33[1,2,0] = 20 [1,2,1] = 21 [1,2,2] = 22 [1,2,3] = 23

34end example]

35[Example: In the following code

36class Test

37{

38

unsafe static void Fill(int* p, int count, int value) {

39

for (; count != 0; count--) *p++ = value;

40

}

41

static void Main() {

42

int[] a = new int[100];

43

unsafe {

44

fixed (int* p = a) Fill(p, 100, -1);

45

}

46}

47}

48a fixed statement is used to fix an array so its address can be passed to a method that takes a pointer. end

49example]

50A char* value produced by fixing a non-null string instance always points to a null-terminated string.

51Within a fixed statement that obtains a pointer p to a string instance s, the pointer values ranging from p to

52 p + s.Length - 1 represent addresses of the characters in the string, and the pointer value

53p + s.Length always points to a null character (the character with value '\0').

54Modifying objects of managed type through fixed pointers can result in undefined behavior. [Note: For

55example, because strings are immutable, it is the programmer’s responsibility to ensure that the characters

56referenced by a pointer to a fixed string are not modified. end note]

393

C# LANGUAGE SPECIFICATION

1[Note: The automatic null-termination of strings is particularly convenient when calling external APIs that

2expect “C-style” strings. Note, however, that a string instance is permitted to contain null characters. If such

3null characters are present, the string will appear truncated when treated as a null-terminated char*. end

4note]

525.7 Stack allocation

6In an unsafe context, a local variable declaration (§15.5.1) can include a stack allocation initializer, which

7allocates memory from the call stack.

8local-variable-initializer:

9

expression

10

array-initializer

11

stackalloc-initializer

12

stackalloc-initializer:

13

stackalloc unmanaged-type [ expression ]

14The unmanaged-type indicates the type of the items that will be stored in the newly allocated location, and

15the expression indicates the number of these items. Taken together, these specify the required allocation

16size. Since the size of a stack allocation cannot be negative, it is a compile-time error to specify the number

17of items as a constant-expression that evaluates to a negative value.

18A stack allocation initializer of the form stackalloc T[E] requires T to be an unmanaged type (§25.2) and

19E to be an expression convertible to type int. The construct allocates E * sizeof(T) bytes from the call

20stack and returns a pointer, of type T*, to the newly allocated block. If E is a negative value, then the

21behavior is undefined. If E is zero, then no allocation is made, and the pointer returned is implementation-

22defined. If there is not enough memory available to allocate a block of the given size, a

23System.StackOverflowException is thrown.

24The content of the newly allocated memory is undefined.

25Stack allocation initializers are not permitted in catch or finally blocks (§15.10).

26[Note: There is no way to explicitly free memory allocated using stackalloc. end note] All stack-

27allocated memory blocks created during the execution of a function member are automatically discarded

28when that function member returns. [Note: This corresponds to the alloca function, an extension

29commonly found in C and C++ implementations. end note]

30[Example: In the following code

31using System;

32class Test

33{

34

static string IntToString(int value) {

35

int n = value >= 0 ? value : -value;

36

unsafe {

37

char* buffer = stackalloc char[16];

38

char* p = buffer + 16;

39

do {

40

*--p = (char)(n % 10 + '0');

41

n /= 10;

42

} while (n != 0);

43

if (value < 0) *--p = '-';

44

return new string(p, 0, (int)(buffer + 16 - p));

45

}

46

}

47

static void Main() {

48

Console.WriteLine(IntToString(12345));

49

Console.WriteLine(IntToString(-999));

50}

51}

394

Соседние файлы в предмете Электротехника