【问题标题】:Using a 2D array global variable in C when I only know one dimension at compile-time当我在编译时只知道一维时,在 C 中使用二维数组全局变量
【发布时间】:2013-12-30 05:21:10
【问题描述】:

我的情况很奇怪。我有一个全局二维字符数组(表示字符串数组)。这些字符串的长度不超过 28,包括终止字符,所以我只想使用一个维度设置为 28 的二维数组。另一个维度是在编译时确定的,但我的程序会计算它有多少个插槽在分配数组之前需要。

我正在尝试像这样声明数组(全局):

char** dictionary;

然后在我的一个函数中,我需要分配它。一旦我尝试使用字典[0][0] 或其他东西访问它们,这两个会给我带来糟糕的访问错误:

dictionary = malloc(sizeof(char)*(28)*numberWords); //numberWords ends up being around 60000
//separately:
char newDict[numberWords][28];
dictionary = newDict;

是的,我对 C 有点陌生。希望我的学校教我而不是 Java。

【问题讨论】:

    标签: c arrays variables 2d global


    【解决方案1】:
    char newDict[numberWords][28];
    dictionary = newDict;
    

    首先这部分是错误的,newDict 是一个数组,它分配在一段内存中,而字典是一个指向指针的指针,它分散在堆的不同部分,因为字典正在寻找一个指针,所以你访问不正确指向一个指针,而 newdict 不包含指针,读取数组和指针,它们是不同的,尽管它们似乎以相似的方式工作

    我看到您想使用数组表示法,因此您分配 dictionaty = newdict(这是错误的)

    最简单的方法是

    char ** dictionary;
     dictionary = (char **)malloc(sizeof(char *)*NUMBER_OF_WORDS)
    
     for(int i =0;i<NUM_WORDS,i++)
     {
     dictionary[i] = (char *)malloc(sizeof(char)*28);
     }
    
     now you can access each word like this 
     dictionary[word_number][the letter]; 
    
     //so in your code you said char ** dictionaty, lets go through this, dictionary is a 
       pointer to another pointer that points to a char. look at my code, dictionary is a 
       pointer, that points to another pointer that eventuall points to a char.
    

    为什么会这样?

    数组符号的工作方式如下 a[x] = *(a+x) ,换句话说,转到数组 a,添加 x 并获取该内存位置中的数字,方括号称为语法糖,只是为了使我们的生活更轻松,真正发生的是 *(a+x)。

    对于 2d 数组 a[x][y] = * ( *(a+x) + y) 这就是说转到指针 a,将 x 添加到指针中,获取该内存中的任何内容 *(a +x) 然后将 y 添加到该内存中并获取指向 * (* (a+x) + y) 的任何内容

    请注意,当我说将 x 添加到指针时,它取决于数组包含的内容,比如你是否有一个 int 数组,因为 int 是 4 个字节,假设 x 是 1,

    int a[10]
    a[1] = *(a+1) (the compiler actually adds 4 bytes to the address although we 
    said 1  obviously since an int is 4 bytes, this 
    is pointer arithmetic you should read up on it. this makes things much easier. 
    

    在内存中真正发生的是添加了 4 个字节以到达 a+1 的地址,编译器为我们处理了这个,所以这让事情变得更容易,在你的情况下它是一个字符,所以说 a [1] = *(a+1),

    回到你的问题。

    dictionary[0][0] 将为您提供第一个单词中的第一个字母,以获取整个字符串,例如 printf 和 %s,因为您的字符串以空值结尾。

    【讨论】:

    • 谢谢。所有这些答案都是可能的解决方案,但这更多是我所要求的。但也许我应该以不同的方式来提高效率。
    【解决方案2】:

    如果您想对字符串进行全局访问,并且您知道字符串的最大长度,但在程序执行之前您不知道要拥有多少个字符串,那么您可以声明一个指向 char 的全局指针数组[28]。另外这里的好处是内存是连续的。

    #define MAX 28
    
    char ( *p_array)[MAX] ;
    
    void func( int size )
    {
        p_array = malloc( sizeof( *p_array ) * size ) ;
    
        for( int i = 0 ; i < size ; i++ )
            snprintf( p_array[i] , sizeof( *p_array ) , "test string no.: %d" , i ) ;
    
        for( int i = 0 ; i < size ; i++ )
            printf("%s\n" , p_array[i] ) ;
    }
    

    【讨论】:

      【解决方案3】:

      如果你声明

      char newDict[numberWords][28];
      

      那么 newDict 不是 char **,而是一个实际的二维字符数组,因此分配不起作用。另一方面,我认为newDict 声明是正确的方法。如果你真的想要这个全局指针的东西,那么也许像

      typedef char String[28]; //a String is a single array of 28 chars
      String* dictionary;
      

      将与您的 newDict 声明兼容(因为数组到指针的衰减仅适用于“外部”级别,而不是递归到所有级别)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-18
        • 2014-04-23
        • 2022-01-11
        • 2021-12-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多