关于数组与指针的思考与总结(Ⅰ)
关于数组与指针的思考与总结(Ⅰ)
这是我15年上半年,也就是刚入大学的时候,发表的第一篇博文.之前是发表在sina上的,现在我把它转到cnblogs这儿.
近期准备总结一下数组与指针的关系:
首先要弄清在一维数组中的各类表达关系(为后面的二维数组做准备)
本文章要弄清 array、&array和*array,数组名的诡异含义,另外聊一些定义数组的方法,还有一些废话云云.
若哪里有不对或瞎扯的地方的欢迎批评,指教!
引入的问题如下:
先看一段代码:
int main( void )
{
int array[3] = { 1, 2, 3 };
printf( "array = %p\t &array = %p\t &array [0]= %p \n", array, &array, &array[0] );
return(0);
}
运行结果如下:
array = 0028FED4 &array = 0028FED4 &array [0] = 0028FED4
也就是说array = &array = &array[0],注意!他们仅仅是地址相同。
下面再接着讨论数组名的含义顺便解释前面的问题:
其实数组名就是个坑,让我久久不能释怀,这就是编译器在背后作祟!
先看看下面的情况:
int main( void )
{
int array[3] = { 1, 2, 3 };
printf( "sizeof(array) = %d\n", sizeof(array) );
printf( "array+1 = %d", *(array + 1) );
return(0);
}
运行结果:
sizeof(array) = 12
array+1 = 2
看出问题了么,在sizeof的时候array是整个数组,但一到array+1的时候array + 1就变成一个指向数组中第一个成员的指针了。
也就是说:
数组名代表的是整个数组的地址,但是也会退化为指针,如果还不理解什么意思的话。这里引用一段《c语言常见295问题集》中的解答
"一个T的数组类型的左值如果出现在表达式中会蜕变为一个指向数组第一个成员的指针(除三种情况以外);结果指针的类型是T的指针。这就是说,一旦数组出现在表达式中,编译器会隐式的生成一个指向数组的第一个成员的指针,就像程序员写出了&a[0]一样。例外的情况是,数组为sizeof或&操作符的操作数,或者为字符数组的字符串初始值。"
总结一下这个成员表达式和指针的关系(最多的就是在讨论数组名的含义):
array + 1 : 代表数组中第二个成员的地址; 若取其值: *(array + 1)
&array:代表整个数组的地址; &array + 1 则是以sizeof(array)的大小递增的;
*array:代表数组第一个成员的值
array[1]:也就是*(array+1);
(备注:在c语言中根本不存在array[0]的语法表达式 ; 任何的 [] 运算法都会转化为指针的运算符)
解释在实际中我们使用的表达式意义:
1.怎么获取一个数组的长度:
若定义数组:
int array[3] = { 1,2,3};
int len = sizeof(array)/sizeof(array[0]);
or
int len = sizeof(array)/sizeof(int);
运算完的len结果都是3
因为sizeof(array) 等于12,而sizeof(array[0])和sizeof(int)都是4;
2.怎么给函数传递一个数组:
int Maxarray( int test[], int size )
{
int Max = test[0];
for ( int i = 0; i < size; i++ )
{
if ( test[i] > Max )
Max = test[i];
}
return(Max);
}
int main()
{
int array[3] = { 1, 2, 3 } ;
int max = Maxarray( array, sizeof(array) / sizeof(int) );
printf( "数组array中最大值是:%d\n", max );
return(0);
}
这里在main函数中向Max函数传递了一个实参"array",在Maxarray中定义形参为"int test[]",其实就是一个数组向指针的蜕化(你还可以这样写 Maxarray(int *test))。因为在实际使用数组的时候不可能把一个数组的全部成员都传进一个函数中使用,于是传进所使用数组地址,也就是数组名(想想多有道理);接着在Maxarray中对传进的数组名进行操作与访问。
3.还有一些定义数组的方法:
char *test01 = "abcdefg";
char test02[] = "abcdefg";
后者应该都认识,就是一个数组,test的值是不能变的。
但是可以这样:
int main( void )
{
const char *test01 = "abcdefg";
printf( "*(test01 + 1) = %c\t", *(test01 + 1) );
printf( "sizeof(test01) = %d\n", sizeof(test01) ); /* 指针变量的字节数都是4 */
/* test01++; */
char test02[] = "abcdefg";
printf( "*(test02 + 1) = %c\t", *(test02 + 1) );
printf( "sizeof(test02) = %d\n", sizeof(test02) );
/* test02++; */
return(0);
}
运行结果:
*(test01 + 1) = b sizeof(test01) = 4
*(test02 + 1) = b sizeof(test02) = 8
注意代码中有两条注释语句,其中第二条语句在编译的时候会报错:
"[Error] lvalue required as increment operand"
也就是说test02不能作为变量(增量)使用;
这和一般数组定义的时候一样,int array[3];的时候array也不能作为变量(增量)使用;
这里着重讨论第一种数组申请,也就是char *test01 = "abcdefg";这里为什么添加const 呢,因为编译器害怕指向一个数组的指针"test01"变成野指针;也就是失去目的的指针;
char *test01 = "abcdefg";
在内存中申请一段字符串 "abcdefg";
接着用一个指针,也就是"test01" 指向这个所申请的这个字符串的地址,看!这是test01就是一个变量了。
这样写了当然也有获取字符串的长度方法,但是却不是前面的sizeof云云那么简单了。因为sizeof(test02)只会得到一个结果为4的值,因为单个指针变量的字节数就是4;
那该怎么表示用一个指针申请的一段字符串的长度呢?
这样吧,也没别的办法,还记得字符串的最后一个是什么么?没错是'\0',那就顺藤摸瓜吧!
int count = 0;//计数器
while(*test02++ != '\0')//判断完后自增
{
count++;
}
接着尝试输出count就可以看到你想要的结果了!
梦想就是你在人生的最低谷,却还有着火一般的热情!
共勉!
浙公网安备 33010602011771号