我想了解C上字符串的一些内容:
我无法理解为什么你不能在正常的作业中改变字符串。 (但只能通过string.h的函数),例如:我不能d="aa"
(d是char的指针或char数组)。
有人可以向我解释幕后发生了什么 - 编译器会运行这样的事情而你会收到分段错误错误。
其他的,我在C中运行一个包含以下行的程序:
char c='a',*pc=&c;
printf("Enter a string:");
scanf("%s",pc);
printf("your first char is: %c",c);
printf("your string is: %s",pc);
任何人都可以解释背后发生的事情吗?
请注意: 我不希望程序正常运行,我没有问这个问题来获取其他程序的建议,我只想了解在这些情况下幕后发生的事情。
答案 0 :(得分:2)
C中几乎不存在字符串(除了像某些C源文件中的"abc"
这样的C字符串文字)。
实际上,字符串主要是约定:C字符串是char
的数组,其最后一个元素是零字符'\0'
。
如此声明
const char s[] = "abc";
与
完全相同 const char s[] = {'a','b','c','\0'};
特别是,sizeof(s)
在两种情况下都是4(3 + 1)(因此sizeof("abc")
)。
标准C库包含许多函数(例如strlen(3)或strncpy(3) ...),这些函数遵循和/或预先假定字符串是{{1}的零终止数组的约定} -s
更好的代码是:
char
一些评论:害怕buffer overflow。读取字符串时,总是给读取字符串绑定,或者使用getline(3)之类的函数,dynamically allocates堆中的字符串。谨防memory leaks(使用像valgrind这样的工具......)
计算字符串时,也要注意最大尺寸。请参阅snprintf(3)(避免char buf[16]="a",*pc= buf;
printf("Enter a string:"); fflush(NULL);
scanf("%15s",pc);
printf("your first char is: %c",buf[0]);
printf("your string is: %s",pc);
)。
通常,您采用的惯例是返回一个字符串并在堆中动态分配。如果您的系统提供,您可能需要使用strdup(3)或asprintf(3)。但是你应该采用调用函数(或其他东西,但在你脑中定义得很好)的约定free(3) - 字符串。
你的程序在语义上可能是错误的,并且运气不好发生在有时的工作中。仔细阅读undefined behavior。绝对避免它(你的点1,2,3可能是UB)。可悲的是,UB有时可能会“工作”。
为了解释一些实际的未定义行为,你必须考虑你的特定实现:编译器,标志 - 特别是优化标志 - 传递给编译器,操作系统,内核,处理器,月相等等......未定义的行为通常不可重现(例如因为ASLR等...),请阅读heisenbugs。要解释第1,2,3点的行为,您需要深入了解实施细节;查看编译器生成的汇编代码(sprintf
)。
我建议你使用所有警告和调试信息编译你的代码(例如使用gcc -S -fverbose-asm
和GCC ...),改进代码,直到你没有警告,并学习如何使用调试器(例如gcc -Wall -g
)逐步运行代码。
答案 1 :(得分:1)
如果我输入2个以上的字母(在scanf上)我会出现分段错误错误,为什么会这样?
因为内存仅分配给一个字节。
请参阅char c
并指定"a"
。等于'a'
且'\0'
写入一个字节的内存位置。
如果scanf()
使用此内存来读取多个字节,那么这只是未定义的行为。
答案 2 :(得分:0)
char c="a";
是c语言中的错误声明,因为即使单个字符包含在一对双引号(""
)中也会被视为C中的字符串,因为它被视为"一个\ 0"因为所有字符串都以' \ 0'空字符。
<{1}}是错误的,因为char c="a";
是正确的。
另请注意,为char分配的内存仅为1byte,因此它只能容纳一个字符,数据类型的内存分配详细信息如下所述