C he 指针
1.声明一个指向整型数组的指针
int (*p)[10];
2.如果一个 一维数组matrix[10] 作为函数参数 , 则函数原型应为:
void func( int *ptr ); 或
void func( int ptr[]);
如果一个 二维数组matrix[10][10] 作为函数参数 , 则函数原型为 :
void func( int (*ptr)[10] ); 或
void func( int ptr[][10] );
因为 ptr 的第一个下标要根据 第二个下标(整型数组的长度)进行调整,第二个下标根据整型长度调整
而一维的数组 作为参数时,计算下标时不需要。所以声明成
void func(int **ptr) ; 不正确。
3. int *api[10] ;
分析:假定他是一个表达式,对他求值
下标优先级高,所以他是某种类型的数组(包含10个元素)。然后执行间接访问操作,结果是一个整型
所以api 是一个指向整型的指针数组。
4. 理解指针与数组名
例如:int b[4] b的类型是指针常量
例(c和指针 p98):
源文件1中有声明:int a[10]; int *b = a;
在源文件2中有代码: extern int *a;
extern int b[];
x = a[3];
y = b[3];
则程序会失败。
分析: 由源文件1知 a 是一个数组名,b是指针。而在文件2中,a被当成指针变量,所以a[3]的过程如下:a的内容加3,然后进行解引用; b被当成一个数组名(指针常量),所以b[3]过程为:取出b[0]的地址(&b[0]),将他加3;
所以这两个过程都会导致不可预知的错误。
5. 字符串函数:
strlen()的返回值类型是size_t(无符号整数类型),所以 strlen( a ) - strlen( b ) 总是大于等于0。如果将结果强制转换成Int,问题就能解决。
6.注意血统问题:虽然2个指针指向同一个位置,但可能二者完全不是一种类型的。
7.还是数组与指针:
1 #include <stdio.h> 2 3 int 4 main() 5 { 6 int a[4]; 7 int *b = a;
printf("a:%s\n",a); 8 printf("&a:%x\n &b:%x\n", &a,&b); 9 printf("&a[0]:%x\n &b[0]:%x\n",&a[0], &b[0]); 10 }
输出结果如下:
a:bf90bd80
&a:bf90bd80
&b:bf90bd7c
&a[0]:bf90bd80
&b[0]:bf90bd80
数组名的本质是:指向元素的指针常量。但是在 数组名当做sizeof操作符或单目操作符&的操作数时例外。(c和指针 p142)。是叫指针退化。(数组名原地就是数组内容,而指针时指向的地址)。
看程序(coolshell):
1 #include <stdio.h> 2 struct str{ 3 int len; 4 char s[0]; 5 }; 6 7 struct foo { 8 struct str *a; 9 }; 10 11 int main(int argc, char** argv) { 12 struct foo f={0}; 13 if (f.a->s) { 14 printf( f.a->s); 15 } 16 return 0; 17 }
如果将s[0],改为指针,则会在13行崩溃(coolshell);
8. 注意数组的不完整声明(C和指针 P199)。
9. 数组和结构的区别:
数组元素的大小都相同,所以可以通过下表访问。而结构的成员可能时不同的类型。
结构的变量是标量类型。
10. 结构成员的访问采用的 相对地址
struct foo {
int i;
char *p;
}f;
则 &(f->i) 和 &f 一样,而 &(f->p) == &f + 4 (具体参看 coolshell)
可以分配给结构一个连续的区域:(利用了零长数组和相对地址,ISO C不允许)(具体coolshell)
1 #include <stdlib.h> 2 #include <string.h> 3 4 struct line { 5 int length; 6 char contents[0]; // C99的玩法是:char contents[]; 没有指定数组长度 7 }; 8 9 int main(){ 10 int this_length=10; 11 struct line *thisline = (struct line *) 12 malloc (sizeof (struct line) + this_length); 13 thisline->length = this_length; 14 memset(thisline->contents, 'a', this_length); 15 return 0; 16 }