JavaScript is required to for searching.
跳过导航链接
退出打印视图
Oracle Solaris Studio 12.3:C++ 用户指南     Oracle Solaris Studio 12.3 Information Library (简体中文)
search filter icon
search icon

文档信息

前言

第 1 部分C++ 编译器

1.  C++ 编译器

2.  使用 C++ 编译器

3.  使用 C++ 编译器选项

第 2 部分编写 C++ 程序

4.  语言扩展

5.  程序组织

6.  创建和使用模板

7.  编译模板

8.  异常处理

9.  改善程序性能

10.  生成多线程程序

第 3 部分库

11.  使用库

12.  使用 C++ 标准库

13.  使用传统 iostream

14.  生成库

第 4 部分附录

A.  C++ 编译器选项

B.  Pragma

B.1 Pragma 形式

B.1.1 将函数作为 pragma 参数进行重载

B.2 Pragma 参考

B.2.1 #pragma align

B.2.2 #pragma does_not_read_global_data

B.2.3 #pragma does_not_return

B.2.4 #pragma does_not_write_global_data

B.2.5 #pragma dumpmacros

B.2.6 #pragma end_dumpmacros

B.2.7 #pragma error_messages

B.2.8 #pragma fini

B.2.9 #pragma hdrstop

B.2.10 #pragma ident

B.2.11 #pragma init

B.2.12 #pragma ivdep

B.2.13 #pragma must_have_frame

B.2.14 #pragma no_side_effect

B.2.15 #pragma opt

B.2.16 #pragma pack( n)

B.2.17 #pragma rarely_called

B.2.18 #pragma returns_new_memory

B.2.19 #pragma unknown_control_flow

B.2.20 #pragma weak

B.2.20.1 #pragma weak name

词汇表

索引

B.2 Pragma 参考

本节介绍了 C++ 编译器可识别的 pragma 关键字。

B.2.1 #pragma align

#pragma align integer(variable[,variable...])

使用 align 使所列变量与 integer 字节内存对齐,并覆盖缺省设置。请遵循以下限制:

#pragma align 64 (aninteger, astring, astruct)
int aninteger;
static char astring[256];
struct S {int a; char *b;} astruct;

#pragma align 在名称空间内部使用时,必须使用改编名称。例如,以下代码中的 #pragma align 语句就是无效的。要更正此问题,应将 #pragma align 语句中的 abc 替换为其改编名称。

namespace foo {
    #pragma align 8 (a, b, c)
    static char a;
    static char b;
    static char c;
}

B.2.2 #pragma does_not_read_global_data

#pragma does_not_read_global_data(funcname[, funcname])

此 pragma 断言,指定的例程不直接或间接读取全局数据,从而在调用此类例程的周围实现更好的代码优化。具体来讲,赋值语句或存储可以围绕这样的调用移动。

指定函数的原型被声明后,该 pragma 才可用。如果全局访问的断言不为真,那么程序的行为就是未定义的。

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.3 #pragma does_not_return

#pragma does_not_return(funcname[, funcname])

pragma 向编译器断言,将不会返回对指定例程的调用,从而使编译器可执行与该假定一致的优化。例如,寄存器生命周期在调用点终止,这样可以进行进一步的优化。

如果指定的函数不返回,程序的行为就是未定义的。

指定函数的原型被声明后,该 pragma 才是可用的,如以下示例所示:

extern void exit(int);
#pragma does_not_return(exit)

extern void __assert(int);
#pragma does_not_return(__assert)

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.4 #pragma does_not_write_global_data

#pragma does_not_write_global_data(funcname[, funcname])

此 pragma 断言,指定的例程列表不直接或间接写入全局数据,从而在调用此类例程的周围实现更好的代码优化。具体来讲,赋值语句或存储可以围绕这样的调用移动。

指定函数的原型被声明后,该 pragma 才可用。如果全局访问的断言不为真,那么程序的行为就是未定义的。

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.5 #pragma dumpmacros

#pragma dumpmacros (value[,value...])

要查看宏在程序中如何工作时,请使用该 pragma。该 pragma 提供了诸如宏定义、取消定义和用法实例的信息,并按宏的处理顺序将输出输出到标准错误 (stderr)。dumpmacros pragma 达到文件结尾或遇到 #pragma end_dumpmacro 之前一直有效。请参见B.2.6 #pragma end_dumpmacros。下表列出了 value 的可能值:

