C语言编译参考博文:C及C++源码执行流程及编译
1 小解
C语言一大特色-指针,指针(pointer)是变量的地址。
指针变量是存放地址的变量。因此,正确灵活使用指针可有效表示复杂的数据结构,动态分配内存。
2 例解
2.1 指针变量的引用
- Demo1
# include<stdio.h>
void main() {
// 整型变量
int a=250,i=250,j=2500;
// 整型指针变量
int *p1,*p_1, *p_2;
// 指针变量名赋值
p_1 = &i;
p_2 = &j;
printf("%s %d, %d \n", "直接访问:",i ,j);
printf("%s %d, %d \n", "指针访问:", *p_1, *p_2);
printf("%s %p, %p \n","变量地址:", p_1, p_2);
}
- Result
直接访问: 250, 2500
指针访问: 250, 2500
变量地址: -531005380, -531005384
- Analysis
(1) 定义指针变量使用星号*
,且需要指定指针变量的类型,即存储的地址类型,若存储整型变量的地址,则使用int *p_1;
表示,其他类推;
(2) 指针变量的赋值,使用指针变量名赋值,指针变量名为p_1
,不包括星号,星号表示取指针指向的对象的内容,即指针变量*p_1
指向存储单元&i
的内容;变量名表示地址值,如上*p_1
输出变量值,p_1
输出变量地址;
(3) 指针变量只能接受地址;
(4) &取变量地址,*取指针所指对象的内容(值);
2.2 交换地址比较数据大小
- Demo2
# include<stdio.h>
void main() {
int a, b, *p1, *p2;
scanf("a=%d, b=%d", &a, &b);
p1 = &a, p2 = &b;
if (a<b) {
p1 = &b;
p2 = &a;
}
printf("输入原始值:a=%d, b=%d \n", a, b);
printf("比较值:max=%d, min=%d \n", *p1, *p2);
}
- Result
a=250,b=2500
输入原始值:a=250, b=2500
比较值:max=2500, min=250
- Analysis
(1) 比较a和b的值,使用指针操作,通过改变指向的地址,即可改变输出值;保证原值不变;
(2) 交换值:指针通过交换地址,普通变量需要通过中间变量改变值;
2.3 指针变量作为函数参数数字比较
- Demo3
# include<stdio.h>
void pointer_swap_value(int *p1, int *p2) {
int temp;
temp = *p1;
*p1 = *p2;
*p2 = temp;
}
void pointer_swap_address(int *p3, int *p4) {
int *temp1;
temp1 = p3;
p3 = p4;
p4 = temp1;
}
void normal_swap(int x, int y) {
int temp2;
temp2 = x;
x = y;
y = temp2;
}
void main() {
void pointer_swap_value(int *p1, int *p2);
void pointer_swap_address(int *p3, int *p4);
void normal_swap(int x, int y);
int a, b, c, d,e,f;
int *pointer_1, *pointer_2, *pointer_3, *pointer_4;
scanf("a=%d,b=%d,c=%d,d=%d,e=%d,f=%d",&a, &b, &c, &d, &e, &f);
pointer_1 = &a;
pointer_2 = &b;
pointer_3 = &e;
pointer_4 = &f;
if (a<b) {
pointer_swap_value(pointer_1, pointer_2);
}
if (c<d) {
normal_swap(c, d);
}
if (e<f) {
pointer_swap_address(pointer_3, pointer_4);
}
printf("指针交换值比较结果:a=%d, b=%d\n", a, b);
printf("普通比较结果:c=%d, d=%d \n", c, d);
printf("指针交换地址比较结果:e=%d, f=%d \n", e, f);
}
- Result
a=250,b=2500,c=250,d=2500,e=250,f=2500
指针交换值比较结果:a=2500, b=250
普通比较结果:c=250, d=2500
指针交换地址比较结果:e=250, f=2500
- Analysis
(1) 普通函数调用normal_swap
实参将数据传递给形参,形参交换数据后,形参被释放,实参的值并未改变;
(2) 指针地址进行实参和形参的值传递,同样,当调用结束后,地址被释放,实参仍不能改变;
(3) 通过改变实参变量指向的变量内容,可实现实参数据的改变;
比较前各指针和变量对应关系:
初始化时, 实际变量a,b
地址假设为0x001,0x002
,指向他们的指针分别指向对应的地址,形参对应的地址如上图所示,只有变量的形参地址有所出入(为方便理解,这里仍用a,b变量表示),因为形参是新开辟的地址,但是指针形参具有指向性,所以地址仍是实参的地址.
执行交换操作时,使用指针变量作为形参的交换有两种交换方式,一种是交换指针变量的值,一种是交换指针变量指向的地址,若交换指针变量的值,则改变形参的值,此时实参的指针也是指向该形参的地址,所以当形参释放是改变了实参的值;若交换指针地址,则将形参指针指向不同的地址,没有改变地址中的内容,所以形参释放时,实参值不会改变;而直接传递变量时,则出现更扯的情况,因为地址都不一样,释放后,自然不会改变实参.
2.4 指针与数组
2.4.1 一维数组
- Demo
# include<stdio.h>
void main() {
int a[10], i=250, j;
int *p, *p1=&i;
p = a;
for(j=0;j<10;j++) {
a[j] = j;
}
for(p=a;p<(a+10);p++) {
printf("pointer to array: %d \n",*p);
}
printf("pointer: %d \n", *p1);
}
- Result
pointer to array: 0
pointer to array: 1
pointer to array: 2
pointer to array: 3
pointer to array: 4
pointer to array: 5
pointer to array: 6
pointer to array: 7
pointer to array: 8
pointer to array: 9
pointer: 250
- Analysis
(1) 数组名为数组首地址,p=a即将指针指向数组首地址,首地址为常量,所以索引数组时使用p++
自增;
(2) 指针索引数组元素:p+j
;
(3) 指针赋值:int *p=&i;
或p=&i;
2.4.2 二维数组
- Demo
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
float (*p)[3],*p1,*p2;
int i, j, row, column, ele_num;
void line_split();
float score[4][3] = {{10, 20, 30},{40, 50, 60},{70, 80, 90},{100, 110, 120}};
row = sizeof(score)/sizeof(score[0]);
column = sizeof(score[0])/sizeof(score[0][0]);
ele_num = row * column;
printf("Array row: %d,column:%d\n",sizeof(score)/sizeof(score[0]),sizeof(score[0])/sizeof(score[0][0]));
line_split();
/*Array score address.*/
printf("score[i]+j address.\n");
for(i=0;i<4;i++){
for(j=0;j<3;j++){
printf("%p\t",score[i]+j);
}
printf("\n");
}
line_split();
/*Assign array name to pointer.*/
printf("p+n address.\n");
for(p1=score[0];p1<score[0]+ele_num;p1++){
if((p1-score[0])%3==0) printf("\n");
printf("%p\t",p1);
}
printf("\n");
line_split();
/*Array row get initial address.*/
printf("Row first element address.\n");
printf("&score[0][0]:%p\tscore[0]:%p\t&score[0]:%p\tscore:%p\t*(score):%p\n",&score[0][0] ,score[0], &score[0],*score, score);
printf("&score[1][0]:%p\tscore[1]:%p\t&score[1]:%p\t(score+1):%p\t*(score+1):%p\n",&score[1][0] ,score[1], &score[1], score+1, *(score+1));
printf("&score[2][0]:%p\tscore[2]:%p\t&score[2]:%p\t(score+2):%p\t*(score+2):%p\n",&score[2][0] ,score[2], &score[2], score+2, *(score+2));
printf("&score[3][0]:%p\tscore[3]:%p\t&score[3]:%p\t(score+3):%p\t*(score+3):%p\n",&score[2][0] ,score[3], &score[3], score+3, *(score+3));
line_split();
printf("%p\n",score[0]+4);
line_split();
printf("*(score+i)+j address\n");
for(i=0;i<4;i++){
for(j=0;j<3;j++){
printf("%p\t",*(score+i)+j);
}
printf("\n");
}
line_split();
printf("%f\n", *(p1+9));
p = score;
printf("%f", *(*(p+3)+2));
system("pause");
}
void line_split(){
printf("-------------------\n");
}
- Result
Array row: 4,column:3
-------------------
score[i]+j address.
000000000062FDE0 000000000062FDE4 000000000062FDE8
000000000062FDEC 000000000062FDF0 000000000062FDF4
000000000062FDF8 000000000062FDFC 000000000062FE00
000000000062FE04 000000000062FE08 000000000062FE0C
-------------------
p+n address.
000000000062FDE0 000000000062FDE4 000000000062FDE8
000000000062FDEC 000000000062FDF0 000000000062FDF4
000000000062FDF8 000000000062FDFC 000000000062FE00
000000000062FE04 000000000062FE08 000000000062FE0C
-------------------
Row first element address.
&score[0][0]:000000000062FDE0 score[0]:000000000062FDE0 &score[0]:000000000062FDE0 score:000000000062FDE0
*(score):000000000062FDE0
&score[1][0]:000000000062FDEC score[1]:000000000062FDEC &score[1]:000000000062FDEC (score+1):000000000062FDEC *(score+1):000000000062FDEC
&score[2][0]:000000000062FDF8 score[2]:000000000062FDF8 &score[2]:000000000062FDF8 (score+2):000000000062FDF8 *(score+2):000000000062FDF8
&score[3][0]:000000000062FDF8 score[3]:000000000062FE04 &score[3]:000000000062FE04 (score+3):000000000062FE04 *(score+3):000000000062FE04
-------------------
000000000062FDF0
-------------------
*(score+i)+j address
000000000062FDE0 000000000062FDE4 000000000062FDE8
000000000062FDEC 000000000062FDF0 000000000062FDF4
000000000062FDF8 000000000062FDFC 000000000062FE00
000000000062FE04 000000000062FE08 000000000062FE0C
-------------------
- Analysis
(1) score和score[0]+0表示二维数组的第0行第0列的地址,其他元素依次类推score[0]+n;&score[0][0]表示第0行第0列元素地址;
(2) score[0]+1表示第0行第1列元素地址;score[1]+2表示第一行第二列元素地址;
(3) score+1表示第1行第0列元素地址;
(4) 普通指针变量p指向数组,每次偏移一个单位指向下一个元素,不能跨行偏移;
(5) 地址获取后,可直接使用*获取地址内的值;
数组元素对应地址表示:
序号 | 0 | 1 | 2 |
0 | &score[0][0] | &score[0][1] | &score[0][2] |
score[0] | score[0]+1 | score[0]+2 | |
&score[0] | *(score+0)+1 | *(score+0)+2 | |
score | |||
*score | |||
1 | &score[1][0] | &score[1][1] | &score[1][2] |
score[0]+3 | score[0]+4 | score[0]+5 | |
score[1] | score[1]+1 | score[1]+2 | |
&score[1] | *(score+1)+1 | *(score+1)+2 | |
score+1 | |||
*(score+1) | |||
2 | &score[2][0] | &score[2][1] | &score[2][2] |
score[0]+6 | score[0]+7 | score[0]+8 | |
score[2] | score[2]+1 | score[2]+2 | |
&score[2] | *(score+2)+1 | *(score+2)+2 | |
score+2 | |||
*(score+2) | |||
3 | &score[3][0] | &score[3][1] | &score[3][2] |
score[0]+9 | score[0]+10 | score[0]+11 | |
score[3] | score[3]+1 | score[3]+2 | |
&score[3] | *(score+3)+1 | *(score+3)+2 | |
score+3 | |||
*(score+3) |
指针表示地址:p=score[0];
序号 | 0 | 1 | 2 |
---|---|---|---|
0 | p | p+1 | p+2 |
1 | p+3 | p+4 | p+5 |
2 | p+6 | p+7 | p+8 |
3 | p+9 | p+10 | p+11 |
2.4.3 数组指针
指向一维数组的指针变量,表示行指针,指向二维数组的行,实实在在的指针,(*p)[n]数据n表示列数,结构如下图:
格式:
int (*p)[3];
其中,(*p)[3]表示指向的行有3个元素,指向的行数不限。
- Demo1
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
float (*p)[3],*p1,*p2;
int i, j, row, column, ele_num, c, r;
void line_split();
float score[4][3] = {{10, 20, 30},{40, 50, 60},{70, 80, 90},{100, 110, 120}};
/*返回指针的函数*/
float *search_column(float (*pointer_c)[3], int column);
float *p_c, *p_r;
printf("Enter the number of student:");
scanf("%d,%d", &c,&r);
printf("The score of No.%d are:\n", c);
p_c = search_column(score, c);
for(i=0;i<3;i++){
printf("%5.2f\t", *(p_c+i));
}
system("pause");
// return 0;
}
float *search_column(float(*pointer_c)[3], int column){
float *pt;
pt = *(pointer_c+column);
return(pt);
}
- Result
Enter the number of student:2
The score of No.2 are:
70.00 80.00 90.00
-
Analysis
(1) 指针变量*p指向一维数组,(p)[3]该数组含有3个浮点型元素;
(2)p
表示二维数组中的行(p=score),取元素地址:(p+i)+j; -
Demo2
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int i, j;
int a[3][2] = {{10, 11}, {2, 13}, {3, 14}};
int a1[4][3] = {{2, 3, 5}, {6, 5, 5}, {44, 20, 30}, {55, 22, 33}};
int (*p2)[2], *p3, (*p4)[2];
printf("\n------数组指针:行指针------\n");
p4 = a1;
for(i=0;i<3;i++){
// p4表示行指针,列数为2:(*p4)[2]
printf("取数组指针的值:%d\n", *p4[i]);
}
printf("\n------数组指针:默认方式------\n");
// 数组指针相当于二维数组的行指针
p2 = a;
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", &a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", *(p2)+i);
}
printf("\n");
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", *(*p2+i));
}
printf("\n------数组指针:指定方式1------\n");
(*p2)[0] = a[0][0];
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", &a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", p2[0]+i);
}
printf("\n");
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", *(p2[0]+i));
}
printf("\n------数组指针:指定方式2------\n");
p4 = a1;
for(i=0;i<4;i++){
for(j=0;j<3;j++){
printf("%d\t", &a1[i][j]);
}
}
printf("\n");
for(i=0;i<12;i++){
printf("%d\t", *(p4)+i);
}
printf("\n");
for(i=0;i<4;i++){
for(j=0;j<3;j++){
printf("%d\t", a1[i][j]);
}
}
printf("\n");
for(i=0;i<12;i++){
printf("%d\t", *(*(p4)+i));
}
printf("\n----普通指针----\n");
p3 = a;
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", &a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", p3+i);
}
printf("\n");
for(i=0;i<3;i++){
for(j=0;j<2;j++){
printf("%d\t", a[i][j]);
}
}
printf("\n");
for(i=0;i<6;i++){
printf("%d\t", *(p3+i));
}
system("pause");
return 0;
}
- Result
------数组指针:行指针------
取数组指针的值:2
取数组指针的值:5
取数组指针的值:5
------数组指针:默认方式------
6487408 6487412 6487416 6487420 6487424 6487428
6487408 6487412 6487416 6487420 6487424 6487428
10 11 2 13 3 14
10 11 2 13 3 14
------数组指针:指定方式1------
6487408 6487412 6487416 6487420 6487424 6487428
6487408 6487412 6487416 6487420 6487424 6487428
10 11 2 13 3 14
10 11 2 13 3 14
------数组指针:指定方式2------
6487360 6487364 6487368 6487372 6487376 6487380 6487384 6487388 6487392 6487396 6487400 6487404
6487360 6487364 6487368 6487372 6487376 6487380 6487384 6487388 6487392 6487396 6487400 6487404
2 3 5 6 5 5 44 20 30 55 22 33
2 3 5 6 5 5 44 20 30 55 22 33
----普通指针----
6487408 6487412 6487416 6487420 6487424 6487428
6487408 6487412 6487416 6487420 6487424 6487428
10 11 2 13 3 14
10 11 2 13 3 14
- Analysis
(1) 数组指针为行指针,等同二维数组的行,其中(*p4)[2],表示p4为数组指针,该指针指向的二维数组有两列;
(2) p4等价于a1[x],表示行,*p4[i]隔一个数取值,表示两列元素;
(3) *p4+i逐次取第i个元素的地址,*(*p4+i)
依次取第i个元素的值;
(4) 由分配的地址空间可知,每个整型数据,分配4个字节,如6487360 6487364分别表示a[0][0]
和a[0][1]
;
2.4.4 指针数组
指针数组用于表示二维数组,是二维数组的优化,仍是数组性质,只不过将数组的内容改为指针,用指针指向数据,节约内存,结构如图2.6所示:
格式:
type *point[number];
其中,通过一位数组取值方式获取指针数组的值,取值格式:name[i],取地址name+i,&name[i],i为整数,若数组未赋值,指针数组为空指针(null)。
- Demo
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
int i, j;
int a[3][2] = {{10, 11}, {2, 13}, {3, 14}};
int a1[4][3] = {{2, 3, 5}, {6, 5, 5}, {44, 20, 30}, {55, 22, 33}};
int (*p2)[2], *p3, (*p4)[2];
char *p5[10] = {"我爱我家", "我爱祖国", "热爱生活", "爱家人", "爱自己"};
char temp, *p6, **p7;
char a2[5][256] = {"我爱我家", "我爱祖国", "热爱生活", "爱家人", "爱自己"};
printf("\n------字符串数组------\n");
for(i=0;i<5;i++){
printf("%s\t",a2[i]);
p5[i] = a2[i];
printf("%s\t", p5[i]);
}
printf("\n------指针数组------\n");
// printf("指针数组:%s", p5[0]);
for(i=0;i<10;i++){
printf("%s\t", p5[i]);
}
printf("\n------指针的指针1------\n");
temp = 'x';
p6 = &temp;
// printf("temp: %c", temp);
p7 = &p6;
printf("指针的指针: %c,%c,%c",temp, *p6, **p7);
printf("\n------指针的指针2------\n");
// 定义时初始化,字符串赋值
// char temp1[10]={"xin"};
char temp1[10] = {'x', 'i', 'n'};
p6 = temp1;
p7 = &p6;
printf("指针的指针: %c,%c,%c",temp1, *p6, **p7);
printf("字符串数组:%s", temp1);
char temp2[10];
// 单个元素字符赋值
temp2[0]='x';
printf("字符数组: %s",temp2);
printf("\n------指针数组------\n");
system("pause");
return 0;
}
- Result
------字符串数组------
我爱我家 我爱我家 我爱祖国 我爱祖国 热爱生活 热爱生活 爱家人 爱家人 爱自己
爱自己
------指针数组------
我爱我家 我爱祖国 热爱生活 爱家人 爱自己 (null) (null) (null) (null) (null)
------指针的指针1------
指针的指针: x,x,x
------指针的指针2------
指针的指针: x,x,x字符串数组:xin字符数组: x
- Analysis
(1) 二维数组a2[5][256]
= {“我爱我家”, “我爱祖国”, “热爱生活”, “爱家人”, “爱自己”};需要指定数组行空间和列空间,以满足存储,但是会造成内存浪费,5*256个字节中只有一小部分被实际使用,短字符串会让大部分的行是空的,另一方面,这个行根本没有使用到,却为他预留内存;
(2) 指针数组就是来解决该问题的,*p[5]={“我爱我家”, “我爱祖国”, “热爱生活”, “爱家人”, “爱自己”};,此种方式,建立含有5个指针变量的数组,这些指针指向对应的数组元素,然后只给实际存在的对象分配内存未使用的则为空指针:null,结果:(null) (null) (null) (null) (null);
(3) 空指针:null无值,但是分配地址,只是未指定是那个地址块,
(3) 直接通过p[i]取值,因为指针已经指向了该数据,可直接获取;
2.4.5 指针的指针
该指针指向另一个指针,即存储另一个指针的地址,也称二级指针。
格式
type **pointer;
-Demo
#include <stdio.h>
#include <stdlib.h>
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
int main(int argc, char *argv[]) {
char temp, *p6, **p7;
printf("\n------指针的指针1------\n");
temp = 'x';
p6 = &temp;
p7 = &p6;
printf("指针的指针: %c,%c,%c",temp, *p6, **p7);
printf("\n------指针的指针2------\n");
// 定义时初始化,字符串赋值
// char temp1[10]={"xin"};
char temp1[10] = {'x', 'i', 'n'};
p6 = temp1;
p7 = &p6;
printf("指针的指针: %c,%c,%c",temp1, *p6, **p7);
printf("字符串数组:%s", temp1);
char temp2[10];
// 单个元素字符赋值
temp2[0]='x';
printf("字符数组: %s",temp2);
system("pause");
return 0;
}
- Result
------指针的指针1------
指针的指针: x,x,x
------指针的指针2------
指针的指针: x,x,x字符串数组:xin字符数组: x
- Analysis
(1) 字符串数组定义时初始化可使用字符串如:char temp1[10]={“xin”};,使用时初始化,则需要单个字符赋值,如temp1[0]=‘x’;;
(2) 指针的指针存储指针的地址,如*p6为一级指针,**p7为二极指针,存储一级指针的地址,如p7=&p6
;;
3 链表
链表是一种数据结构,可动态进行存储分配.
特点:
根据需要实现增加,删除和插入节点.
链表有一个头指针head,仅存放地址,指向一个元素;
链表其他元素包括两个部分,即数据和指针,指针指向下一个节点的元素;
链表元素不是连续存储;
表尾地址为NULL,不指向任何元素,表示链表的结束;
链表的增删改查需要使用指针操作且链表的指向是连续的,中间不能断开;
3.1 静态链表操作
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
# define NULL 0
/* run this program using the console pauser or add your own getch, system("pause") or input loop */
/*建立结构体,添加指向结构体的指针,
该结构体单元是链表的单个元素
*/
struct people{
int age;
char name[20];
struct people *next;
};
typedef struct {
int age;
char name[20];
struct Person *next;
}Person;
int main(int argc, char *argv[]) {
struct people xin, tian, shui, *head, *p;
/* 初始化链表元素*/
xin.age = 10; strcpy(xin.name, "xindaqi");
tian.age = 10; strcpy(tian.name, "lanlan");
shui.age = 10; strcpy(shui.name, "qingqing");
/*建立链表元素关系*/
head = &xin;
xin.next = &tian;
tian.next = &shui;
shui.next = NULL;
p = head;
printf("Age Name\n");
do{
printf("%d %s\n",p->age, p->name);
p = p->next;
}while(p!=NULL);
Person Jim, Green, *h, *p1;
Jim.age = 22;
strcpy(Jim.name, "Jim");
Green.age = 23;
strcpy(Green.name, "Green");
h = &Jim;
Jim.next = &Green;
Green.next = NULL;
p1 = h;
printf("------typdef------\n");
do {
printf("%d, %s\n", p1->age, p1->name);
p1 = p1->next;
}while(p1!=NULL);
system("pause");
// return 0;
}
- Result
Age Name
10 xindaqi
10 lanlan
10 qingqing
------typdef------
22, Jim
23, Green
- Analysis
(1) 利用结构体建立链表元素单元,该结构体中含有指向结构体的指针变量;
(2) 初始化链表,将结构体初始地址赋予指针头
,依次利用next建立链表元素的连接;
(3) 链接:p = head = &xin;
将p指向结构体初始位置,而结构体中含有指针变量,当p指向该指针变量时,会自动指向该指针变量指向的下一个结构体初始位置,形成了链表结构;
4 总结
(1) 指针是变量的地址;指针变量名是地址;指针变量是存储地址的变量;
(2) 实参变量和形参变量通过单向值传递,进行数据交换,当函数调用结束后,形参变量即被释放,即形参值的改变不能改变实参的改变;
(3) 通过改变实参变量指向的变量内容,可实现实参数据的改变;
(4) 链表元素单元是利用结构体建立的,该结构体中含有指向结构体的指针变量;
(5) 二维数组是数组的数组,可将二维数组理解为一维数组的元素为一维数组,因此二维数组的行可视为一维数组即(a[4][3]
中的行a[0]视为int a[4]);
(6) 二维数组元素遍历可通过首元素依次偏移获取如score[0]+n,其中n为二维数组元素,n小于二维数组元素总个数;
(7) 二维数组普通元素寻址有4种方式:
序号 | 取地址 | 描述 |
---|---|---|
1 | &score[i][j] | 取地址符号&和索引下标取地址 |
2 | score[i]+j | 每行初始地址和列偏移量取地址 |
3 | score[0]+n | 数组第一个元素首地址和其他元素偏移量取地址 |
4 | *(score+i)+j | 每行地址和列偏移量取地址 |
(8) 二维数组每行首元素有6种寻址方式:
序号 | 取地址 | 描述 |
---|---|---|
1 | &score[i][0] | 取地址符号&和索引下标取地址 |
2 | score[i]+j | 每行初始地址和列偏移量取地址 |
3 | score[0]+n | 数组第一个元素首地址和其他元素偏移量取地址 |
4 | *(score+i) | 每行地址和列偏移量取地址 |
5 | score+i | 第一个元素首地址和行偏移量获取地址 |
6 | score[i] | 按行取地址 |
[参考文献]
[1][谭浩强著.C程序设计(第二版).北京:清华大学出版社,1999]
[2]https://blog.csdn.net/qq_36561650/article/details/81069194
[3]https://blog.csdn.net/endeavor_g/article/details/80552680
[4]https://blog.csdn.net/qq_34707315/article/details/77318444
[5]http://c.biancheng.net/view/368.html