问题描述
当我在主函数中使用整个代码时,它运行良好,但现在我想将该函数用于一些我在二维数组中初始化的“字符串”。
该函数背后的想法是创建一个全局初始化的结构体的乘积。带有 strcpy
的行给出了错误:
Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP,subcode=0x0).
我在 Mac 上使用 Xcode 11.3.1。
你们能帮我解决这个问题吗?
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <time.h>
struct produkt neues_angebot(char *produktname);
struct produkt{
char name[5];
int produkt_zahl;
float produkt_preis;
};
struct produkt neues_angebot(char *produktname){
time_t t;
srand((unsigned) time(&t));
struct produkt Zwischenname = {
"xxx",(rand() % 49),((rand()% 600)/100)
};
strcpy(Zwischenname.name,produktname);
return Zwischenname;
}
int main(int argc,const char * argv[]) {
char teste[]="hello";
printf("%s\n",neues_angebot(teste).name);
}
解决方法
C 中的字符串以空字符结尾。字符串 "hello"
使用 6 个字节的存储空间:5 个字符 h e l l o
加上终止的空字符。
现在 strcpy
不进行长度检查,因此 strcpy(Zwischenname.name,produktname)
将尝试将所有 6 个字节复制到数组 Zwischenname.name
中,该数组只有 5 个字节的空间。这会溢出数组并且是未定义的行为 - 您观察到的崩溃是许多可能的结果之一。
strcpy
会将 teste
的最后一个字符(空终止符 '\0'
)复制到目标缓冲区的边界之外,因为它比需要的长度短一个字节,这将导致 Zwischenname.name
不是空终止。
问题是 printf
需要空终止符才能知道字符串在哪里结束才能正常工作,将非空终止字符数组作为参数传递给 printf("%s",argument);
会调用未定义的行为。
请记住,为了将字符数组视为正确的字符串,它需要以空字符结尾,C 中的许多库函数都依赖于这一原则。始终确保它是。