user-0 提问: c语言中常量在内存中是怎样的？

回复:
user: user-0
content: 谢谢！谢谢！谢谢！谢谢！

user: user-1
content: const 类型限定符   C C 语言 声明  C 类型系统中每一个独立的类型在都有数个该类型的限定版本，对应 const 、 volatile及对于指向对象指针的 restrict 限定符中的一个、两个或全部三个。此页面描述 const 限定符的效果。  编译器可以把声明带 const 限定类型的对象放到只读内存中，而且若程序决不取该 const 对象的地址，则可能完全不存储它。  const 语义仅应用到左值表达式；只要在不要求左值的语境中使用 const 左值表达式，就会丢失其 const 限定符（注意不丢失 volatile 限定符，若它存在）。  指代 const 限定类型对象的左值表达式，和指代拥有至少一个 const 限定类型成员（包含为聚合体或联合体所递归含有的成员）的结构体或联合体的左值表达式，不是可修改左值。具体而言，它们不可赋值：  const int n = 1; // const 类型对象 n = 2; // 错误： n 的类型为 const 限定   int x = 2; // 无限定类型对下 const int* p = &x; *p = 3; // 错误：左值 *p 的类型为 const 限定   struct {int a; const int b; } s1 = {.b=1}, s2 = {.b=2}; s1 = s2; // 错误： s1 的类型无限定，但它有 const 成员 const 限定的结构体或联合体类型的成员，取得它所属类型的限定版本（在用 . 运算符或 -> 运算符访问时）。  struct s { int i; const int ci; } s; // s.i 的类型为 int ， s.ci 的类型为 const int const struct s cs; // cs.i 和 cs.ci 的类型都是 const int 若以 const 类型限定符声明数组类型（通过使用 typedef ），则数组类型无 const 限定，但其元素类型有。若以 const 类型限定符声明函数类型（通过使用 typedef ），则行为未定义。  typedef int A[2][3]; const A a = {{4, 5, 6}, {7, 8, 9}}; // const int 的数组的数组 int* pi = a[0]; // 错误： a[0] 拥有 const int* 类型 const 限定的复合字面量不必指代相异的对象；能与恰好拥有重叠表示的其他复合字面量和字符串字面量一同存储它们。  const int* p1 = (const int[]){1, 2, 3}; const int* p2 = (const int[]){2, 3, 4}; // p2 的值可等于 p1+1 _Bool b = "foobar" + 3 == (const char[]){"bar"}; // b 的值可为 1 (C99 起) 指向非 const 类型的指针能隐式转换成指向同一或兼容类型的 const 限定版本的指针。能用转型表达式进行逆向转换。  int* p = 0; const int* cp = p; // OK ：添加限定符（ int 到 const int ） p = cp; // 错误：舍弃限定符（ const int 到 int ） p = (int*)cp; // OK ：转型 注意指向指向 T 指针的指针不可转换为指向指向 const T 指针的指针；对于要兼容的二个类型，其限定必须等同。  char *p = 0; const char **cpp = &p; // 错误： char* 与 const char* 不是兼容类型 char * const *pcp = &p; // OK ：添加限定符（ char * 到 char *const ） 任何修改有 const 限定类型的对象的尝试导致未定义行为。  const int n = 1; // const 限定类型对象 int* p = (int*)&n; *p = 2; // 未定义行为 函数声明中，关键词 const 可出现在用于声明数组类型函数参数的方括号内。它限定数组类型变换到的指针类型。  下列二个声明声明同一函数：  void f(double x[const], const double y[const]); void f(double * const x, const double * const y); (C99 起) 关键词 const  注意 C 从 C++ 接纳了 const 限定符，但不同于 C++ 中， C 中 const 限定类型的表达式不是常量表达式；它们不可用作 case 标号，或用于初始化静态和线程存储期对象、用作枚举项或位域大小。以之为数组大小是，产生的数组为 VLA 。  引用 C11 standard (ISO/IEC 9899:2011): 6.7.3 Type qualifiers (p: 121-123) C99 standard (ISO/IEC 9899:1999): 6.7.3 Type qualifiers (p: 108-110) C89/C90 standard (ISO/IEC 9899:1990): 3.5.3 Type qualifiers 参阅 cv （ const 与 volatile ）类型限定符 的 C++ 文

user: user-2
content: 引用 10 楼 m0_46108109 的回复:[quote=引用 8 楼 寻开心 的回复:]  是不是意味着程序有个最小大小。只有一行的代码，也要占用那么大区域？[/quote]  程序最小代码可以不用， 早期的com文件，可以只占据几个字节 那个图，只是展示了内存管理的方式。 不是意味着所有的区域都要有数据。 何况那个地址并不是真实的物理地址呢，是映射出来的  更多的你要去了解windows或者其他操作系统的内存管理方式了

user: user-3
content: 跟const没关系，这是常数的意思。

user: user-4
content: 引用 8 楼 寻开心 的回复: 是不是意味着程序有个最小大小。只有一行的代码，也要占用那么大区域？

user: user-5
content: 主要看这个变量在哪里定义，如果在函数外，那么该变量存放在数据段，如果在函数内定义，这个变量存放在栈上。

user: user-2

user: user-2
content: int global; int main() { int local; int *pHeap = (int*) malloc( sizeof(int)); printf("Global:%p. Local/Stack:%p Head:%p\n", &global, &local, pHeap); 这三个指针就明确的帮你定位了， 你看一下他们的指针值就能显著的看出区别 return 0; }

user: user-2
content: 在结构当中定义的LENGTH是结构的一个成员， 结构本身在堆了面，这个成员变量也在堆里面 其实这是个假的const， 通过强制类型转换，你还是可以改掉它的值的 只有分配在只读区域的那些const才是真的改不了的const 你定义的这种const，只是告诉编译器遇到对它的直接修改不允许，强制转换就是绕过它了

user: user-0
content: 引用 4 楼 寻开心 的回复:你可以自己做测试的 取得它的地址，printf用%p，输出它的地址， 看看就能知道了  自己再定义几个不同的变量， 全局的，局部的，动态的， 然后也都取地址，比较一下指针就看到它在哪一个区域了  地址怎么分辨区域？

user: user-2
content: 你可以自己做测试的 取得它的地址，printf用%p，输出它的地址， 看看就能知道了  自己再定义几个不同的变量， 全局的，局部的，动态的， 然后也都取地址，比较一下指针就看到它在哪一个区域了

user: user-2
content: 是的， 它是在堆当中了。

user: user-0
content: 引用 1 楼 寻开心 的回复:不一定， 还是看它是全局变量还是局部变量 局部变量还是在栈里面的 全局变量是在数据区，也不是栈，也不是堆  typedef  struct book { 	const int  LENGTH = 10;  }Book;  Book * book1 = (Book*)malloc(sizeof(Book));      book1中的LENGTH 是不是就在堆中了？

user: user-2
content: 不一定， 还是看它是全局变量还是局部变量 局部变量还是在栈里面的 全局变量是在数据区，也不是栈，也不是堆