I';我是C语言的新手,有人能解释为什么这个字符串的大小会改变吗?

I';我是C语言的新手,有人能解释为什么这个字符串的大小会改变吗?,c,string,char,printf,C,String,Char,Printf,我从来没有真正做过太多的C,但我开始玩它。我正在写下面这样的小片段,试图理解C中关键结构/函数的用法和行为。下面我写的片段试图理解char*string和char string[]之间的区别,以及字符串的长度是如何工作的。此外,我想看看是否可以使用sprintf连接两个字符串并将其设置为第三个字符串 我发现,我用来存储其他两个字符串的连接的第三个字符串必须设置为char string[]语法,否则二进制文件将与SIGSEGV(地址边界错误)一起消失。使用数组语法设置它需要一个大小,所以我首先将它

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

我发现,我用来存储其他两个字符串的连接的第三个字符串必须设置为
char string[]
语法,否则二进制文件将与
SIGSEGV(地址边界错误)
一起消失。使用数组语法设置它需要一个大小,所以我首先将它设置为其他两个字符串的组合大小。这似乎让我能够很好地执行连接

不过出于好奇,我尝试将“连接”字符串扩展为比我分配的长度更长的字符串。令我惊讶的是,它仍然有效,字符串大小增加,可以
printf
'd

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

#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));
}
#包括
#包括
#包括
void main(){
char*str1=“Sup”;
char*str2=“Dood”;
int length1=strlen(str1);
int length2=strlen(str2);
int length3=长度1+长度2;
字符str3[长度3];
//char-str3[7];
printf(“%s(长度%d)\n”,str1,长度1);//Sup(长度3)
printf(“%s(长度%d)\n”,str2,长度2);//Dood(长度4)
printf(“总长度:%d\n”,长度3);//总长度:7
printf(“str3长度:%d\n”,(int)strlen(str3));//str3长度:6
sprintf(str3,“%s%s”,str1,str2);
printf(“%s\n”,str3);//SupDood
printf(“sprintf之后的str3长度:%d\n”,//sprintf之后的str3长度:29
(int)strlen(str3);;
}
这一行是错误的:

char str3[length3];
你没有考虑到终止零。应该是:

char str3[length3+1];
您还试图获取str3的长度,而它尚未设置

此外,该行:

sprintf(str3, "%s<-------------------->%s", str1, str2);
sprintf(str3、%s%s)、str1、str2);

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

您的
str3
太短-您需要为空终止符和“”字符串文本的长度添加额外的字节

不过出于好奇,我试了一下 将“连接”字符串扩展为 比我的尺码长 分配。令我大吃一惊的是,它 仍然工作和字符串大小 增加了,可以打印出来


该行为未定义,因此它可能会或可能不会发生故障。

strlen
返回字符串长度,但不带尾随的空字节(
\0
0x00
),但当您创建一个变量来保存组合字符串时,需要添加该1个字符

char str3[length3 + 1];

…你应该准备好了。

我建议你去当地的书店买一本“C编程入门”书,而不是通过反复试验来学习C。那样的话,你会对这门语言有更好的了解


没有什么比一个半懂C的程序员更危险的了

C字符串以“\0”结尾,需要额外的字节,所以至少应该这样做

char str3[length3 + 1]

将完成此任务。

在sprintf()中,ypu的写入超出了为str3分配的空间。这可能会导致任何类型的未定义行为(如果幸运的话,它将崩溃)。在strlen()中,它只是从指定的内存位置搜索空字符,并在第29个位置找到一个。它也可以是129,也就是说,它的行为非常不稳定。

你必须理解的是,C实际上没有字符串,它有字符数组。此外,字符数组没有相关的长度信息——相反,字符串长度是通过迭代字符直到遇到空字节来确定的。这意味着,每个字符数组的长度至少应为strlen+1个字符

C不执行数组边界检查。这意味着您盲目调用的函数信任您为字符串分配了足够的空间。如果情况并非如此,则可能会超出为字符串分配的内存范围。对于堆栈分配的字符数组,您将覆盖局部变量的值。对于堆分配的字符数组,您可以在应用程序的内存区域之外进行写入。在这两种情况下,最好的情况是你会立即出错,而最坏的情况是事情看起来正常,但实际上却不正常

至于作业,你不能这样写:

char *str;
sprintf(str, ...);
并且期望它能工作——str是一个未初始化的指针,因此该值是“未定义的”,实际上意味着“垃圾”。指针是内存地址,因此尝试写入未初始化指针就是尝试写入随机内存位置。这不是个好主意。相反,您要做的是:

char *str = malloc(sizeof(char) * (string length + 1));
它分配了n+1个字符的存储空间,并将指向该存储空间的指针存储在str中。当然,为了安全起见,您应该检查malloc是否返回null。完成后,您需要拨打免费电话(str)

您的代码使用数组语法的原因是,作为局部变量的数组是自动分配的,因此实际上有一个空闲的内存片。对于未初始化的指针,情况通常不是这样

至于字符串大小如何变化的问题,
char str[] = "Foo bar";
str[1] = (char)0; // I'd use the character literal, but this editor won't let me
char str[] = "Foo bar";
str[7] = '!';
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
printf("str3 length: %d\n", (int)strlen(str3));      // What is the length of str3? str3 is uninitialized!
sprintf(str3, "%s<-------------------->%s", str1, str2); 
printf("%s\n", str3);  // Sup<-------------------->Dood