c - 为什么我的程序允许我更改 C 中 const char 的值?
问题描述
我使用 CodeBlocks for Windows 作为我的 IDE。我的程序有问题,我想了解一下。在我展示的程序中,我将一个变量声明为 achar*
并且我的程序将其转换为const char*
. 我希望这char*
是只读的,但我可以修改,因为我不知道是什么原因。
这是我的代码:
#include <stdio.h>
#include <windows.h>
int main() {
int i, d;
char *array[5][5]; // This is the variable that I declare as char*
for (i = 0; i != 5; i++) {
for (d = 0; d != 5; d++) {
array[i][d] = " "; // I can change its value because it is a char* type variable
}
}
for (i = 1; i != 0; i++) {
printf("%s %s %s %s %s\n", array[0][0], array[0][1], array[0][2], array[0][3], array[0][4]);
printf("%s %s %s %s %s\n", array[1][0], array[1][1], array[1][2], array[1][3], array[1][4]);
printf("%s %s %s %s %s\n", array[2][0], array[2][1], array[2][2], array[2][3], array[2][4]);
printf("%s %s %s %s %s\n", array[3][0], array[3][1], array[3][2], array[3][3], array[3][4]);
printf("%s %s %s %s %s\n", array[4][0], array[4][1], array[4][2], array[4][3], array[4][4]);
array[0][0] = "AAA"; // Again I can change its value
array[1][0] = "BBB"; // And again...
Sleep(1000);//This is only to see the results
system("cls");
if (i == 5) {
array[0][0] = strdup(array[1][0]); // I was trying to copy two strings using the strcpy() but the program stopped, and the problem was that the destiny string was a const char* type string and that couldn't be, even though I could change it before
strcpy(array[0][0], array[1][0]);
}
}
return 0;
}
解决方案
char *array[5][5]
定义array
为指向 modifiable 的可修改 2D 指针数组char
。你可以修改它的元素,它们指向的字符串也可以修改。
尽管" "
是一个字符串文字,如果不调用未定义的行为就无法修改,但 C 标准不会将其键入为const char[]
,而是 as ,当存储到 的元素时char []
,它会衰减为 a 。char *
array
当你strcpy(array[0][0], array[1][0])
直接写时,你试图用指向array[0][0]
的字符串的内容来修改指向的内存array[1][0]
。由于您将字符串文字的地址存储在 中array[0][0]
,因此您实际上是在尝试修改存储字符串文字的内存,这具有未定义的行为。
相反,strdup(array[1][0])
分配 指向的字符串的副本array[1][0]
并返回一个可以存储到array[0][0]
. 下一条语句strcpy(array[0][0], array[1][0]);
将原始字符串复制到其副本之上,这是允许的并且没有效果。您可以删除对 的调用strcpy()
。
建议声明array
为const char *array[5][5]
,使strcpy(array[0][0], array[0][1])
产生警告,但允许array[0][0] = strdup(array[0][1])
。但是请注意,一旦您在这个数组中混合了字符串文字和分配的字符串,您将无法分辨哪些应该被释放,哪些不能。所有分配的内存将在退出时释放,但如果程序运行很长时间并不断修改此数组,则无法进行适当的内存管理将导致内存泄漏和潜在的无限内存使用。
一些编译器提供了将字符串文字类型作为const char[]
(例如:)的扩展gcc -Wwrite-strings
。使用此选项,当您存储" "
到array[0][0]
. 默认情况下使用此设置是一种很好的做法,但可能需要在大型程序中进行大量修改,const
在许多地方添加一个称为const
中毒的过程。在此过程中发现潜在错误并不罕见。const
更一般地说,如果函数定义中的指针参数不直接或间接用于修改它指向的对象,则应该声明它。它可以帮助读者理解代码,也可以帮助编译器生成更好的可执行代码。
推荐阅读
- c - 主对角线和反对角线的 C 矩阵元素相同
- ios - 尝试将应用上传到应用商店时出错,
- html - 放大浏览器时如何阻止元素相互遮挡
- python - 从 N 名玩家中生成每场可能的比赛,并创建 N-1 组,每组 N/2 场比赛
- python - scikit-learn 似乎没有正确构建
- jekyll - Github 页面,使用 jekyll 隐藏两个 markdown 页面
- npm - pnpm 与 winrar。哪些方法可以更快地安装模块?
- typescript - 为什么 Vue 3 无法识别我的 Vuex 商店模块?
- python - 日期时间格式问题
- classloader - 使用 catalog.lookup 从函数转换返回值时发生 ClassCastException