堆栈上的常量数据?
Const data on the stack?
我打算回答某人有关 printf 接受 char * 的问题,所以我构建了一个小测试程序并提出了自己的问题。使用 GCC 6.3
在 codechef.com/ide 上编译
Pass the char* directly to printf
我认为问题是问 "missing" const 限定符发生了什么,对吧?
http://man7.org/linux/man-pages/man3/printf.3.html
char * str1 = "This is string 1\n";
char str2[] = "This is string 2\n";
int main(void) {
char str3[100] = "This is string 3\n";
char * str4 = "This is string 4\n";
str3[8] = 'c';
printf(str1);
printf(str2);
printf(str3);
printf(str4);
return 0;
}
输出:
这是字符串 1
这是字符串 2
这是 ctring 3
这是字符串 4
我正在考虑程序的内存布局,我更加困惑了。 https://www.geeksforgeeks.org/memory-layout-of-c-program/
str1 是指向字符串文字 "this is a string 1\n" 的指针。 str1 存在于 data 中并指向存在于 ?? 中的字符串文字(我假设还初始化了数据段)
How is read-only memory implemented in C?
就内存布局而言,str2 与 str1 相似。
str3 是有趣的地方。 str3 存在于堆栈中,100 个字符宽,并被分配给 char[0] = 'T'、char[1] = 'h' 等 declaration/assignment。这不应该是 CONST。 str3 的声明和赋值是在堆栈上声明 100 个字符并从数据(rom 数据段或初始化数据段或文本?)中为它们赋值。
str4是栈上指针,指向数据段内存。这个有点像str1和str2,没啥意思
然后将 str3[8] = 'c' 分配给 test/verify/demonstrate str3 的堆栈内存在 printfing 之前不是只读的。
我希望 1、2、4 可以工作,但为什么 3 可以工作(甚至没有编译器警告???)。我可能错误地认为 const 是 "read only" 的同义词,因为如果我只是写信给它, str3 就不可能是 "read only"。
任何人都可以向我解释为什么 str3 没有发出警告或错误吗? str3 不是 const char *,要么是编译器优化了它(将赋值更改为 "This is ctring 3\n"),要么是警告被抑制(似乎也不太可能),或者我对 cost 关键字有根本性的误解。堆栈内存如何常量?也许我的一个或多个假设是错误的。
当函数原型包含指向 const
限定对象的指针时,这意味着该函数承诺不会尝试修改指向的内容。这并不意味着只能接受指向 const
对象(无论可能是什么)的指针。
另一方面,如果原型包含一个指向对象的指针,该对象不符合const
,这意味着它可能会尝试修改内容。在那种情况下,将指针传递给不可变对象会导致未定义的行为。如果您尝试将指针传递给 const
限定对象(如果启用警告),大多数编译器会警告您,因为 const
限定指针可能指向不可变对象。
一般来说,您应该将 const
视为 "I promise not to modify this" 而不是 "this cannot be modified"。
我打算回答某人有关 printf 接受 char * 的问题,所以我构建了一个小测试程序并提出了自己的问题。使用 GCC 6.3
在 codechef.com/ide 上编译Pass the char* directly to printf 我认为问题是问 "missing" const 限定符发生了什么,对吧? http://man7.org/linux/man-pages/man3/printf.3.html
char * str1 = "This is string 1\n";
char str2[] = "This is string 2\n";
int main(void) {
char str3[100] = "This is string 3\n";
char * str4 = "This is string 4\n";
str3[8] = 'c';
printf(str1);
printf(str2);
printf(str3);
printf(str4);
return 0;
}
输出:
这是字符串 1
这是字符串 2
这是 ctring 3
这是字符串 4
我正在考虑程序的内存布局,我更加困惑了。 https://www.geeksforgeeks.org/memory-layout-of-c-program/
str1 是指向字符串文字 "this is a string 1\n" 的指针。 str1 存在于 data 中并指向存在于 ?? 中的字符串文字(我假设还初始化了数据段) How is read-only memory implemented in C?
就内存布局而言,str2 与 str1 相似。
str3 是有趣的地方。 str3 存在于堆栈中,100 个字符宽,并被分配给 char[0] = 'T'、char[1] = 'h' 等 declaration/assignment。这不应该是 CONST。 str3 的声明和赋值是在堆栈上声明 100 个字符并从数据(rom 数据段或初始化数据段或文本?)中为它们赋值。
str4是栈上指针,指向数据段内存。这个有点像str1和str2,没啥意思
然后将 str3[8] = 'c' 分配给 test/verify/demonstrate str3 的堆栈内存在 printfing 之前不是只读的。
我希望 1、2、4 可以工作,但为什么 3 可以工作(甚至没有编译器警告???)。我可能错误地认为 const 是 "read only" 的同义词,因为如果我只是写信给它, str3 就不可能是 "read only"。
任何人都可以向我解释为什么 str3 没有发出警告或错误吗? str3 不是 const char *,要么是编译器优化了它(将赋值更改为 "This is ctring 3\n"),要么是警告被抑制(似乎也不太可能),或者我对 cost 关键字有根本性的误解。堆栈内存如何常量?也许我的一个或多个假设是错误的。
当函数原型包含指向 const
限定对象的指针时,这意味着该函数承诺不会尝试修改指向的内容。这并不意味着只能接受指向 const
对象(无论可能是什么)的指针。
另一方面,如果原型包含一个指向对象的指针,该对象不符合const
,这意味着它可能会尝试修改内容。在那种情况下,将指针传递给不可变对象会导致未定义的行为。如果您尝试将指针传递给 const
限定对象(如果启用警告),大多数编译器会警告您,因为 const
限定指针可能指向不可变对象。
一般来说,您应该将 const
视为 "I promise not to modify this" 而不是 "this cannot be modified"。