您的位置:首页 > 编程语言 > C语言/C++

C语言之数组与指针

2012-09-28 03:57 295 查看
*******数组首元素的地址 vs 数组首地址[b]*******[/b]

/*

a: bff0660c

a+1: bff06610

&a: bff0660c

&a+1: bff06620

*/

int a[5] = {1,2,3,4,5};

printf("a: %x\n", a); //address of first element in the array

printf("a+1: %x\n", a+1); //address of second element in the array

printf("&a: %x\n", &a); //starting address of the array

printf("&a+1: %x\n", &a+1); //1 plus the ending address of the array

 

[b]*******数组名和指针是不同的概念[/b](可以用extern证明,见deepc2.c)*******

在一个地方定义为指针,另一各地方也只能声明为指针;在一个地方定义为数组,另一各地方也只能声明为数组;

数组和指针都可以指针或下标的形式访问。

[b]*******指针数组与数组指针*******[/b]

int *p[10]; //指针数组。p先与[]结合,构成一个数组的定义,数组名为p,int*修饰的是数组的内容,即数组的每个元素类型为int*。

int (*q)[10] or int (*)[10] q; //数组指针。q先与*结合,构成一个指针的定义,指针变量名为q。int修饰的是数组的内容,即数组的每个元素类型为int。数组在这里并没有名字,是个匿名数组。所以,q是一个指向包含10个int型数据的数组的指针,即数组指针。

可推广至函数返回值 与 函数指针。

/*

b: bfb033a7

p1: bfb033a7

p2: bfb033a7

p1+1: bfb033ac

p2+1: bfb033ac

p3: bfb033a7

p4: bfb033a7

p3+1: bfb033aa

p4+1: bfb033aa

p5: bfb033a7

p6: bfb033a7

p5+1: bfb033b1

p6+1: bfb033b1

*/

char b[5] = {'A','B','C','D'};

printf("b: %x\n", b);

char (*p1)[5] = &b;

char (*p2)[5] = b; //incompatible type

printf("p1: %x\n", p1);

printf("p2: %x\n", p2);

printf("p1+1: %x\n", p1+1); //increase based on type of p1, not &b

printf("p2+1: %x\n", p2+1); //increase based on type of p2, not b

char (*p3)[3] = &b; //incompatible type

char (*p4)[3] = b; //incompatible type

printf("p3: %x\n", p3);

printf("p4: %x\n", p4);

printf("p3+1: %x\n", p3+1); //increase based on type of p3, not &b

printf("p4+1: %x\n", p4+1); //increase based on type of p4, not b

[b]*******地址强制转换*******[/b]

 

//little endian: the least significant byte at lowest address.

//big-endian: the most significant byte at lowest address.

int checkSystem()

{

//union size is the largest size of its fields. And all fields are stored right from lowest address.

union check{

int i;

char ch; //stored at the lowest byte.

}c;

c.i = 1;

return (c.ch == 1);

}

int main()

{

/*

Little-Endian

value: 12345678 //output digits from highest byte to lowest byte

p[0]: 78 //'78' is the least significant byte. p[0] locates at the lowest address.

p[1]: 56

p[2]: 34

p[3]: 12 //'12' is the most significant byte. p[3] locates at the highest address.

ptr1[-1]: 4

*ptr2: 2000000 //output digits from highest byte to lowest byte, so '02' comes first. when big-endian, *ptr2: 0x100

*/

printf("%s\n", checkSystem()?"Little-Endian":"Big-Endian");

int i;

int value = 0x12345678;

printf("value: %x\n", value);

char *p = (char*)&value;

for(i=0; i<4;i++)

{

printf("p[%d]: %x\n", i, p[i]);

}

int a[4] = {1,2,3,4};//1: 0x00000001, 2: 0x00000002, 3: 0x00000002, 4: 0x00000004.
int *ptr1 = (int*)(&a+1); //ptr1 points to the ending address of array a: the integer right after array a.
int *ptr2 = (int*)((int)a+1); //ptr2 points to starting (low) address of the second byte of a[0]。 (int)a+1 与 (int*)a+1不同。

printf("ptr1[-1]: %x\n*ptr2: %x\n", ptr1[-1], *ptr2);

return 0;

}

[b][b]*******
二维数组*******[/b]

#include <stdio.h>

int main(int argc, char* argv[])

