标识符(identifier)是程序中变量、类型、函数和标号的名称,它可以由程序设计者命名,也可以由系统指定标识符由字母、数字和下划线组成,第一个字符不能是数字,接下来我们就来聊聊关于c语言占位修饰符?以下内容大家不妨参考一二希望能帮到您!

c语言占位修饰符(C八类标识符作用域)

c语言占位修饰符

标识符(identifier)是程序中变量、类型、函数和标号的名称,它可以由程序设计者命名,也可以由系统指定。标识符由字母、数字和下划线组成,第一个字符不能是数字。

通常来说,一段程序代码中所用到的标识符(名字)并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域(scope)。

作用域的使用能够提高程序逻辑的局部性,增强程序的可靠性,减少名字冲突。

对于C 来说,符号{}可以界定标识符的scope,关键字extern、static也可以拓宽或限制标识符的作用域。同时,类名、命名空间也可以限制标识符的作用域。

1 global scope(全局作用域)

典型的具有全局作用域的名字,包括:全局变量、全局函数等。

Use of global variables is generally discouraged. It makes your program more difficult to understand, and harder to debug. But sometimes using a global variable is acceptable.

通常不鼓励使用全局变量。它使您的程序更难理解,也更难调试。但有时使用全局变量是可以接受的。

// global.h #ifndef GLOBAL_DOT_H /* This is an "include guard" */ #define GLOBAL_DOT_H /** * This tells the compiler that g_myglobal exists somewhere. * Without "extern", this would create a new variable named * g_myglobal in _every file_ that included it. Don't miss this! */ extern int g_myglobal; /* _Declare_ g_myglobal, that is promise it will be _defined_ by * some module. */ typedef enum { RESOURCE_UNDEFINED = -1, RESOURCE_UNKNOWN = 0, RESOURCE_OK, RESOURCE_CANCEL, RESOURCE_ABORT, /* Insert more here. */ RESOURCE_MAX /* The maximum number of resources defined. */ } EnumResourceID; extern const char * const resources[RESOURCE_MAX]; extern const int gcvar = 12; #endif /* GLOBAL_DOT_H */ // global.c #include "global.h" /* Always include the header file that declares something * in the C file that defines it. This makes sure that the * declaration and definition are always in-sync. */ int g_myglobal; /* _Define_ my_global. As living in global scope it gets initialised to 0 * on program start-up. */ // 全局变量(外部变量),在加载阶段加载 const char * const resources[RESOURCE_MAX] = { "<unknown>", "OK", "Cancel", "Abort" }; // main.c #include "global.h" void test(){} // 全局函数 int main(void) { g_myglobal = 42; EnumResourceID resource_id = RESOURCE_UNDEFINED; while(( resource_id) < RESOURCE_MAX) { GoalKicker.com – C Notes for Professionals 252 printf("resource ID: %d, resource: '%s'\n", resource_id, resources[resource_id]); } return 0; }

2 Function Prototype Scope(函数原型作用域)

函数声明也称为函数原型。

#include <stdio.h> /* The parameter name, apple, has function prototype scope. These names are not significant outside the prototype itself. This is demonstrated below. */ int test_function(int apple); // Function Prototype Scope int main(void) { int orange = 5; orange = test_function(orange); printf("%d\r\n", orange); //orange = 6 return 0; } int test_function(int fruit) { fruit = 1; return fruit; }

3 Function scope(函数作用域)

Function scope is the special scope for labels. This is due to their unusual property. A label is visible through the entire function it is defined and one can jump (using instruction gotolabel) to it from any point in the same function.

函数作用域是标号的特殊范围。这是因为它们的特殊属性。标号在定义的整个函数中都是可见的,可以从同一函数中的任意点跳转(使用指令gotolabel)到它。

#include <stdlib.h> #include <stdio.h> void close(FILE *fp){} void a_function(void) { bool error = true; double* a = (double*)malloc(sizeof(double[34])); if (!a) { fprintf(stderr,"can't allocate\n"); return; /* No point in freeing a if it is null */ } FILE* b = fopen("some_file","r"); if (!b) { fprintf(stderr,"can't open\n"); goto CLEANUP1; /* Free a; no point in closing b */ } /* do something reasonable */ if (error) { fprintf(stderr,"something's wrong\n"); goto CLEANUP2; /* Free a and close b to prevent leaks */ } /* do yet something else */ CLEANUP2: close(b); CLEANUP1: free(a); } main(){}

Labels such as CLEANUP1 and CLEANUP2 are special identifiers that behave differently from all other identifiers. They are visible from everywhere inside the function, even in places that are executed before the labeled statement, or even in places that could never be reached if none of the goto is executed. Labels are often written in lower-case rather than upper-case.

CLEANUP1和CLEANUP2等标号是特殊标识符,其行为与所有其他标识符不同。它们在函数内部的任何地方都是可见的,甚至在标记语句之前执行的地方,或者如果没有执行goto,就永远无法到达的地方。标号通常用小写字母而不是大写字母书写。

4 Block Scope(块作用域)

