C 如何处理替换字符串文本,以及为什么在堆上进行分配很重要?

C 如何处理替换字符串文本,以及为什么在堆上进行分配很重要?,c,c-strings,C,C Strings,我从一个程序员那里听说,替换c字符串文字会导致未定义的行为 例如: 但是,我找不到像下面这样的方法,我必须将12小时的时间转换为军事时间: char* timeConversion(char* s) { char* military_time = malloc(9*sizeof(char)); strncpy(military_time, s,8); if(s[8] == 'P'){ if(s[0]!='1' || s[1]!='2'){ ch

我从一个程序员那里听说,替换c字符串文字会导致未定义的行为

例如:

但是,我找不到像下面这样的方法,我必须将12小时的时间转换为军事时间:

char* timeConversion(char* s) {
    char* military_time = malloc(9*sizeof(char));
    strncpy(military_time, s,8);
    if(s[8] == 'P'){
       if(s[0]!='1' || s[1]!='2'){
       char hours = 10*(s[0]-'0')+(s[1]-'0');
       hours += 12;
       char tenner = (hours/10) + '0';
       char onner = hours%10 + '0';
       military_time[0] = tenner; //undefined
       military_time[1] = onner;
       }
    } else {
        if(s[0]=='1' && s[1] =='2'){
            military_time[0] = '0';
            military_time[1]= '0';
        }
    }
    return military_time;
}
有办法解决这个问题吗

此外,我想知道这个代码的行为。 替换:

char* military_time = malloc(9*sizeof(char));
与:

导致错误的行为。我不认为在第二种情况下,变量会过时。这可能是我提交答案的网站的问题吗

多谢各位

我从一个程序员那里听说,替换c字符串文字会导致未定义的行为

正确,您不能尝试修改字符串文字。编译器通常将它们放在只读区域中

指向字符串文本的指针应使用
const
声明,以避免未定义的行为:

char const *a = "111"; 
a[0] = '2';            // Ok: compiler error, because assigment to const
然而,我没有找到一种方法,就像下面的练习一样

char*军事时间=malloc(9*sizeof(char))不创建字符串文字,因此
军事时间[0]=tenner很好

您可以修改已为其分配内存的内存:

char b[] = "111";      // Create array and initialize with contents copied from literal
b[0] = '2';            // Ok: array can be modified

char *c = malloc(4);   // Create pointer which points to malloc'd area
strcpy(c, "111");      // Copy content from literal
c[0] = '2';            // Ok: pointer points to area that can be modified
导致错误的行为


是的,由于上述原因,代码不正确。

您可以使用数组为字符串分配内存:
char-millitary\u-time[]=“12345678”
。然后你可以写信给它。您仍然无法返回它,因为当您离开函数时,它将被删除。为此,函数通常要么返回由
malloc
分配的指针,要么将指针作为函数要写入的参数(例如
fread
)。但是如果你真的很绝望,你可以让数组成为静态的,这意味着只要程序处于活动状态,它就会存在(但是它也会一直占据空间,即使你不需要它)
(s[0]-48)+(s[1]-48)
?不要那样做。使用字符值
'0'
而不是
48
。48不能保证工作,
'0'
将始终工作。48也是令人困惑的。当你让调用者提供你所需要的存储时,这总是变得更容易。然后,它可以决定如何分配它,如果需要,还可以决定如何发布它。很少有必要这样做。因此签名应该是int-timeConversion(const-char*time,char[]result,size\u t resultLen)。使用int返回值指示错误情况,如不可转换的时间字符串或结果缓冲区太小。
a[0]=“2”
最像是导致分段错误,因为
a
指向一个只读文本。尽管您可以这样做:
char music_time[]=“12345678”因为这会将只读文本复制到您的数组中,该数组是可修改的。谢谢您的回答。您可以添加哪些类型的数据(关于c字符串、字符和文字)在离开该方法后被删除,哪些必须手动删除。malloced数据在过程结束后可以存在,这是真的吗?我很好奇,因为我在同一个练习中遇到了这样的问题。@TVSuchty这实际上是一个单独的问题,但简单地说,
timeConversion
中的所有数据都在函数exit中被释放,除了一个用
malloc(9*sizeof(char))
创建的数据。它将一直存在,直到您
free()
It,或者当程序结束并且操作系统回收内存时;返回a
,即使我不修改任何内容也不起作用,因为
a
被破坏了?@TVSuchty不,这个例子很好。像
“brevb”
这样的文本与您的程序一样长时间存在
a
被销毁,但这并不重要,因为
“brevb”
的地址在
返回a中被返回在此之前。这太令人困惑了。因此,地址被复制然后销毁,而指向的内存仍然保留。那么为什么我不能返回一个数组,返回的数组应该复制数组,然后销毁内部数组
char const *a = "111"; 
a[0] = '2';            // Ok: compiler error, because assigment to const
char b[] = "111";      // Create array and initialize with contents copied from literal
b[0] = '2';            // Ok: array can be modified

char *c = malloc(4);   // Create pointer which points to malloc'd area
strcpy(c, "111");      // Copy content from literal
c[0] = '2';            // Ok: pointer points to area that can be modified
char* military_time = "12345678";