关于C中的字符串[重复]

2o7dmzc5  于 2023-10-16  发布在  其他
关注(0)|答案(2)|浏览(125)

此问题已在此处有答案

How to access a local variable from a different function using pointers?(10个答案)
25天前关闭
我是一个初学C的人,我试着写一个函数,它应该返回一个字符串,但当我试图打印从函数获得的结果时,我只得到(null)
下面是我的代码:

  1. char *reverse(char *str) {
  2. char result[20];
  3. /* logic */
  4. return result;
  5. }
  6. int main() {
  7. char str[20];
  8. printf("Enter a string: ");
  9. scanf("%[^\n]s", str);
  10. printf("The string reversed is: %s", reverse(str));
  11. }

为什么这个打印(null),当我注意到这样的东西工作得很好:

  1. char *func() {
  2. return "hello";
  3. }
  4. int main() {
  5. printf("%s", func());
  6. }
hjqgdpho

hjqgdpho1#

函数reverse()返回一个指针,指向在函数体中使用局部作用域定义的数组:当函数返回并且指针变为无效(悬空指针)时,此数组将超出作用域。从无效指针进行阅读具有未定义的行为。令人惊讶的是,printf为此输出(null),但未定义的行为意味着任何事情都可能发生,不要感到惊讶,不要期望下一次发生同样的行为,试图解释实际观察到的行为是徒劳的。
你应该使数组static或从堆中分配它,或者更好地,把目标数组作为参数。
注意scanf("%[^\n]s", str)是不正确的:

  • 后面的s没有意义,应该删除;
  • 应该指定要存储到str中的最大字符数,以避免潜在的缓冲区溢出:scanf("%19[^\n]", str)
  • 你应该测试scanf()的返回值来检测无效或丢失的输入,比如一个空行。

以下是修改后的版本:

  1. #include <stdio.h>
  2. #include <string.h>
  3. char *reverse(char *result, const char *str) {
  4. size_t len = strlen(str);
  5. for (size_t i = 0; i < len; i++) {
  6. result[i] = str[len - 1 - i];
  7. }
  8. result[len] = '\0';
  9. return result;
  10. }
  11. int main(void) {
  12. char str[20];
  13. char output[20];
  14. printf("Enter a string: ");
  15. if (scanf("%19[^\n]", str) == 1) {
  16. printf("The string reversed is: %s\n", reverse(output, str));
  17. return 0;
  18. } else {
  19. return 1;
  20. }
  21. }
展开查看全部
k5ifujac

k5ifujac2#

您的代码段打印(null)的原因是您从reverse函数返回了一个本地数组结果,这是一个堆栈分配的数组。一旦reverse函数返回,结果数组的内存将被释放,并留下一个悬空指针。如果忽略此指针,则会导致未定义的行为,在您的情况下,它恰好是print(null)。

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4. char* reverse(const char* str) {
  5. int length = strlen(str);
  6. char* result = (char*)malloc((length + 1) * sizeof(char));
  7. if (result == NULL) {
  8. fprintf(stderr, "Memory allocation failed.\n");
  9. exit(1);
  10. }
  11. for (int i = 0; i < length; i++) {
  12. result[i] = str[length - 1 - i];
  13. }
  14. result[length] = '\0';
  15. return result;
  16. }
  17. int main() {
  18. char str[20];
  19. printf("Enter a string: ");
  20. scanf("%19[^\n]", str); // Limit input length to avoid buffer overflow
  21. char* reversed = reverse(str);
  22. printf("The string reversed is: %s\n", reversed);
  23. // Don't forget to free the dynamically allocated memory when done
  24. free(reversed);
  25. return 0;
  26. }

1.我们使用malloc为结果字符串动态分配内存。字符串的长度由strlen(str)决定,我们加1来容纳空终止符。
1.我们将输入字符串str中的字符以相反的顺序复制到动态分配的结果字符串中。
1.我们确保结果字符串以空终止。
1.在使用反转字符串之后,使用free释放动态分配的内存以避免内存泄漏是很重要的。

展开查看全部

相关问题