Alignment And Compiler Error C2719 字节对齐和编译错误C2719

Compiler Error C2719

'parameter': formal parameter with __declspec(align('#')) won't be aligned

The align __declspec modifier is not permitted on function parameters. Function parameter alignment is controlled by the calling convention used. For more information, see Calling Conventions.

函数参数不允许使用align __declspec修饰符。函数参数的对齐由使用的调用约定控制。有关更多信息,请参阅调用约定。

The following sample generates C2719 and shows how to fix it:

以下示例生成C2719并显示如何修复它:

// C2719.cpp
void func(int __declspec(align(32)) i);   // C2719
// try the following line instead 请尝试改为
// void func(int i);

__declspec

The extended attribute syntax for specifying storage-class information uses the __declspec keyword, which specifies that an instance of a given type is to be stored with a Microsoft-specific storage-class attribute listed below. Examples of other storage-class modifiers include the static and extern keywords. However, these keywords are part of the ANSI specification of the C and C++ languages, and as such are not covered by extended attribute syntax. The extended attribute syntax simplifies and standardizes Microsoft-specific extensions to the C and C++ languages.

扩展的属性语法,用于指定存储类的信息,使用__declspec关键字。该关键字指定一个给定类型的实例,该实例使用下面的Microsoft特定存储类的属性存储。其他的存储类修饰符的例子包括static和extern关键字。但是,这些关键字是C和C ++语言的ANSI规范的一部分,因此扩展属性语法不包含这些关键字。扩展属性语法简化并标准化了特定于Microsoft的C和C ++语言扩展。

Grammar
decl-specifier: DECL说明符:

  • __declspec ( extended-decl-modifier-seq )

extended-decl-modifier-seq: 扩展的decl修饰符顺序:

  • extended-decl-modifieropt
  • extended-decl-modifier extended-decl-modifier-seq

