65,210
社区成员
发帖
与我相关
我的任务
分享
#include <stdio.h>
int main(int argc, char* argv[])
{
const int ic = 100;
const int *pc=
const_cast<int &>(ic)++;
printf("%d,%d\n", ic, *pc);
return 0;
}
#include <stdio.h>
int main(int argc, char* argv[])
{
volatile const int ic = 100;
volatile const int *pc=
const_cast<int &>(ic)++;
printf("%d,%d\n", ic, *pc);
return 0;
}
在程序编译期间在可能的情况下符号常量的值会代替该名字的出现,这个替代过程,被称为常量折叠(constant folding)
To understand the behavior of C and C++ programs, you need to know about linkage. In an executing program, an identifier is represented by storage in memory that holds a variable or a compiled function body. Linkage describes this storage as it is seen by the linker. There are two types of linkage: internal linkage and external linkage.
Internal linkage means that storage is created to represent the identifier only for the file being compiled. Other files may use the same identifier name with internal linkage, or for a global variable, and no conflicts will be found by the linker – separate storage is created for each identifier. Internal linkage is specified by the keyword static in C and C++.
External linkage means that a single piece of storage is created to represent the identifier for all files being compiled. The storage is created once, and the linker must resolve all other references to that storage. Global variables and function names have external linkage. These are accessed from other files by declaring them with the keyword extern. Variables defined outside all functions (with the exception of const in C++) and function definitions default to external linkage. You can specifically force them to have internal linkage using the static keyword. You can explicitly state that an identifier has external linkage by defining it with the extern keyword. Defining a variable or function with extern is not necessary in C, but it is sometimes necessary for const in C++.
(对于C++来说,是global namespace的全局变量)C++默认const变量的链接性质是内部的,而C则相反,默认是外部的.在C++中,const变量默认是内部链接的,除非你显式加上extern修饰词,否则,其它文件是看不到的。
声明(declaration)引入一个名字,而定义(definition)给出程序中各个实体(entity,比如函数,类型等)的完整唯一的描述。
一个声明就是一个定义,除非:
1. 它声明了一个函数但是没有给出函数体。
2. 它使用了extern关键字。
3. 它声明了一个类的名字。
4. 它是typedef。
5. 它在类定义中声明了static members.
为什么类的静态变量不可以就地初始化(只能声明,不能定义):
在C++里,头文件定义一个const对象会怎么样:
一般不会怎么样,这个和C里的在头文件里定义const int一样,每一个包含了这个头文件的编译单元都会定义这个对象。但由于该对象是const的,所以没什么影响。但是:有2种情况可能破坏这个局面:
1.如果涉及到对这个const对象取地址并且依赖于这个地址的唯一性,那么在不同的编译单元里,取到的地址可以不同。(但一般很少这么做)
2.如果这个对象具有mutable的变量,某个编译单元对其进行修改,则同样不会影响到别的编译单元。
为什么类的静态常量也不可以就地初始化:
因为这相当于在头文件里定义了const对象。作为例外,int/char等可以进行就地初始化,是因为这些变量可以直接被优化为立即数(常量折叠),就和宏一样。
还有,头文件不应该含有非inline 函数或对象的定义。这些定义如果在同一程序的两个或多个文件中被包含就会产生重复定义的编译错误。
12: const int ic = 100;
00401028 mov dword ptr [ebp-4],64h
13:
14: const int *pc=
0040102F lea eax,[ebp-4]
00401032 mov dword ptr [ebp-8],eax
15:
16: const_cast<int &>(ic)++;
00401035 mov ecx,dword ptr [ebp-4]
00401038 add ecx,1
0040103B mov dword ptr [ebp-4],ecx
17:
18: printf("%d,%d\n", ic, *pc);
0040103E mov esi,esp
00401040 mov edx,dword ptr [ebp-8]
00401043 mov eax,dword ptr [edx]
00401045 push eax //这里是101入栈
00401046 push 64h //这里直接是100入栈了.
00401048 push offset string "%d,%d\n" (0041301c)
0040104D call dword ptr [__imp__printf (004150a4)]
00401053 add esp,0Ch
00401056 cmp esi,esp
00401058 call _chkesp (0040108e)
19:
20: return 0;
0040105D xor eax,eax
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[])
{
volatile int const ic = 100;//不加volatile,此时const ic被替换成了100
const int *pc=(const int *)
const_cast<int &>(ic)++;
printf("%d,%d\n", ic, *pc);
system("pause");
return 0;
}
#include <stdio.h>
int main(int argc, char* argv[])
{
const int ic = 100; // 编译期间的常量,没有地址,类似于C中的#define
const int *pc= // 分配内存.
const_cast<int &>(ic)++;
printf("%d,%d\n", ic, *pc); // ic仍然保存在符号表中,取数时使用的文本替换.
return 0;
}