{

int a[5][5];

int (*p)[4];

p = a;

printf("a_ptr=%p, p_ptr=%p\n", &a[4][2], &p[4][2]);

printf("%p, %d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);

printf("%p, %d\n", &a[4][2] - &p[4][2], &a[4][2] - &p[4][2]);

printf("%p, %d\n", 0x50-0x40, 0x50-0x40);

/*

*Output:

*a_ptr=0xbfcd5c50, p_ptr=0xbfcd5c40 //address difference: 16 bytes. &a[4][2] - &p[4][2] = 0x10

*0xfffffffc, -4 //pay attention to '%p' and '%d'.

*0x4, 4 //Why 4? It is pointer arithmetic. (int*)0xbfcd5c50-(int*)0xbfcd5c40 = (0xbfcd5c50-0xbfcd5c40)/sizeof(int) = 4.

*0x10, 16

*/

}

 

[b]*******数组参数与指针参数*******[/b]

无法向函数传递一个数组。C语言中,当一维数组作为函数参数的时候,编译器总是把它解析成一个指向其首元素首地址的指针。

无法把指针变量本身传递给一个函数

void GetMemory0(char *p, int num)

{

p = (char*)malloc(num*sizeof(char));

}

char* GetMemory1(char *p, int num)

{

p = (char*)malloc(num*sizeof(char));

return p;

}

void GetMemory2(char **p, int num)

{

*p = (char*)malloc(num*sizeof(char));

}

int main(int argc, char* argv[])

{

char *str = NULL;

GetMemory0(str, 10); //str does not get the address allocated in GetMemory0. str是局部变量,调用时,编译器会做一份拷贝_str,并把_str传给GetMemory。所以GetMemory改变的只是_str。

//str = GetMemory1(str, 10); //str gets the address allocated in GetMemory1.

//GetMemory(&str, 10); //str gets the address allocated in GetMemory2.

if(str == NULL)

printf("str is still NULL\n");

else{

strcpy(str, "hello");

printf("str: %s\n", str);

free(str);

}

/* Output:

* str is still NULL

*/

return 0;

}

如何为str获取内存呢?两种办法。

第一: 用return。 GetMemory1.

第二: 用二级指针。 GetMemory2.

 

[b]*******二维数组参数与二维指针参数*******[/b]

void fun(char a[3][4]);

void fun(char (*p)[4]);

void fun(char a[][4]);

 

void fun(char *p[4]);

void fun(char **p);

 

void fun(char a[3][4][5]);

void fun(char a[][4][5]);

void fun(char (*p)[4][5]);

 

[b]*******函数指针*******[/b]

 

"char* (*func)(char* p1, char* p2)", but not  "char* (*)(char* p1, char* p2) [b]func[/b]".

Example 1:

char* fun(char* p1, char* p2)

{

int i=0;

i=strcmp(p1, p2);

if(0==i)

return p1;

else

return p2;

}

int main(void)

{

char* (*pf1)(char* p1, char* p2);

pf1 = &fun;

printf("%s\n", (pf1)("aa", "bb")); //pf1 vs *pf1

printf("%s\n", (*pf1)("aa", "bb"));

/* Output:

* bb

* bb

*/

return 0;

}

}

 

Another Example:

void function()

{

printf("Call function!\n");

}

int main(int argc, char* argv[])

{

void (*pf2)(); //pf2 is a pointer to a function that takes nothing and returns nothing.

void (*pf3)();

printf("pf2: %x\n&pf2: %x\n", (int)pf2, (int)&pf2);
*(int*)&pf2 = (int)function; //pf2 stores the address of function.
//*(int*)pf3 = (int)function; //Segmentation fault (core dumped). of course.
//pf3 = (int)&function; //worked, but incompatible type
pf3 = function; //worked. equivalent to "*(int*)&pf2 = (int)function;"

printf("function: %x\n&function: %x\n*function: %x\n", (int)function, (int)&function,*(int*)function);

printf("pf2: %x\n&pf2: %x\n", (int)pf2, (int)&pf2);

(*pf2)();

(*pf3)();

/* Output:

* pf2: b77a3270

* &pf2: bfb8a1d0
* function: 804851f //function = &function = *function
* &function: 804851f //function = &function = *function
* *function: 804851f //function = &function = *function

* pf2: 804851f

* &pf2: bfb8a1d0

* Call function!

* Call function!

*/

return 0;

}

 

(* (void (*)())0) (); //convert 0 to a function pointer. the function is stored at address beginning at 0. Then call the function

(* (char** (*)(char**,char**))0)(char**,char**);

 

*******函数指针数组 VS [b][b][b]函数指针数组的指针[/b]*******[/b][/b]

char* (*pf[3])(char* p); //pf is the array name, not a pointer. the array contains three pointers to function.

 

char* (*(*pf)[3])(char* p); //pf is a pointer to an array of three pointers that point to functions.

char* fun1(char*p)

{

printf("fun1: %s\n", p);

return p;

}

char* fun2(char*p)

{

printf("fun2: %s\n", p);

return p;

}

char* fun3(char*p)

{

printf("fun3: %s\n", p);

return p;

}

int main()

{
char* (*fp1[3])(char*p);
char* (*(*fp2)[3])(char*p);

fp2 = &fp1;

fp1[0] = fun1;

fp1[1] = &fun2;

fp1[2] = &fun3;

fp2[0][0]("fp2[0][0]");

fp2[0][0]("fp2[0][1]");

fp2[0][0]("fp2[0][2]");

/* Output:

* fun1: fp2[0][0]

* fun1: fp2[0][1]

* fun1: fp2[0][2]

*/

return 0;

}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  语言 c function fun fp pointers