(1)指针就是地址,也就是说在某一位数确定的操作系统中,他的范围是可以确定的,就是说指针变量的sizeof值是相等的。
比如32位系统下,不管是指向char、int、还是long型变量的指针,他的大小都是4字节
(2)sizeof是关键字,求值是发生在编译的时候,他不同于函数,因为函数的求值是发生在运行的时候。且看:
int ch[6];
sizeof(ch[6]);//是存在的,值为4,编译是不会报错的
(3)数组int a[5];的&a和a代表的含义:
&a:是数组a的起始地址,那么&a+1是指向下一个数组即指向了元素a[5],不是下一个元素a[1]哦
a:是数组第一个元素a[0]的地址,它相当于&a[0]
#include <stdio.h> #include <string.h> int main() { int a[5]={1,2,3,4,5}; int *ptr=(int *)(&a+1);//相当于ptr=a+sizeof(int)*5 printf("\n*(a+1)=%d *(&a[0]+1)=%d *(ptr-1)=%d\n\n",*(a+1),*(&a[0]+1),*(ptr-1)); }
运行结果:
*(a+1)=2 *(&a[0]+1)=2 *(ptr-1)=5
(4)定义为数组声明为指针
先看个例子:
file1.c
#include <stdio.h> char table[20]="ABCDEF"; void Display_TabAddr(void) { printf("file1:table_addr = 0x%x\n",table); }
file2.c
#include <stdio.h> extern char *table; extern void Display_TabAddr(void); int main() { Display_TabAddr(); printf("file2:table_addr = 0x%x\n",table); return 0; }
运行结果:
file1:table = 0x424a30 --> 这才是table数组的真实地址
file2:table = 0x44434241 --> 0x44 0x43 0x42 0x41的意思难道和table[]里边的"D","C","B","A"有关系???
Press any key to continue
结果分析:
①在file2.c中的table是一个指向char型的指针变量,他占有4字节的存储空间,并且extern表明他在其他文件定义,于是编译器就去工程文件中找啊找
终于在file1.c文件中找到了一个table,于是就把table里边前4个字节的值拿出来当做地址使用,这结果为什么这么牵强的?想不懂!
②在file1.c中table是一个数组,实际大小为20字节
(5)定义为指针声明为数组
file1.c
#include <stdio.h> char *pointer="ABCDEF"; void Display_PointerAddr(void) { printf("file1:*(pointer+1) = %c\n",*(pointer+1)); printf("file1:pointer_addr = 0x%x\n",p); }
file2.c
#include <stdio.h> extern char pointer[]; extern void Display_PointerAddr(void); int main() { Display_PointerAddr(); printf("file2:pointer[0] = 0x%x\n",pointer[0]); printf("file2:pointer[1] = 0x%x\n",pointer[1]); printf("file2:pointer[2] = 0x%x\n",pointer[2]); return 0; }
运行结果:
file1:*(pointer+1) = B file1:pointer_addr = 0x422064 file2:pointer[0] = 0x64 file2:pointer[1] = 0x20 file2:pointer[2] = 0x42 Press any key to continue
结果分析:
在file2.c中编译器把file1.c中的char型指针变量pointer当做是长度为4字节的char型数组,file1.c中pointer存放的是地址内容,于是file1.c中就把这个地址内容当做数组的值来使用了。究竟为什么会这样做,实在不懂其中的原理,只能通过这种现象来记住这种结论。
(4)和(5)编程小结:以后遇到这两种情况时千万不要定义了数组和指针中的一种,然后在另外的文件中extern声明为另外一种类型
(6)变量用作右值时,编译器只取其变量值,不关心类型,但有些隐式类型转换会有warming
(7)指针变量用作数组名时,下标为负号的问题
int tab[5];
int *p=&a+1;
p[-1]会被编译器解释成*(p-1),也就指向了tab[4]
(8)结构体成员是“指针”时一定要记得先初始化让他有个明确的指向后才能进行“赋值”操作!!!对于指针变量在定义时如果还不知道其指向最好用NULL拴住他,免得成为野指针!
(9)char *p=(char *)malloc(0);malloc函数返回的内存里边的一个地址,不是NULL,但是这个地址是不能用的。这好比尺子上的某个刻度,刻度本身并没有长度,只有某两个刻度一起才能量出长度。
(10)free(p)之后p的指向并没有发生改变,指向的内容也没有改变。在visual c++6.0中free之后的这个指针变量任然可以拿来使用,
看个例子:
#include <stdio.h> #include <stdlib.h> void my_mallloc(void) { char *p2 = (char *)malloc(1); printf("\nafter free p1--in my_malloc:\np2=%d\n",p2); printf("(*p2) = %d\n\n",*p2); } int main() { char *p1=(char *)malloc(1); printf("\nbefore free p1:\np1=%d\n\n",p1); free(p1); *p1 = 123; printf("after free p1:\n(*p1) = %d\n",*p1); printf("p1 = %d\n",p1); my_mallloc(); return 0; }
运行结果:
before free p1: p1=8266296 after free p1: (*p1) = 123 p1 = 8266296 after free p1--in my_malloc: p2=8266296 (*p2) = -51 Press any key to continue
结果分析:从运行的结果分析可知,在my_malloc函数中定义的指针变量p2和main里边的p1指向是一样的。只是从编程的逻辑上不允许这样做,因为你既然都要free他就是之后不要用到这个内存的意思,之后为了防止吴用free(p1)之后也要将p1用NULL来拴住。