我是C的新手,有人可以解释为什么这个字符串的大小可以改变吗?

Bo *_*nes 0 c string printf char

我从来没有真正做过多少C但是我开始玩它了.我写的小片段像下面这样去理解的关键结构/功能的使用和行为C中的一个下面我写试图理解之间的区别char* stringchar string[]如何则字符串的长度工作.此外,我想看看是否sprintf可以用来连接两个字符串并将其设置为第三个字符串.

我发现我用来存储其他两个串联的第三个字符串必须用char string[]语法设置,否则二进制文件会死掉SIGSEGV (Address boundary error).使用数组语法设置它需要一个大小,所以我最初通过将其设置为其他两个字符串的组合大小来开始.这似乎让我足够好地执行连接.

但出于好奇,我尝试将"连接"字符串扩展为比我分配的字符更长.令我惊讶的是,它仍然有效,字符串大小增加,可能会printf很好.

我的问题是:为什么会发生这种情况,它是无效还是有风险/缺点?此外,为什么char str3[length3]有效但在行尝试执行char str3[7]时会导致"SIGABRT(Abort)" sprintf

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

void main() {
    char* str1 = "Sup";
    char* str2 = "Dood";

    int length1 = strlen(str1);
    int length2 = strlen(str2);
    int length3 = length1 + length2;

    char str3[length3];
    //char str3[7];

    printf("%s (length %d)\n", str1, length1);           // Sup (length 3)
    printf("%s (length %d)\n", str2, length2);           // Dood (length 4)
    printf("total length: %d\n", length3);               // total length: 7
    printf("str3 length: %d\n", (int)strlen(str3));      // str3 length: 6
    sprintf(str3, "%s<-------------------->%s", str1, str2); 
    printf("%s\n", str3);                                // Sup<-------------------->Dood

    printf("str3 length after sprintf: %d\n",            // str3 length after sprintf: 29
            (int)strlen(str3));
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*ert 9

这条线错了:

char str3[length3];
Run Code Online (Sandbox Code Playgroud)

您没有考虑终止零点.它应该是:

char str3[length3+1];
Run Code Online (Sandbox Code Playgroud)

你也试图获得str3的长度,但还没有设置.

另外,这一行:

sprintf(str3, "%s<-------------------->%s", str1, str2);
Run Code Online (Sandbox Code Playgroud)

将溢出为str3分配的缓冲区.确保分配足够的空间来容纳整个字符串,包括终止零.


jal*_*alf 6

void main() {
    char* str1 = "Sup"; // a pointer to the statically allocated sequence of characters {'S', 'u', 'p', '\0' }
    char* str2 = "Dood"; // a pointer to the statically allocated sequence of characters {'D', 'o', 'o', 'd', '\0' }

    int length1 = strlen(str1); // the length of str1 without the terminating \0 == 3
    int length2 = strlen(str2); // the length of str2 without the terminating \0 == 4
    int length3 = length1 + length2;

    char str3[length3]; // declare an array of7 characters, uninitialized
Run Code Online (Sandbox Code Playgroud)

到现在为止还挺好.现在:

printf("str3 length: %d\n", (int)strlen(str3));      // What is the length of str3? str3 is uninitialized!
Run Code Online (Sandbox Code Playgroud)

C是一种原始语言.它没有字符串.它具有的是数组和指针.字符串是约定,而不是数据类型.按照惯例,人们同意"字符数组是一个字符串,字符串以第一个空字符结束".所有C字符串函数都遵循此约定,但它是一种约定.简单地假设您遵循它,否则字符串函数将会中断.

所以,str3不是有7个字符的字符串.它是一个包含7个字符的数组.如果将它传递给需要字符串的函数,那么该函数将查找a '\0'以查找字符串的结尾.str3从未初始化,因此它包含随机垃圾.在你的情况下,显然,有一个'\0'在第6个字符之后所以strlen返回6,但这不能保证.如果它不存在,那么它将读取超过数组的末尾.

sprintf(str3, "%s<-------------------->%s", str1, str2); 
Run Code Online (Sandbox Code Playgroud)

而且这里又出错了.您正在尝试将字符串复制"Sup<-------------------->Dood\0"到7个字符的数组中.那不合适.当然C函数不知道这个,它只是复制超过数组的末尾.未定义的行为,可能会崩溃.

printf("%s\n", str3);  // Sup<-------------------->Dood
Run Code Online (Sandbox Code Playgroud)

在这里,您尝试打印存储在的字符串str3.printf是一个字符串函数.它不关心(或知道)数组的大小.它被赋予一个字符串,并且像所有其他字符串函数一样,通过查找a来确定字符串的长度'\0'.