c - 从 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(不过没关系)
解决方案
要理解为什么一种方式有效而另一种方式无效,您必须了解一些关于 C 如何分配字符串和数组的奇怪事情,以及为什么有时字符串是数组而有时它们是指针。
您的数组声明为char S[][4]
. 中的所有字符S
都在内存中的一个连续块中。当您访问S[i][j]
时,编译后的代码通过计算i
和j
like表示的偏移量来确定您所引用的字符的地址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
. 首先它计算i
th 字符串指针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)
推荐阅读
- excel - 从一行文本中删除一组特定的字符
- azure-service-fabric - 我可以从集群外部但在同一个本地网络中使用 RPC 调用无状态服务吗?
- docker - 牧场主网络码头工人撰写
- matlab - 将 PDF 图像加载到 MATLAB
- python - Django ORM:如何使用相关模型上的子查询过滤一个模型
- reactjs - redux 不必要地重新渲染整个组件
- python - 在 python 中的一个 re.compile 语句中排除/包含字符串以提取感兴趣的 url
- mongodb - Mongodb findAndUpdate $unset 一个空数组的字段
- django - 更改 Django Rest Framework 分页输出格式
- java - 无法使用 exec-maven-plugin 执行 Maven 多模块项目