【问题标题】:Beginner C: Why two variables are initialed differently初学者 C:为什么两个变量的初始值不同
【发布时间】:2014-09-18 21:25:57
【问题描述】:

我有以下代码无法成功运行。 src 被分配了一个内存地址,但 dest 没有。我正在使用 Xcode 5 进行命令行开发

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

int main ()
{
    char* src;
    char* dest;

    memcpy(src,  "This is source", 15);
    memcpy(dest, "This is destination", 20);

    strcat(dest, src);

    printf("Final destination string : |%s|", dest);

    return(0);
}

声明后,src 的值为 "" 并有地址,但 dest 为 NULL。我知道这是一个愚蠢的问题,但需要一些帮助才能解决这个问题。

更新 经过大量调查后,我开始知道我需要在 memcpy 之前为指针初始化空间,尽管 Xcode 没有提供我可以轻松找到的有用警告或异常。

正确的用法是使用malloc初始化空间然后做memcpy。

char* src;
char* dest;
src = malloc(sizeof(char)*15);
dest = malloc(sizeof(char)*34);

memcpy(src,  "This is source", 15);
memcpy(dest, "This is destination", 20);

或者我们也可以使用 char 数组并在 dest 上留出足够的空间。

char src[15];
char dest[34];

memcpy(src,  "This is source", 15);
memcpy(dest, "This is destination", 20);

【问题讨论】:

  • Both srcdst 在您的示例中包含垃圾值。它们没有初始化。无论他们最初碰巧持有什么,纯属偶然。初始化变量是您的责任。没有人会为你做这件事。
  • 我现在知道这个问题有一些负面影响,所以我无法对 SF 提出更多问题。如果您看到我的更新,我会感谢您,请重新添加积分。对于初学者来说,你不能认为这是常识,好像我不应该问一样。但是 Linux 和 Mac 中的警告和错误可能会有所不同,并且有些东西不够直观,无法意识到这个问题。在 Xcode 上,当您查看难以判断的溢出数组元素时,它会在观察程序中为您提供 0 值

标签: c memory


【解决方案1】:

您的代码调用了未定义的行为。在初始化它们之前,您正在使用自动存储变量 srcdest 的值。

你写的

"src 被分配了一个内存地址"

这个假设是错误的!(大感叹号)。该变量未初始化,当您以这种方式使用它时,可能会发生任何事情。期间,不讨论。

在 C 程序中有两种变量:

  • 静态存储,这意味着变量使用的存储在链接时确定。具有static 初始化器的全局变量和函数内变量属于这种类型。静态范围变量在程序加载时初始化为 0。

  • 自动存储,即在程序执行时,变量的存储就存在了。

除此之外,C 对象还可以是动态存储的,用malloc 或其亲属分配。

这对您意味着什么? 你必须初始化这些变量。如果你把它们放在静态存储中,它们会被初始化为 0,这对于指针来说是一个非常好的值,但是取消引用它,这是你的代码所做的,是不允许的.因此,您必须将它们初始化为与指针的使用相匹配的兼容对象(=内存区域)的地址。

【讨论】:

    【解决方案2】:

    您既未初始化 src 也未初始化 dest,因此不清楚您将在哪里复制字符串文字。 该程序具有未定义的行为。

    您可以使用数组来做同样的事情。例如

    #include <stdio.h>
    #include <string.h>
    
    int main( void )
    {
        char src[] = "This is source";
        char dest[34] = "This is destination";
    
    
        strcat( dest, src );
    
        printf( "Final destination string : |%s|", dest );
    
        return 0;
    }
    

    或使用指针的另一种方法

    #include <stdio.h>
    #include <string.h>
    
    int main( void )
    {
        const char *s1 = "This is source";
        const char *s2 = "This is destination";
    
        char *dest = malloc( strlen( s1 ) + strlen( s2 ) + 1 );
    
        strcat( strcpy( dest, s2 ), s1 );
    
        printf( "Final destination string : |%s|", dest );
    
        free( dest );
    
        return 0;
    }
    

    【讨论】:

      【解决方案3】:

      如果您使用指针,在使用memcpy 之前,您必须明确保留或分配空间来存储您使用malloc(或其他内存分配例程)复制的字节:

      char *src = NULL;
      
      /* add 1 byte for '\0' string terminator... */
      src = malloc(strlen("This is source") + 1); 
      if (!src) {
          fprintf(stderr, "Error: Could not reserve memory for src pointer\n");
          exit(EXIT_FAILURE);
      }
      
      /* copy over bytes (including terminator byte)... */
      memcpy(src, "This is source", 15);
      
      /* do stuff with 'src'... */
      
      /* don't forget to free 'src' when you are done with it... */
      free(src);
      

      当使用strcat 时,目标指针dest 也应该被分配足够的空间来存储连接的、终止的结果。上面的代码 sn-p 应该提供了有关如何执行此操作的足够提示。

      【讨论】:

      • 但第一个变量“src”使用与 dest 相同的代码成功赋值“This is source”。为什么“dest”不起作用但“src”起作用
      • 一个变量是否“有效”并不重要。如果您没有使用 malloc 或类似的内存分配例程为您的指针预分配足够的空间,则程序是错误的,您将观察到“奇怪”或不一致的行为,例如您所看到的。
      • 在继续之前,您应该阅读指针和内存分配/释放。如果你没有正确管理指针内存,你就会陷入一个痛苦的世界。
      • @HanYi Zhang:变量src没有“成功分配”任何东西。您的实验中的变量 src 包含一个垃圾值,该值只是碰巧不会导致任何崩溃。
      • malloc() 参数中带有strlen() 的示例没有多大意义,您几乎不需要仅用于malloc 的长度。实际上,您将有一个const char * 用于字符串,int 用于strlen() 的结果,然后您可以将它与malloc()memcpy() 一起使用。此外,该示例几乎是合成的,因为您通常会使用 char buffer[50]sizeof buffer 或在 C99 中甚至是 int size = 50char buffer[size]
      【解决方案4】:

      您需要使用 malloc 或将指针设置为指向现有数组的内存: 你需要这样做,因为你现在的指针指向你内存的随机区域,你操作这些区域肯定会导致崩溃或一般系统不稳定 即:

          src=malloc(80);
      

          char mem1[160];
          src=mem1;
          dst=mem1+80;
      

      //或

          char mem2[89];
          dst=mem2;
      

      【讨论】:

      • 这不是字符数组的声明方式,使用char buffer[100],而不是char[100] buffer
      • 嗯,你是对的,自从我用 c 编写以来已经 20 多年了,我会纠正它。虽然我的回答的要点仍然存在:使用数组而不是 malloc() 对于初学者来说更容易掌握。
      猜你喜欢
      • 1970-01-01
      • 2016-01-24
      • 1970-01-01
      • 2015-01-17
      • 1970-01-01
      • 1970-01-01
      • 2013-02-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多