首页 > 解决方案 > 从 C 中的函数访问二维字符数组时出错

问题描述

我看过很多关于在 C 中访问 2D 数组的在线资源,并且都只显示一个答案*( *(arr + i) + j)) 但不幸的是,它给了我这个错误

error: invalid type argument of unary ‘*’ (have ‘int’)
 27 |      printf("%d ",*(*(arr + i) + j));

我的代码:

void pointer_string_array_indexing(char *arr){
        
        for (int i = 0; i < 2; ++i)
        {
            
            for (int j = 0; j < 4; ++j)
        {
            //printf("%c : %d ",*(arr+4*i+j),(arr+4*i+j)); //this will give correct answer
            printf("%c ",*( *(arr + i) + j)); // compilation error
        }
        printf("\n");
        }
        
    }

int main(){
    char S[][4] = {"abc","efg"};
    pointer_string_array_indexing(S);
return 0;

}

我知道这是一个非常著名且重复的问题,但请提供解决方案的代码片段。我正在使用 Ubuntu-20(不过没关系)

标签: cpointersmultidimensional-array

解决方案


要理解为什么一种方式有效而另一种方式无效,您必须了解一些关于 C 如何分配字符串和数组的奇怪事情,以及为什么有时字符串是数组而有时它们是指针。

您的数组声明为char S[][4]. 中的所有字符S都在内存中的一个连续块中。当您访问S[i][j]时,编译后的代码通过计算ijlike表示的偏移量来确定您所引用的字符的地址char *indexed_character_address = S + i*4 + j。现在,编译后的代码用于indexed_character_address加载或存储,具体取决于S[i][j]使用方式。

声明字符串数组的另一种非常不同但令人困惑的相似方式是这样的:

char *T[] = { "tuv", "wxyz" };

编译器在幕后生成此数组的操作与此非常相似:

const char hidden_tuv[4] = { 't', 'u', 'v', '\0' };
const char hidden_wxyz[5] = { 'w', 'x', 'y', 'z', '\0' };
char *T[2] = { hidden_tuv, hidden_wxyz };

和字符串首先放置在某个任意位置"tuv""wxyz"不能保证哪个会先出现,或者它们会彼此靠近。然后使用这两个任意指针创建并初始化另一个数组。

编译器生成的代码以T[i][j]S. 首先它计算ith 字符串指针T的地址,然后它从内存中加载字符串的起始地址之一,然后它用于j从该地址的开头偏移。像这样:

char **address_in_T = T + i;
char *string_start_address = *address_in_T;
// now string_start_address is either hidden_tuv or hidden_wxyz
char *indexed_character_address = string_start_address + j;

那个冗长的代码等价于这个小表达式:

char *indexed_character_address = T[i] + j;
                          //    or &(T[i][j])
                          //    or *(*(T + i) + j)

您的S变量是一个二维字符数组,使用字符串数据初始化,类型为char[2][4]。我的T变量是字符指针的一维数组,类型为(char *)[2].

这里真正令人困惑的部分是,尽管这两个变量的类型非常不同,但 C 语法可以使访问它们看起来非常相似

char c1 = S[i][j];   // actually reads *(S + i*4 + j)
char c2 = T[i][j];    // actually reads *( *(T + i) + j)

推荐阅读