Bo *_*nes 0 c string printf char
我从来没有真正做过多少C但是我开始玩它了.我写的小片段像下面这样去理解的关键结构/功能的使用和行为C中的一个下面我写试图理解之间的区别char* string和char 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)
这条线错了:
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分配的缓冲区.确保分配足够的空间来容纳整个字符串,包括终止零.
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'.