C语言中字符串字面量赋值给char*报错E0513问题求助
字符串字面量赋值给char*的编译差异问题及解决
可正常运行的代码
#include <stdio.h> struct student { char* name; }; struct student s[2]; void main() { s[0].name = "jason"; s[1] = s[0]; printf("%s%s", s[0].name, s[1].name); s[1].name = "fedin"; printf("%s%s", s[0].name, s[1].name); }
编译报错的代码
#include<stdio.h> #include<string.h> #include<stdlib.h> struct item { char* itemName; int quantity; float price; float amount; }; void readItem(item* const p) { printf("Please enter item name. \n"); fgets(p->itemName, 50, stdin); for (int i = 0; i < strlen(p->itemName); i++) { if (p->itemName[i] == '\n') { p->itemName[i] = NULL; } } printf("Please enter the quantity. \n"); scanf_s("%d", &p->quantity); printf("Please enter the price. \n"); scanf_s("%f", &p->price); } void print(item* const p) { printf("Item Name: %s \n", p->itemName); printf("Quantity: %i \n", p->quantity); printf("Price: %.4f \n", p->price); p->amount = (p->quantity) * (p->price); printf("Amount: %.4f \n", p->amount); } int main(void) { struct item item1; item1.itemName = "SDfsd"; item1.quantity = 0; item1.price = 0.0; item1.amount = 0.0; struct item* itemP = &item1; readItem(itemP); print(itemP); free(itemP->itemName); itemP->itemName = NULL; return 0; }
编译错误信息
Error (active) E0513 a value of type "const char *" cannot be assigned to an entity of type "char *" Structure Pointers and Functions F:\Mohamed Taha\Codes\C Programming\C Programming For Beginners\vs\Structure Pointers and Functions\Structure Pointers and Functions\mian.cpp 41
原因分析
- 字符串字面量的本质:C标准规定,字符串字面量(如
"jason")的类型为const char[],存储在程序的只读数据段,不允许被修改。 - 两段代码的编译差异:
- 第一段代码仅对指针做赋值和读取操作,从未尝试修改字符串字面量的内容。旧版C标准(C89)允许
const char*隐式转换为char*,多数编译器为兼容旧代码,在未开启严格编译选项时不会报错。 - 第二段代码中,
readItem函数试图通过fgets修改itemName指向的内存,后续还调用free释放该指针——这两个操作均属非法:只读内存不可写入,且字符串字面量并非堆内存分配,不能用free释放。编译器的严格检查(如VS默认编译选项)捕捉到风险,抛出类型不兼容错误,阻止非法操作的发生。
- 第一段代码仅对指针做赋值和读取操作,从未尝试修改字符串字面量的内容。旧版C标准(C89)允许
解决方案
方案一:使用栈数组
修改结构体定义,将char* itemName替换为固定大小的栈数组,无需手动管理内存,直接支持写入:
struct item { char itemName[50]; int quantity; float price; float amount; };
注意:栈数组无需调用free,作用域结束后自动释放。
方案二:动态分配堆内存
若需灵活的内存大小,在main中为itemName分配堆内存,使用完毕后释放:
int main(void) { struct item item1; // 分配可写入的堆内存,大小按需调整 item1.itemName = (char*)malloc(50 * sizeof(char)); if (item1.itemName == NULL) { printf("Memory allocation failed\n"); return 1; } // 初始化字符串 strcpy(item1.itemName, "SDfsd"); item1.quantity = 0; item1.price = 0.0; item1.amount = 0.0; struct item* itemP = &item1; readItem(itemP); print(itemP); // 安全释放堆内存 free(itemP->itemName); itemP->itemName = NULL; return 0; }
注意:动态分配后需检查malloc是否成功,避免空指针操作。
额外修正:换行符处理逻辑
原代码中用NULL替换换行符错误,NULL是指针类型,应使用字符'\0',且可优化循环逻辑:
if (p->itemName[i] == '\n') { p->itemName[i] = '\0'; break; // 找到换行符后直接退出循环 }
更简洁的写法:
p->itemName[strcspn(p->itemName, "\n")] = '\0';
内容的提问来源于stack exchange,提问作者Mohamed Taha
相关产品推荐
相关产品推荐