含义
defs
打印所有宏定义
undefs
打印所有取消定义的宏
use
打印关于使用的宏的信息
loc
另外打印 defsundefsuse 的位置(路径名和行号)
conds
打印在条件指令中使用的宏的信息
sys
打印系统头文件中所有宏的定义、取消定义和使用的信息

注 - 子选项 loccondssysdefsundefsuse 选项的限定符。使用 loccondssys 本身并不会生成任何结果。例如,#pragma dumpmacros(loc,conds,sys) 不起任何作用。


dumpmacros pragma 与命令行选项作用相同,但 pragma 会覆盖命令行选项。请参见A.2.116 -xdumpmacros[= value[,value...]]

dumpmacros pragma 并不嵌套,因此以下代码行中,处理 #pragma end_dumpmacros 时,将停止打印宏信息:

#pragma dumpmacros(defs, undefs)
#pragma dumpmacros(defs, undefs)
...
#pragma end_dumpmacros

dumpmacros pragma 的作用是累积的。以下代码行

#pragma dumpmacros(defs, undefs)
#pragma dumpmacros(loc)

具有和以下行相同的效果:

#pragma dumpmacros(defs, undefs, loc)

如果使用选项 #pragma dumpmacros(use,no%loc),则使用的每个宏的名称仅输出一次。如果使用选项 #pragma dumpmacros(use,loc),则每次使用宏时都输出位置和宏名称。

B.2.6 #pragma end_dumpmacros

#pragma end_dumpmacros

此 pragma 标记 dumpmacros pragma 的结尾,并停止输出有关宏的信息。如果没有在 dumpmacros pragma 后面使用 end_dumpmacros pragma,dumpmacros pragma 会在文件结尾一直生成输出。

B.2.7 #pragma error_messages

#pragma error_messages (on|off| default, tag… tag)

错误消息 pragma 提供源程序内部对编译器发出的消息的控制。Pragma 只对警告消息有效。 -w 命令行选项可通过抑制所有警告消息来覆盖此 pragma。

B.2.8 #pragma fini

#pragma fini (identifier[,identifier...])

可使用 finiidentifier 标记为完成函数。此类函数应为 void 类型,不接受任何参数,当程序在程序控制下终止或从内存删除包含的共享对象时调用它们。与初始化函数一样,完成函数按链接编辑器处理的顺序执行。

在源文件中,#pragma fini 中指定的函数在该文件中的静态析构函数后面执行。在 pragma 中使用标识符之前,请先声明这些标识符。

此类函数每出现在 #pragma fini 指令中一次,就会被调用一次。

B.2.9 #pragma hdrstop

可将 hdrstop pragma 嵌入源文件的头文件中以标识源文件活前缀的结尾。例如,考虑以下文件:

example% cat a.cc
#include "a.h"
#include "b.h"
#include "c.h"
#include <stdio.h>
#include "d.h"
.
.
.
example% cat b.cc
#include "a.h"
#include "b.h"
#include "c.h"

源文件活前缀以 c.h 结束,因此可在每个文件中的 c.h 后面插入 #pragma hdrstop

#pragma hdrstop 只能位于用 CC 命令指定的源文件活前缀的结尾处。不要在任何 include 文件中指定 #pragma hdrstop

请参见A.2.156 -xpch=vA.2.157 -xpchstop=file

B.2.10 #pragma ident

#pragma ident string

可使用 ident string 放在可执行文件的 .comment 部分中。

B.2.11 #pragma init

#pragma init(identifier[,identifier...])

可使用 init identifier 标记为初始化函数。此类函数应为 void 类型,不接受任何参数,在开始执行时构造程序的内存映像的情况下调用。执行将共享对象送入内存的操作时(程序启动时,或执行某些动态装入操作时,例如 dlopen()),执行共享对象中的初始化函数。调用到初始化函数的唯一顺序就是链接编辑器静态和动态处理该函数的顺序。

在源文件中,#pragma init 中指定的函数在该文件中的静态析构函数后面执行。在 pragma 中使用标识符之前,请先声明这些标识符。

此类函数每出现在 #pragma init 指令中一次,就会被调用一次。