An identifier has block scope if its corresponding declaration appears inside a block (parameter declaration in function definition apply). The scope ends at the end of the corresponding block.

如果标识符的相应声明出现在块内,则该标识符具有块作用域(函数定义中的参数声明适用)。作用域在相应块的末尾结束。

No different entities with the same identifier can have the same scope, but scopes may overlap. In case of overlapping scopes the only visible one is the one declared in the innermost scope.

具有相同标识符的不同实体不能具有相同的作用域,但作用域可能重叠。对于重叠的作用域,唯一可见的是在最内层作用域中声明的作用域。

#include <stdio.h> void test(int bar) // bar has scope test function block { int foo = 5; // foo has scope test function block { int bar = 10; // bar has scope inner block, this overlaps with previous // test:bar declaration, and it hides test:bar printf("%d %d\n", foo, bar); // 5 10 } // end of scope for inner bar printf("%d %d\n", foo, bar); // 5 5, here bar is test:bar } // end of scope for test:foo and test:bar int main(void) { int foo = 3; // foo has scope main function block printf("%d\n", foo); // 3 test(5); printf("%d\n", foo); // 3 return 0; } // end of scope for main:foo

5 File Scope(文件作用域)

#include <stdio.h> /* The identifier, foo, is declared outside all blocks. It can be used anywhere after the declaration until the end of the translation unit. */ static int foo; // variable file scope staticc void test_function(void) // function file scope { foo = 2; } const int cvar = 12; // 默认为文件作用域,当用exetern修饰且有初始化时,为全局作用域 int main(void) { foo = 1; test_function(); printf("%d\r\n", foo); //foo = 3; return 0; }

6 namespace scope(命名空间作用域)

命名空间的成员名字具有命名空间作用域(namespace scope)。该名字的作用域从在该命名空间内的声明点直至当前编译单元内该命名空间的结尾处。使用using namespace语句可以提升该命名空间此时已经声明的名字到该using语句的作用域。

使用限定符::,可以在命名空间名字的作用域内访问该命名空间的成员名字。

C 引入了无名命名空间(unnamednamespace),其作用域即为当前编译单元。例如:

namespace {int i;}

也可以通过前面加上::限定访问文件作用域中的名字。

7 class scope(类作用域)

类(class、struct、union)内定义的名字的作用域称为类作用域(class scope)。 这些名字在当前类的定义内部,以及类定义词法范围外的类成员定义中是可见的。因此,在类内部,成员名字可以先使用后定义,不必前向声明(forward declaration)。

类静态数据成员具有外部链接属性。

类的成员名字在其所在的类作用域内、或者派生类作用域内可见,或者通过 .运算符、->运算符、::限定符访问。

匿名类的作用域,这里的匿名类是指匿名struct、匿名class、匿名union,且没有直接用这种类型定义变量。如果紧随这些无名类型的定义之后,定义了该类型的变量,则类型的定义及使用与普通情况完全一样;严格说,这种情形可以不算是匿名类。

匿名类作为嵌套类,即匿名类在一个外部类的内部定义:则编译器就在此处定义一个该匿名类的无名变量,并把该匿名类的成员的名字提升到该类型定义所在的外部类的作用域内。由于匿名类不能使用点运算符访问其成员,所以匿名类只能有数据成员,不允许有成员函数,也不能包含私有或受保护的数据成员。如果匿名类的定义是连续嵌套,则最内部的匿名类的成员名字被提升至最外部的非匿名类或可用变量访问的成员类之处。

匿名类不作为嵌套类定义,即匿名类定义在一个全局函数内部或者全局函数外部。C/C 语言标准只允许匿名union在这种情形下定义;如果是匿名struct、匿名class,则编译报错。对于此种情形的匿名union,编译器同样在此处定义一个该匿名联合的无名变量,并把该匿名联合的成员的名字提升到该匿名联合所在的作用域内,匿名联合只能有数据成员,不允许有成员函数,也不能包含私有或受保护的数据成员。在函数外的匿名联合只能在当前编译单元内可见,因此必须使用static关键字,或者必须放在匿名命名空间中。

例如:

int main(){ union{ int test; char c; }; test=5; //匿名union的成员的名字提升到定义了该匿名union的作用域内。 struct { int i;} v; //匿名struct,但是紧随其后声明了一个变量v v.i=101; // 编译通过 i=102; //编译报错: 'i' wasnot declared in this scope| return 0; }

8 enumeration scope(枚举作用域)

枚举作用域是指枚举类型的成员(enumerator)的名字的作用域,起自其声明之处,终至枚举定义结束之处。

enum Direction { UP, LEFT, DOWN, RIGHT }; Direction d = UP;

C语言规定,枚举类型的成员(enumerator)的可见范围被提升至该枚举类型所在的作用域内。这被认为有可能污染了外部的作用域。为此,C 11引入了枚举类(enum class)解决此问题。

enum class Format : char { TEXT, PDF, OTHER }; Format f = Format::TEXT; enum Language : int { ENGLISH, FRENCH, OTHER };

-End-

,