extended-decl-modifier: 扩展的decl修饰符:

  • align( # )
  • allocate(" segname ")
  • appdomain
  • code_seg(" segname ")
  • deprecated
  • dllimport
  • dllexport
  • jitintrinsic
  • naked
  • noalias
  • noinline
  • noreturn
  • nothrow
  • novtable
  • process
  • property( { get=get_func_name | ,put=put_func_name } )
  • restrict
  • safebuffers
  • selectany
  • spectre(nomitigation)
  • thread
  • uuid(" ComObjectGUID ")

White space separates the declaration modifier sequence. Examples appear in later sections.

空格分隔声明修饰符序列。示例出现在后面的部分中。

Extended attribute grammar supports these Microsoft-specific storage-class attributes: align, allocate, appdomain, code_seg, deprecated, dllexport, dllimport, jitintrinsic, naked, noalias, noinline, noreturn, nothrow, novtable, process, restrict, safebuffers, selectany, spectre, and thread. It also supports these COM-object attributes: property and uuid.

扩展属性语法支持这些特定于Microsoft的存储类属​​性:align,allocate,appdomain,code_seg,deprecated,dllexport,dllimport,jitintrinsic,naked,noalias,noinline,noreturn,nothrow,novtable,process,restrict,safebuffers,selectany,specter和thread。它还支持这些COM对象属性:property和uuid。

The code_seg, dllexport, dllimport, naked, noalias, nothrow, property, restrict, selectany, thread, and uuid storage-class attributes are properties only of the declaration of the object or function to which they are applied. The thread attribute affects data and objects only. The naked and spectre attributes affect functions only. The dllimport and dllexport attributes affect functions, data, and objects. The property, selectany, and uuid attributes affect COM objects.

code_seg,dllexport,dllimport,naked,noalias,nothrow,property,restrict,selectany,thread和uuid storage-class属性仅是应用它们的对象或函数所声明的属性。线程属性仅影响数据和对象。naked 和spectre 属性仅影响函数。 dllimport和dllexport属性会影响函数,数据和对象。 property,selectany和uuid属性会影响COM对象。

For compatibility with previous versions, _declspec is a synonym for __declspec unless compiler option /Za (Disable language extensions) is specified.

为了与先前版本兼容,除非指定了编译器选项/ Za(禁用语言扩展名),否则_declspec是__declspec的同义词。

The __declspec keywords should be placed at the beginning of a simple declaration. The compiler ignores, without warning, any __declspec keywords placed after * or & and in front of the variable identifier in a declaration.

__declspec关键字应放在简单声明的开头。编译器忽略任何在*或&之后的,并且在变量标识符之前的 __declspec关键字,同时不会有warning出现。

A __declspec attribute specified in the beginning of a user-defined type declaration applies to the variable of that type. For example:

在用户定义的类型声明的开头指定的__declspec属性适用于该类型的变量。例如:


__declspec(dllimport) class X {} varX;

In this case, the attribute applies to varX. A __declspec attribute placed after the class or struct keyword applies to the user-defined type. For example:

在这种情况下,该属性适用于varX。一个__declspec属性放置在class或struct关键字之后,则应用于用户自定义类型。例如:


class __declspec(dllimport) X {};

In this case, the attribute applies to X.

在这种情况下,该属性适用于X.

The general guideline for using the __declspec attribute for simple declarations is as follows:

使用__declspec属性进行简单声明的一般准则如下:

decl-specifier-seq init-declarator-list;

The decl-specifier-seq should contain, among other things, a base type (e.g. int, float, a typedef, or a class name), a storage class (e.g. static, extern), or the __declspec extension. The init-declarator-list should contain, among other things, the pointer part of declarations. For example:

除其他外,decl-specifier-seq应包含基类型(例如int,float,typedef或类名),存储类(例如static,extern)或__declspec扩展。 init-declarator-list应包含声明的指针部分等。例如:


__declspec(selectany) int * pi1 = 0;   //Recommended, selectany & int both part of decl-specifier 推荐,selectany和int都是decl-specifier的一部分
int __declspec(selectany) * pi2 = 0;   //OK, selectany & int both part of decl-specifier OK,selectany&int都是decl-specifier的一部分
int * __declspec(selectany) pi3 = 0;   //ERROR, selectany is not part of a declarator  错误,selectany不是声明者的一部分

The following code declares an integer thread local variable and initializes it with a value:

以下代码声明了一个整数线程局部变量,并使用以下值初始化它:


// Example of the __declspec keyword
__declspec( thread ) int tls_i = 1;

align (C++)

In Visual Studio 2015 and later, use the C++11 standard alignas specifier to control alignment. For more information, see Alignment.

在Visual Studio 2015及更高版本中,使用C 11标准alignas说明符来控制对齐。有关更多信息,请参阅Alignment。

Use __declspec(align(#)) to precisely control the alignment of user-defined data (for example, static allocations or automatic data in a function).

使用__declspec(align(#))来精确控制用户定义数据的对齐(例如,静态分配或函数中的自动数据)。

Syntax
__declspec( align( # ) ) declarator

Remarks
Writing applications that use the latest processor instructions introduces some new constraints and issues. In particular, many new instructions require that data must be aligned to 16-byte boundaries. Additionally, by aligning frequently used data to the cache line size of a specific processor, you improve cache performance. For example, if you define a structure whose size is less than 32 bytes, you may want to align it to 32 bytes to make sure that objects of that structure type are efficiently cached.

编写使用最新处理器指令的应用程序会引入一些新的约束和问题。特别是,许多新指令要求数据必须与16字节边界对齐。此外,通过将常用数据与特定处理器的缓存行大小对齐,可以提高缓存性能。例如,如果定义大小小于32个字节的结构,则可能需要将其与32个字节对​​齐,以确保有效地缓存该结构类型的对象。

# is the alignment value. Valid entries are integer powers of two from 1 to 8192 (bytes), such as 2, 4, 8, 16, 32, or 64. declarator is the data that you are declaring as aligned.

#是对齐值。有效条目是1到8192(字节)之间的2的整数幂,例如2,4,8,16,32或64.声明符是您声明为对齐的数据。

For information about how to return a value of type size_t that is the alignment requirement of the type, see __alignof. For information about how to declare unaligned pointers when targeting 64-bit processors, see __unaligned.

有关如何返回类型size_t的值(即类型的对齐要求)的信息,请参阅__alignof。有关如何在定位64位处理器时声明未对齐指针的信息,请参阅__unaligned。

You can use __declspec(align(#)) when you define a struct, union, or class, or when you declare a variable.

定义struct,union或class时,或者声明变量时,可以使用__declspec(align(#))。

The compiler does not guarantee or attempt to preserve the alignment attribute of data during a copy or data transform operation. For example, memcpy can copy a struct declared with __declspec(align(#)) to any location. Note that ordinary allocators—for example, malloc, C++ operator new, and the Win32 allocators—return memory that is usually not sufficiently aligned for __declspec(align(#)) structures or arrays of structures. To guarantee that the destination of a copy or data transformation operation is correctly aligned, use _aligned_malloc, or write your own allocator.

在复制或数据转换操作期间,编译器不保证或尝试保留数据的对齐属性。例如,memcpy可以将使用__declspec(align(#))声明的结构复制到任何位置。请注意,普通的分配器 - 例如,malloc,C运算符new和Win32 allocators 返回的内存通常与__declspec(align(#))结构或结构数组没有充分对齐。要确保正确对齐复制或数据转换操作的目标,请使用_aligned_malloc,或编写自己的分配器。

You cannot specify alignment for function parameters. When data that has an alignment attribute is passed by value on the stack, its alignment is controlled by the calling convention. If data alignment is important in the called function, copy the parameter into correctly aligned memory before use.

您不能指定函数参数的对齐方式。当具有alignment属性的数据通过堆栈上的值传递时,其对齐由调用约定控制。如果数据对齐在被调用函数中很重要,请在使用前将参数复制到正确对齐的内存中。

Without __declspec(align(#)), the compiler generally aligns data on natural boundaries based on the target processor and the size of the data, up to 4-byte boundaries on 32-bit processors, and 8-byte boundaries on 64-bit processors. Data in classes or structures is aligned in the class or structure at the minimum of its natural alignment and the current packing setting (from #pragma pack or the /Zp compiler option).

如果没有__declspec(align(#)),编译器通常会根据目标处理器和数据大小在自然边界上对齐数据,在32位处理器上最多4个字节边界,在64位上最多8个字节边界处理器。类或结构中的数据在类或结构中以其自然对齐和当前打包设置(来自#pragma pack或/ Zp编译器选项)的最小值对齐。

This example demonstrates the use of __declspec(align(#)):

此示例演示了__declspec(align(#))的用法:



__declspec(align(32)) struct Str1{
   int a, b, c, d, e;
};

This type now has a 32-byte alignment attribute. This means that all static and automatic instances start on a 32-byte boundary. Additional structure types declared with this type as a member preserve this type's alignment attribute, that is, any structure with Str1 as an element has an alignment attribute of at least 32.

此类型现在具有32字节的对齐属性。这意味着所有静态和自动的类型实例都以32字节边界开始。使用此类型声明为成员的其他结构类型时,将保留此类型的alignment属性,即,任何以Str1作为元素的结构都具有至少为32的alignment属性。

Note that sizeof(struct Str1) is equal to 32. This implies that if an array of Str1 objects is created, and the base of the array is 32-byte aligned, each member of the array is also 32-byte aligned. To create an array whose base is correctly aligned in dynamic memory, use _aligned_malloc, or write your own allocator.

请注意,sizeof(struct Str1)等于32.这意味着如果创建了一个Str1对象数组,并且该数组的基数是32字节对齐的,则该数组的每个成员也是32字节对齐的。要创建一个基数在动态内存中正确对齐的数组,请使用_aligned_malloc,或编写自己的分配器。

The sizeof value for any structure is the offset of the final member, plus that member's size, rounded up to the nearest multiple of the largest member alignment value or the whole structure alignment value, whichever is larger.

任何结构的sizeof值是最终成员的偏移量,加上该成员的大小,向上舍入到最大成员对齐值的最接近的倍数或整个结构对齐值,以较大者为准。

The compiler uses these rules for structure alignment:

编译器使用这些规则进行结构对齐:

Unless overridden with __declspec(align(#)), the alignment of a scalar structure member is the minimum of its size and the current packing.

除非用__declspec(align(#))覆盖,否则标量结构成员的对齐是其大小和当前packing中的最小值。

Unless overridden with __declspec(align(#)), the alignment of a structure is the maximum of the individual alignments of its member(s).

除非用__declspec(align(#))覆盖,否则结构的对齐是其成员的各个对齐的最大值。

A structure member is placed at an offset from the start of its parent structure which is the smallest multiple of its alignment greater than or equal to the offset of the end of the previous member.

结构构件放置在距其父结构的起点偏移处,该父结构的最小倍数大于或等于前一成员的末端的偏移量。

The size of a structure is the smallest multiple of its alignment greater than or equal to the offset of the end of its last member.

结构的大小是其对齐的最小倍数大于或等于其最后一个成员的末尾的偏移量。

__declspec(align(#)) can only increase alignment restrictions.

__declspec(align(#))只能增加对齐限制。

For more information, see:

有关更多信息,请参阅:

align Examples

对齐示例

Defining New Types with __declspec(align(#))

使用 __declspec(align(#))定义新类型

Aligning Data in Thread Local Storage

在线程本地存储中对齐数据

How align Works with Data Packing

如何将Works与数据打包对齐

Examples of Structure Alignment (x64 specific)

align Examples
The following examples show how __declspec(align(#)) affects the size and alignment of data structures. The examples assume the following definitions:

以下示例显示__declspec(align(#))如何影响数据结构的大小和对齐方式。这些示例假设以下定义:


#define CACHE_LINE  32
#define CACHE_ALIGN __declspec(align(CACHE_LINE))

In this example, the S1 structure is defined by using __declspec(align(32)). All uses of S1 for a variable definition or in other type declarations are 32-byte aligned. sizeof(struct S1) returns 32, and S1 has 16 padding bytes following the 16 bytes required to hold the four integers. Each int member requires 4-byte alignment, but the alignment of the structure itself is declared to be 32. Therefore, the overall alignment is 32.

在此示例中,通过使用__declspec(align(32))定义S1结构。 S1对变量定义或其他类型声明的所有使用都是32字节对齐的。 sizeof(struct S1)返回32,并且S1在保存四个整数所需的16个字节之后有16个填充字节。每个int成员都需要4字节对齐,但结构本身的对齐声明为32.因此,整体对齐为32。



struct CACHE_ALIGN S1 { // cache align all instances of S1 缓存对齐S1的所有实例
   int a, b, c, d;
};

struct S1 s1;   // s1 is 32-byte cache aligned  s1是32字节缓存对齐

In this example, sizeof(struct S2) returns 16, which is exactly the sum of the member sizes, because that is a multiple of the largest alignment requirement (a multiple of 8).

在此示例中,sizeof(struct S2)返回16,这正是成员大小的总和,因为这是最大对齐要求的倍数(8的倍数)。



__declspec(align(8)) struct S2 {
   int a, b, c, d;
};

In the following example, sizeof(struct S3) returns 64.

在以下示例中,sizeof(struct S3)返回64。


struct S3 {
    struct S1 s1;   
    // S3 inherits cache alignment requirement
    // from S1 declaration
    //S3继承了来自S1声明的缓存对齐要求

    int a;         
    // a is now cache aligned because of s1
    // 28 bytes of trailing padding
    //由于s1,现在缓存对齐需要28字节的尾随填充
};

In this example, notice that a has the alignment of its natural type, in this case, 4 bytes. However, S1 must be 32-byte aligned. Twenty-eight bytes of padding follow a, so that s1 starts at offset 32. S4 then inherits the alignment requirement of S1, because it is the largest alignment requirement in the structure. sizeof(struct S4) returns 64.

在此示例中,请注意a具有其自然类型的对齐方式,在本例中为4个字节。但是,S1必须是32字节对齐的。二十八个字节的填充跟随a,因此s1从偏移32开始.S4然后继承S1的对齐要求,因为它是结构中最大的对齐要求。 sizeof(struct S4)返回64。


struct S4 {
   int a;
   // 28 bytes padding  28字节填充
    struct S1 s1;      // S4 inherits cache alignment requirement of S1 S4继承了S1的缓存对齐要求
};

The following three variable declarations also use __declspec(align(#)). In each case, the variable must be 32-byte aligned. In the case of the array, the base address of the array, not each array member, is 32-byte aligned. The sizeof value for each array member is not affected when you use __declspec(align(#)).

以下三个变量声明也使用__declspec(align(#))。在每种情况下,变量必须是32字节对齐的。在数组的情况下,数组的基址,而不是每个数组成员,是32字节对齐的。使用__declspec(align(#))时,每个数组成员的sizeof值不受影响。


CACHE_ALIGN int i;
CACHE_ALIGN int array[128];
CACHE_ALIGN struct s2 s;

To align each member of an array, code such as this should be used:

要对齐数组的每个成员,应使用以下代码:


typedef CACHE_ALIGN struct { int a; } S5;

S5 array[10];

In this example, notice that aligning the structure itself and aligning the first element have the same effect:

在此示例中,请注意对齐结构本身和对齐第一个元素具有相同的效果:


CACHE_ALIGN struct S6 {
   int a;
   int b;
};

struct S7 {
   CACHE_ALIGN int a;
               int b;
};

S6 and S7 have identical alignment, allocation, and size characteristics.

S6和S7具有相同的对齐,分配和尺寸特征。

In this example, the alignment of the starting addresses of a, b, c, and d are 4, 1, 4, and 1, respectively.

在该示例中,a,b,c和d的起始地址的对齐分别是4,1,4和1。


void fn() {
   int a;
   char b;
   long c;
   char d[10]
}

The alignment when memory is allocated on the heap depends on which allocation function is called. For example, if you use malloc, the result depends on the operand size. If arg >= 8, the memory returned is 8 byte aligned. If arg < 8, the alignment of the memory returned is the first power of 2 less than arg. For example, if you use malloc(7), the alignment is 4 bytes.

在堆上分配内存时的对齐取决于调用哪个分配函数。例如,如果使用malloc,则结果取决于操作数大小。如果arg> = 8,则返回的内存为8字节对齐。如果arg <8,则返回的内存对齐是比arg小2的第一个幂。例如,如果使用malloc(7),则对齐为4个字节。

Defining New Types with __declspec(align(#))
You can define a type with an alignment characteristic.

使用 __declspec(align(#))定义新类型
您可以定义具有对齐特征的类型。

For example, you can define a struct with an alignment value this way:

例如,您可以通过以下方式定义具有对齐值的结构:


struct aType {int a; int b;};
typedef __declspec(align(32)) struct aType bType;

Now, aType and bType are the same size (8 bytes) but variables of type bType are 32-byte aligned.

现在,aType和bType的大小相同(8字节),但bType类型的变量是32字节对齐的。

Aligning Data in Thread Local Storage 在线程本地存储中对齐数据

Static thread-local storage (TLS) created with the __declspec(thread) attribute and put in the TLS section in the image works for alignment exactly like normal static data. To create TLS data, the operating system allocates memory the size of the TLS section and respects the TLS section alignment attribute.

使用__declspec(thread)属性创建并放入图像中的TLS部分的静态线程局部存储(TLS)与正常静态数据完全一样。要创建TLS数据,操作系统会分配TLS部分大小的内存,并遵守TLS部分对齐属性。

This example shows various ways to place aligned data into thread local storage.
此示例显示将对齐数据放入线程本地存储的各种方法。


// put an aligned integer in TLS
__declspec(thread) __declspec(align(32)) int a;

// define an aligned structure and put a variable of the struct type
// into TLS
__declspec(thread) __declspec(align(32)) struct F1 { int a; int b; } a;

// create an aligned structure
struct CACHE_ALIGN S9 {
   int a;
   int b;
};
// put a variable of the structure type into TLS
__declspec(thread) struct S9 a;

How align Works with Data Packing 如何将Works与数据打包对齐

The /Zp compiler option and the pack pragma have the effect of packing data for structure and union members.This example shows how /Zp and __declspec(align(#)) work together:

/ zp编译器选项和pack pragma具有为结构和联合成员打包数据的效果。此示例显示/ Zp和__declspec(align(#))如何一起工作:


struct S {
   char a;
   short b;
   double c;
   CACHE_ALIGN double d;
   char e;
   double f;
};

The following table lists the offset of each member under a variety of /Zp (or #pragma pack) values, showing how the two interact.

下表列出了各种/ Zp(或#pragma pack)值下每个成员的偏移量,显示了两者如何相互作用。

Variable /Zp1 /Zp2 /Zp4 /Zp8
a 0 0 0 0
b 1 2 2 2
c 3 4 4 8
d 32 32 32 32
e 40 40 40 40
f 41 42 44 48
sizeof(S) 64 64 64 64

For more information, see /Zp (Struct Member Alignment).
有关更多信息,请参见/ Zp(Struct Member Alignment)

The offset of an object is based on the offset of the previous object and the current packing setting, unless the object has a __declspec(align(#)) attribute, in which case the alignment is based on the offset of the previous object and the __declspec(align(#)) value for the object.

对象的偏移量基于前一个对象的偏移量和当前打包设置,除非该对象具有__declspec(align(#))属性,在这种情况下,对齐基于前一个对象的偏移量和 __declspec(align(#))对象的值。

猜你喜欢

转载自www.cnblogs.com/CookieBox/p/Alignment.html