B.2.12 #pragma ivdep

ivdep pragma 指示编译器忽略在循环中找到的部分或全部对数组引用的循环附带依赖性,以进行优化。这将使编译器能够执行各种循环优化(例如微向量化、分发、软件流水线等),而以其他方式可能无法执行这些优化。当用户知道这些依赖性无关紧要或者实际上永远不会发生时,可以使用该指令。

#pragma ivdep 指令的解释依赖于 —xivdep 选项的值。

B.2.13 #pragma must_have_frame

#pragma must_have_frame(funcname[,funcname])

该 pragma 要求总是编译指定的一组函数来获得完整的堆栈帧(如 System V ABI 中所定义)。必须在使用该 pragma 列出函数之前,声明该函数的原型。

extern void foo(int);
extern void bar(int);
#pragma must_have_frame(foo, bar)

只有在声明了指定函数的原型后,才允许使用该 pragma。该 pragma 必须位于函数结尾之前。

void foo(int) {
  .
  #pragma must_have_frame(foo)
  .
  return;
  }

请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.14 #pragma no_side_effect

#pragma no_side_effect(name[,name...])

可使用 no_side_effect 指示函数不更改任何持久状态。Pragma 声明了命名的函数不具有任何副作用。也就是说,函数将返回仅依赖于传递参数的结果。此外,函数及其调用的子孙函数行为如下所示:

编译器执行优化时可以使用该信息。

如果函数具有副作用,执行调用该函数的程序的结果是未定义的。

name 参数指定当前转换单元中函数的名称。Pragma 必须与函数在相同的作用域,并且必须在函数声明之后出现。pragma 必须在函数定义之前。

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.15 #pragma opt

#pragma opt level (funcname[, funcname])

funcname 指定当前转换单元中定义的函数的名称。level 值指定用于所指定函数的优化级别。可以指定优化级别 0、1、2、3、4、5。可以通过将 level 设置为 0 来关闭优化。必须在该 pragma 之前使用原型或空参数列表声明函数。pragma 则必须对要优化的函数进行定义。

pragma 中所列任何函数的优化级别都降为 -xmaxopt 值。-xmaxopt=off 时,忽略 pragma。

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.16 #pragma pack( n)

#pragma pack([n])

可使用 pack 影响对结构成员的封装。

如果使用了该项,n 必须为 0 或 2 的幂。0 以外的值指示编译器针对数据类型使用 n 字节对齐和平台的自然对齐中的较小者。例如,以下指令使在指令后面(以及后续的 pack 指令前面)定义的所有结构成员对齐时依据的字节边界不严于 2 字节边界,即使正常对齐是 4 或 8 字节边界时也是如此。

#pragma pack(2)

n 为 0 或省略该项时,成员对齐还原为自然对齐值。

如果 n 值等于或大于平台上最严格的对齐时,则采用自然对齐。下表显示了每个平台最严格的对齐。

表 B-1 平台上最严格的对齐

平台
最严格的对齐
x86
4
SPARC 通用
8
64 位 SPARC V9 (-m64)
16

pack 指令应用于自身与下一个 pack 指令之间的所有结构定义。如果在具有不同包装的不同转换单元中定义了相同的结构,那么程序可能会因某种原因而失败。具体来说,不应该在包括定义预编译库接口的头文件之前使用 pack 指令。建议将 pack 指令放在要封装的结构紧前面的程序代码中,并将 #pragma pack() 放在该结构紧后面。

如果在 SPARC 平台上使用 #pragma pack 封装效果比类型的缺省对齐紧密,必须为应用程序的编译和链接指定 -misalign 选项。下表显示了整型数据类型的存储大小和缺省对齐。

表 B-2 存储大小和缺省对齐字节数

类型
32 位 SPARC

大小,对齐

64 位 SPARC

大小,对齐

x86

大小,对齐

bool
1, 1
1, 1
1, 1
char
1, 1
1, 1
1, 1
short
2, 2
2, 2
2, 2
wchar_t
4, 4
4, 4
4, 4
int
4, 4
4, 4
4, 4
long
4, 4
8, 8
4, 4
float
4, 4
4, 4
4, 4
double
8, 8
8, 8
8, 4
long double
16, 8
16, 16
12, 4
指向数据的指针
4, 4
8, 8
4, 4
指向函数的指针
4, 4
8, 8
4, 4
指向成员数据的指针
4, 4
8, 8
4, 4
指向成员函数的指针
8, 4
16, 8
8, 4

