以下是C:
中的代码void test1(void);
int main(){
test1();
return 0;
}
void test1(void){
char c,
*p = &c,
*sp1[3] = {"this 1","this 2", "this 3"}, //pointers array
(*sp2)[5] = {"this 1","this 2", "this 3"},
//2 dimensions array declaration in method 1
sp3[][5] = {"this 1","this 2", "this 3"};
//2 dimensions array declaration in method 2
p++; //ok
sp1++; //error
sp2++; //ok
sp3++; //error
}
我读过一个指针是一个变量,所以增量是可以的,但数组名不是一个变量,所以赋值是不可接受的。
在上面的代码中,p
是一个指针,所以增量是正确的; sp1
,sp3
都是数组名称,增量会导致错误,但为什么sp2
可以呢?
在同一本书中,有如下功能:
//print lines
void writelines(char *lineptr[],int nlines){
while(--nlines >= 0){
printf("%s\n",*lineptr++);
}
}
在此函数中,lineptr
是数组的名称,但会对其应用增量。为什么?是因为参数是用C中的值转换的,所以lineptr
实际上是指针吗?
答案 0 :(得分:2)
目前还不清楚你的代码试图完成什么,而不仅仅是与指针和数组搏斗,试图围绕它们的使用(这是你的C学习时间的极好用途)。
考虑到这一点,让我们看看你的声明,并试着帮助理解它们。首先让我们看看c
和p
(我已经初步化了'c'以避免使用未初始化的值):
char c = 'a',
*p = &c,
c
简单地声明为char
,在函数堆栈上创建1-char
自动存储。 p
被声明为字符指针(或指向char 的指针),其值初始化为地址 c
(指针只是一个变量,用于保存其他内容的地址作为其值。正常变量,例如c
包含立即值,在这种情况下为'a'
。{{1}只需将p
的地址作为其值,例如c
指向p
)
接下来声明一个指针数组,它们被初始化为保存初始化程序中提供的字符串文字的地址,例如
c
注意:如果要提供每个指针的初始化,则无需指定 *sp1[] = {"this 1","this 2", "this 3"},
。
在这里,您有效地将3
的数组声明为char * 。 3-pointers
指向sp1[0]
,"this 1"
指向sp1[1]
等等......
接下来,你声明一个指向数组5 char 的指针(或指向5-chars数组的指针)注意:,就像在我的评论中那样,是不够的2 -chars,因此它被声明为指向下面"this 2"
数组的指针。现在,您需要注意这里。由于您声明了一个指向数组的指针,它本身没有为7个字符分配任何存储空间(它只是一个指向已存在7个字符的指针)。你有几个选择。
由于7-chars
的类型为sp3
,您可以在char[][7]
之后声明sp2
,并为其指定兼容数组的地址,例如
sp3
让 *sp1[] = {"this 1","this 2", "this 3"},
sp3[][7] = {"this 1","this 2", "this 3"},
(*sp2)[7] = sp3,
指向sp2
的开头,或者您可以使用C99 复合文字为sp3
声明后的文字创建存储空间,例如
sp2
最后,您可以为 *sp1[] = {"this 1","this 2", "this 3"},
/* using a compound literal to create storage */
(*sp2)[7] = (char [][7]){"this 1","this 2", "this 3"},
sp3[][7] = {"this 1","this 2", "this 3"},
动态分配存储空间(我们将再次离开)。现在因为你只是在这里与指针搏斗,你看到你不能简单地增量 sp2
它是一个数组,但是......你可以声明一个指针指向它的开头并将其作为一部分递增你的运动,例如
sp3
现在将拼图的所有部分组合在一起并执行每个指针的增量,您可以执行类似于以下操作的操作。 (注意:我在递增 sp3[][7] = {"this 1","this 2", "this 3"},
*p3 = *sp3; /* pointer to first element in sp3 */
之后不会降低p
的价值,而是我还是p++
,因此它仍然指向有效的存储空间)
p - 1
示例使用/输出
#include <stdio.h>
void test1 (void);
int main (void) {
test1();
return 0;
}
void test1 (void) {
char c = 'a',
*p = &c,
*sp1[] = {"this 1","this 2", "this 3"},
/* using a compound literal to create storage */
(*sp2)[7] = (char [][7]){"this 1","this 2", "this 3"},
sp3[][7] = {"this 1","this 2", "this 3"},
*p3 = *sp3; /* pointer to first element in sp3 */
p++; /* advance p to one-char-past-c */
(*sp1)++; /* advance pointer to sp1[0] by one */
sp2++; /* advance pointer to next char[7] */
p3++; /* advance pointer to sp3[0] by one */
printf ("(p - 1): %c\n*sp1: %s\n*sp2: %s\np3 : %s\n",
*(p - 1), *sp1, *sp2, p3);
}
注意:如果您选择在$ ./bin/arrayptrinc
(p - 1): a
*sp1: his 1
*sp2: this 2
p3 : his 1
之后声明sp2
并让sp3
指向sp2
的开头,则输出相同用:
sp3
虽然我不确定这是否与您的想法完全相同,但我认为它与您锻炼身体的位置非常接近。如果没有,请告诉我。仔细看看,如果您有任何其他问题,请告诉我。