B.2.17 #pragma rarely_called

#pragms rarely_called(funcname[, funcname])

pragma 向编译器发出提示以说明很少调用指定的函数,从而使编译器可以对此类例程的调用点执行分析反馈式优化,而不需要分析收集阶段的开销。因为该 pragma 只是建议,所以编译器不执行基于该 pragma 的任何优化。

只有在声明指定函数的原型之后,才能使用 #pragma rarely_called 预处理程序指令。以下是 #pragma rarely_called 示例:

extern void error (char *message);
#pragma rarely_called(error)

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.18 #pragma returns_new_memory

#pragma returns_new_memory(name[,name...])

pragma 断言,每个指定的函数都返回新分配内存的地址,以及指针没有与任何其他指针相关的别名。使用该信息,优化器可以更好地跟踪指针值,厘清内存分配,从而改善调度和流水作业。

如果该断言为假,那么执行调用该函数的程序的结果是未定义的。

name 参数指定当前转换单元中函数的名称。Pragma 必须与函数在相同的作用域,并且必须在函数声明之后出现。pragma 必须在函数定义之前。

有关 pragma 如何将重载的函数名视为参数的更加详细的说明,请参见B.1.1 将函数作为 pragma 参数进行重载

B.2.19 #pragma unknown_control_flow

#pragma unknown_control_flow(name[,name...])

可使用 unknown_control_flow 指定一组违反过程调用的常规控制流属性的例程。例如,可通过任意的任何其他例程调用来访问 setjmp() 调用后面的语句。该语句通过调用 longjmp() 来访问。

因为这种例程使标准流程图分析无效,调用它们的例程不能安全地优化,所以要禁用优化器来编译这些例程。

如果函数名称被重载,那么会选择最近声明的函数。

B.2.20 #pragma weak

#pragma weak name1 [= name2]

可使用 weak 定义弱全局符号。该 pragma 主要在源文件中用于生成库。链接程序在不能解决弱符号时不会发出警告。

weak pragma 可以按以下两种形式之一来指定符号:

B.2.20.1 #pragma weak name

采用 #pragma weak name 形式时,指令使 name 成为弱符号。链接程序将不会指示是否未找到 name 的符号定义。它也不会在出现符号的多个弱定义时发出警告。链接程序仅执行第一个遇到的定义。

如果另一个编译单元有函数或变量的强定义,那么 name 将链接到它。如果没有 name 的强定义,那么链接程序符号的值为 0。

以下指令将 ping 定义为弱符号。链接程序找不到名为 ping 的符号的定义时,不会生成错误消息。

#pragma weak ping
#pragma weak name1 = name2

采用 #pragma weak name1 = name2 形式时,符号 name1 成为对 name2 的弱引用。如果没有在其他地方定义 name1,那么 name1 的值为 name2。如果在其他地方定义了 name1,那么链接程序使用该定义并忽略对 name2 的弱引用。以下指令指示链接程序解析对 bar(如果已在程序中某处定义)的任何引用,以及解析对 foo 的引用。

#pragma weak bar = foo

采用标识符形式时,必须在当前编译单元中声明和定义 name2。例如:

extern void bar(int) {...}
extern void _bar(int);
#pragma weak _bar=bar

使用字符串形式时,符号不需要预先声明。如果以下示例中的 _barbar 都是 extern "C",则不需要声明函数。但 bar 必须在同一对象中定义。

extern "C" void bar(int) {...}
#pragma weak "_bar" = "bar"
重载函数

使用标识符形式时,在 pragma 位置的作用域中必须只有一个具有指定名称的函数。尝试将标识符形式 #pragma weak 用于重载函数会出现错误。例如:

int bar(int);
float bar(float);
#pragma weak bar        // error, ambiguous function name

要避免错误,请使用字符串形式,如以下示例所示。

int bar(int);
float bar(float);
#pragma weak "__1cDbar6Fi_i_" // make float bar(int) weak

有关更多信息,请参见 Oracle Solaris《链接程序和库指南》。