第八章 指標 (Pointer).

Slides:



Advertisements
Similar presentations
第 8 章 数组 计算机科学学院 李淮 Tel QQ
Advertisements

While 迴圈 - 不知重複執行次數
电子成绩单项目实现.
第九章 字串 (String).
第8章 指针 ● 8.1 指针简介 ● 8.2 指针变量的操作 ● 8.3 数组与指针 ● 8.4 二维数组与指针 ●本章小结 ●本章练习.
C语言基础——指针的高级应用 Week 05.
高级语言程序设计 C++程序设计教程(下) 2006年春季学期 与一些教材的区别 偏重理论,不去讨论某个系统的具体使用方法,但会涉及实现技术
数据结构与算法 数据结构与算法实验
第九章 指针 目录 指针与指针变量的概念 变量的指针和指向变量的指针变量 数组的指针和指向数组的指针变量
Linked List(串列) Why Linked List? Pointer Dynamic Allocation
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
C语言程序设计 第十二章 位运算.
Introduction to the C Programming Language
复习与总结.
程序设计基础.
第5章 函数与预处理 《 C语言程序设计》 (Visual C++ 6.0环境) 本章导读
第一章 C语言概述.
struct 可以在同一個名稱下擁有多種資料型態。使用struct能讓資料的存取和處理更為靈活。
資料大樓 --談指標與陣列 綠園.
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
编译原理与技术 类型检查 2018/11/21 《编译原理与技术》-类型检查.
Introduction to the C Programming Language
C 程式設計— 指標.
项目六 用指针优化学生成绩排名 项目要求 项目分析
结构体和共用体 2 梁春燕 华电信息管理教研室.
搜尋資料結構 Search Structures.
C 程式設計— 指標 台大資訊工程學系 資訊系統訓練班.
程序讲解 第一题: 将指定文件的m行到n行字符写到显示屏上,m和n值从键盘输入。 运行时输入及结果: please enter m,n:
Introduction to the C Programming Language
第七章 函数 目录 有参的加法函数的开发 函数定义的一般形式 函数参数和函数的值 函数的调用
Introduction to the C Programming Language
Chap 8 指针 8.1 寻找保险箱密码 8.2 角色互换 8.3 冒泡排序 8.4 电码加密 8.5 任意个整数求和*
C语言程序设计 李祥.
第五章 指针 5.1 指针的概念和定义 5.2 指针运算 5.3 指针和数组 5.4 字符串指针 5.5 指针数组 5.6 指向指针的指针
重點 資料結構之選定會影響演算法 選擇對的資料結構讓您上天堂 程式.
第八章 使用指针.
Introduction to the C Programming Language
第十章 指针.
第7章 陣列與指標 7-1 陣列的基礎 7-2 一維陣列的處理 7-3 二維與多維陣列的處理 7-4 陣列的函數參數
第十章 用户自定义数据类型 目录 学生信息管理系统的开发 结构体数据类型的概述 结构体变量的使用 结构体数组
第十章 结构体与链表 西安工程大学.
C语言概述 第一章.
C语言大学实用教程 第5章 函数与程序结构 西南财经大学经济信息工程学院 刘家芬
C语言复习3----指针.
Introduction to the C Programming Language
函式庫補充資料.
Oop8 function函式.
第六章 指针 C++程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
7.1 C程序的结构 7.2 作用域和作用域规则 7.3 存储属性和生存期 7.4 变量的初始化
第十四章 若干深入问题和C独有的特性 作业: 函数指针 函数作参数 函数副作用 运算 语句 位段 存储类别 编译预处理
C程序设计.
C语言程序设计 李祥 QQ:
第二章 基本数据类型 ——数据的表示.
第三章 基本的輸出與輸入函數 (Basic Output & Input Function)
C程序设计.
挑戰C++程式語言 ──第9章 函數.
第八节 算术运算符和算术表达式.
本节内容 指针类型.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
《数据结构与算法设计》第一部分 面向对象的C++程序设计基础.
第二章 数据类型、运算符和表达式 §2.1 数据与数据类型 §2.2 常量、变量和标准函数 §2.3 基本运算符及其表达式 目 录 上一章
Introduction to the C Programming Language
基本資料型態 變數與常數 運算子 基本的資料處理 授課:ANT 日期:2014/03/03.
第九章 指针 C程序设计中使用指针可以: 使程序简洁、紧凑、高效 有效地表示复杂的数据结构 动态分配内存 得到多于一个的函数返回值.
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
第六章 复合数据类型 指针的声明与使用 数组的声明与使用 指针与数组的相互引用 字符串及相关库函数 new与delete
本节内容 指针类型 视频提供:昆山爱达人信息技术有限公司 官网地址: 联系QQ: QQ交流群 : 联系电话:
C语言基础学习 从外行到入门.
Presentation transcript:

第八章 指標 (Pointer)

「指標就是位址」,這句話可以說是本章最重要的基本觀念。 8-1 指標的基本語法 「指標就是位址」,這句話可以說是本章最重要的基本觀念。 指標 是C語言用來表示位址的一種語法,透過指標可以直接存取到任何的記憶體位址,我們把指標指向欲處理的資料位址,就可以方便地對那個資料進行操作。如果那個位址儲存的是一堆相關的資料,例如一個陣列資料,只須使用一個指標就可以讀取或寫入全部的資料。

8-1-1 指標與位址 「指標就是位址」,意思是說指標資料型態的值就是某個記憶體位址。 例如我們宣告 int a; int *p=&a; 8-1-1 指標與位址 「指標就是位址」,意思是說指標資料型態的值就是某個記憶體位址。 例如我們宣告  int a; int *p=&a;   表示 a 是一個整數變數的名稱,其資料型態是 int,而變數 a 是存在記憶體的某個地方,它的內容是一個"整數值",&a 就是這個地方的位址。 p 是一個整數指標變數(通常簡稱為整數指標)的名稱,其資料型態是 int *,既然是變數所以 p 也是存在記憶體的某個地方,但是它的內容是一個"記憶體位址",請注意 p 前面有個星號 *。我們宣告初值 p=&a 就是把 a 的位址,存入指標變數 p,換句話說就是 p 指向 a

因為 p 是指標變數,當然 &p 也表示這個變數的位址,只不過很少用到就是了。 *p 則是表示 “p所指資料的內容”,就本例而言,因為 p 指向 a,其實 *p 就是 a 的內容值。 變數名稱 (內容) 記憶體位址 a 99 0x1A20 p 0x1A20 0x1A22

就是宣告字元變數 c 與字元指標 cp,而 cp = &c 就是把 c 的位址,存入指標變數 p,換句話說就是 "p 指向 c"。 同理 char c, *cp; cp = &c;   就是宣告字元變數 c 與字元指標 cp,而 cp = &c 就是把 c 的位址,存入指標變數 p,換句話說就是 "p 指向 c"。 c 0x1000 cp 0x1001 ‘X’ 0x1000

指標宣告的語法 type *name; type 是任何資料型態如 int , char, float等 name 是指標變數的名稱

8-1-2 取址運算&與間接運算* 指標的基本用法有兩個相關的運算符號:取址運算 & 與間接運算 * 先來看看 & 取址運算: 8-1-2 取址運算&與間接運算* 指標的基本用法有兩個相關的運算符號:取址運算 & 與間接運算 *   先來看看 & 取址運算: 宣告 int a; a是整數變數 &a是a的位址 這個 & 運算符號的意義,就是取得變數的位址,所以稱為"取址運算"。 其實我們用來輸入整數的 scanf("%d",&a); 就是這個 & 運算符號

而間接運算 * 是用取得“指標所指向的變數值”,變數資料不是直接取得而是經由指標來間接(indirect)存取。 宣告 int a, *p; p=&a; a是整數變數 &a是a的位址 p是指標 *p是指標所指的內容值

因為 p 指向 a,所以 *p 就是 a 的內容,如果   *p = 100; 則 a 的值就會變成 100, 而 printf("%d %d",a, *p); 就會印出 100 100 的結果。

【語法練習 8-1-1】 (1) 試宣告一個整數變數 x ________________________ (2) 試宣告一個整數指標 p ________________________  (3) 將 p 指向 x ________________________ (4) 印出 p 所指的內容 _______________________ (5) 印出 x 的位址 ________________________

8-1-3 指標常數與指標變數 指標常數是指直接指定的記憶體位址,例如 0xA0000000L 是 IBM PC VGA 卡顯示區的記憶體位址。 有一個常常用到的指標常數是 NULL,稱為"虛指標",代表不指向任何資料。   通常我們用 NULL 指標來做一連串資料的結束,或是表示所指向的資料是不存在的。   指標變數是指一個變數的內容是指標,也就是儲存指向某資料的位址;那個位址存的是整數,這個指標就是整數指標;那個位址存的是字元,這個指標就是字元指標。

其實不管是整數指標還是字元指標,對指標的內容而言,都一樣是位址,所差異的只是存取指標所指的內容時,一次是取一個整數為單位,或是一次取一個字元。因此我們可以用型態轉換的方式,直接變換指標的型態。例如: int a, *ap; char c, *cp;   a = 258; ap = &a; cp = (char *) ap; c = *cp;

有時候我們會遇到不指定資料型態的指標,寫成 void 有時候我們會遇到不指定資料型態的指標,寫成 void * 的宣告型態,表示暫時不指定資料型態,由程式設計者自己用型態轉換來指定,視當時的需要再決定。通常都是用在 malloc 或 calloc 等記憶体配置函數的宣告。 指標型態的列印,最好使用 printf 的 %p 格式,這是列印出完整的“位址”。如果編譯程式不是提供 %p 的格式,也可以用 %u 的格式來印。 int num=18, *p=#   printf("*p=%d p=%p &p=%p", *p, p, &p);

【語法練習 8-1-2】 (1) 試宣告一個字元變數 x ________________________ (2) 試宣告一個字元指標 p ________________________  (3) 將 p 指向 x ________________________ (4) 印出 p 所指的內容 _______________________  (5) 印出 p 所佔的記憶體位元組數 ________________________

8-1-4 指標的加減運算 指標的型態宣告會指定所指向的資料,一次存取的單位。整數指標一次取一個整數,而字元指標一次取一個字元為單位。因此,指標的加法和減法運算,也是每次加一個單位或減一個單位的位址。對整數指標而言,加一個單位就是增加 2 個位元組的位址。 如果 p 是整數指標 int *p,其位址是 1000, 則 p+1 就是位 1002,p+2 就是位址 1004, 而 p+i 是 p 往後的第 i 個,位址為  1000+i*sizeof(int) = 1000+i*2

指標的遞加運算 ++ 就是每次指向下一個單位的資料,遞減運算 -- 就是指向前一個單位的資料,通常是處理陣列型態的資料時,才會派上用場。

【範例 8-1-3】用指標存取陣列的元素 7 int a[5]={9,8,7,6,5}; 8 int *ip; 11 ip=a; 12 printf("*ip = %d\n",*ip); 13 printf("*(ip+1) = %d\n",*(ip+1)); 14 printf("*(ip+2) = %d\n",*(ip+2)); 15 printf("*(ip+3) = %d\n",*(ip+3)); 16 printf("*(ip+4) = %d\n",*(ip+4));

8-1-5 指標的用途 指標是C語言功能很強的語法,通常有下列的用途: 1‧傳遞函數的引數 2‧有效率地存取陣列資料 3‧直接記憶體定址 8-1-5 指標的用途 指標是C語言功能很強的語法,通常有下列的用途: 1‧傳遞函數的引數 2‧有效率地存取陣列資料 3‧直接記憶體定址 4‧複雜的資料型態 5‧動態記憶體配置

1‧傳遞函數的引數   由於函數內部無法直接存取函數外的資料,可以將資料的位址以指標型態傳入函數內,這樣就可以間接存取到函數外的資料,這就是所謂的傳址呼叫 (call by address) 的觀念。 我們可以用這種方式來傳回多個函數內部的執行結果,也可以把資料處理完後,將其位址以指標型態來傳回。

2‧有效率地存取陣列資料   當指標指向一個陣列時,陣列元素的存取就可用指標間接運算來進行,由於指標是直接操作記憶体位址,可用比較接近機器指令的方式來運算,所以執行的速度較快,效率較高。此外,指標也用來將陣列的起始位址傳入函數,而不用傳入整個陣列的資料,簡化函數呼叫的執行工作。

3‧直接記憶體定址   用指標直接指向記憶體位址,就可以直接控制 VGA 螢幕或其他硬體裝置,這是比較接近低階語言的用法。此外,也可以用指標傳遞系統呼叫 (system call) 的各項參數。

4‧複雜的資料型態   許多資料結構所使用的複雜資料型態,例如鏈結串列 (linked list)、樹狀結構 (tree structure) 等,就需要用指標型態才能達成。

5‧動態記憶體配置   當程式執行時,視需要向系統要求配置記憶體空間,來存放資料,就是所謂的動態記憶體配置 (dynamic memory allocation)。等到資料處理完後,程式釋放記憶體還給系統,下次有需求時再要求配置,這樣可以充份利用系統所剩餘的記憶體空間,讓程式可以處理更大量的資料。

8-2  指標與函數 指標常見的用途之一,就是傳遞函數的引數,以及傳回函數執行的結果。本節討論指標與函數間的相關應用。

8-2-1 傳址呼叫--用指標傳入函數 C語言程式使用函數呼叫時,會把實際引數的值複製一份傳給型式引數,例如: 8-2-1 傳址呼叫--用指標傳入函數 C語言程式使用函數呼叫時,會把實際引數的值複製一份傳給型式引數,例如: int sum_sq (int,int); main() { int a=3,b=4,c;   c=sum_sq(a,b); printf("sum of square %d %d is %d",a,b,c); } int sum_sq (int p,int q) int r;   r=p*p+q*q; return r;

主程式呼叫 sum_sq 函數時,實際引數 a,b 的值會分別拷貝給函數內的型式引數 p,q 。這種複製引數值的函數呼叫,稱為傳值呼叫 (call by value) 。函數內的 p 與 q 的值即使有所改變,也不會影響到函數外 a,b 的值。這是因為變數 a,b 的勢力範圍只有在主程式中,而變數 p,q 的勢力範圍只在函數中。 但是有時候,我們想在函數內直接改變函數外的資料時,這種方式就無法達成目的。解決的方法就是將變數的位址傳入函數內,這樣函數內藉由位址來間接存取這兩個變數,就可以實際改變其內容。這種將位址傳入出數的方式,就稱為傳址呼叫 ( call by address)。傳址呼叫時,將實際引數的位址帶入,而函數內用指標變數來承接。

【範例 8-2-1】 用傳值呼叫無法將兩變數的值互換 【範例 8-2-1】 用傳值呼叫無法將兩變數的值互換 4 void swap (int,int); 6 main() 7 { int a=100,b=99; 10 printf("before swap(): a=%d b=%d\n",a,b); 11 swap(a,b); 12 printf("after swap(): a=%d b=%d\n",a,b); 13 } 15 void swap (int p, int q) 16 { 17 int t; 19 printf("before exchange: p=%d q=%d\n",p,q); 20 t=p; 21 p=q; 22 q=t; 23 printf("after exchange: p=%d q=%d\n",p,q); 24 }

【範例 8-2-2】 用傳址呼叫來將兩個變數的值互換 【範例 8-2-2】 用傳址呼叫來將兩個變數的值互換 4 void swap (int *,int *); 6 main() 7 { int a=100,b=99; 10 printf("before swap(): a=%d b=%d\n",a,b); 11 swap(&a,&b); 12 printf("after swap(): a=%d b=%d\n",a,b); 13 } 15 void swap (int *p, int *q) 16 { 17 int t; 19 printf("before exchange: *p=%d *q=%d\n",*p,*q); 20 t = *p; 21 *p=*q; 22 *q=t; 23 printf("after exchange: *p=%d *q=%d\n",*p,*q); 24 }

8-2-2 用指標傳回多個傳回值 一個函數只能用 return 來傳回一個傳回值。如果函數內運算的結果,得到一個以上的數值,就必須另覓他法。 8-2-2 用指標傳回多個傳回值 一個函數只能用 return 來傳回一個傳回值。如果函數內運算的結果,得到一個以上的數值,就必須另覓他法。 一種方法是採用全域變數,定義在所有函數內的外面。函數內的所有運算結果,可以直接存入全域變數,欲傳入出數內的引數值,也可以先存入全域變數,然後在函數內直接存取。

【範例 8-2-3】用全域變數來傳回多個運算結果 用全域變數來傳回多個運算結果--商與餘數 4 int quo, rem; /* global variables */ 6 main() 7 { 8 void divide2(int,int); 9 int a=7,b=3; 11 divide2(a,b); 12 printf("quotient of %d divided by %d is %d\n",a,b,quo); 13 printf("remainder of %d divided by %d is %d\n",a,b,rem); 14 } 16 void divide2 (int p, int q) 17 { 18 quo = p/q; 19 rem = p%q; 20 }

用全域變數來傳函數的傳回值,雖然很方便,但是要付出一些代價。其一是全域變數是所有函數都存取得到,非屬本函數專用,可能會被其他函數所更動,導致錯誤的結果。其二是程式如果使用太多全域變數,管理起來較費事,而且函數內部有函數外部的資料,會破壞函數的獨立性。此外,全域變數所佔用的記憶體空間無法釋放,不像函數的引數是在堆疊中,呼叫時才佔用記憶體,函數返回時,就會釋放。 用指標來傳回多個傳回值,也是一種可行的方法。這樣讓傳遞資料的呼叫者,與函數內部的執行結果,直接對映,不會受到其他程式片段或函數的影響。

【範例 8-2-4】 用指標來傳回多個運算結果 用指標來傳回多個運算結果--商與餘數 4 main() 5 { 5 { 6 void divide2(int,int,int *,int *); 7 int a=7,b=3,quo,rem; 8 9 divide2(a,b,&quo,&rem); 10 printf("quotient of %d divided by %d is %d\n",a,b,quo); 11 printf("remainder of %d divided by %d is %d\n",a,b,rem); 12 } 14 void divide2 (int p, int q, int *qval, int *rval) 15 { 16 *qval = p/q; 17 *rval = p%q; 18 }

8-2-3 指標型態的傳回值 有時候函數運算的結果是一項位址,例如一個字串的位址,一個陣列的起始位址等,這時就必須使用指標型態的傳回值。

【範例 8-2-5】 設計一個函數輸入一個字串,傳回字串中第一個空白符號 ( ‘ ’、‘\t 或 ‘\n’ ) 出現的位址,若找不到則傳回虛指標 NULL。字串是以 ‘\0’ 字元做為結束。 5 char *get_white (char *); 7 main() 8 { 9 char msg1[20]="Merry Xmas"; 10 char msg2[20]="line1\nline2\n"; 11 char msg3[20]="ChenHongShan"; 12 char *s1,*s2,*s3; 14 s1=get_white(msg1); 15 printf("msg1 : %s s1 : [%s]\n",msg1,s1); 16 s2=get_white(msg2); 17 printf("msg2 : %s s2 : [%s]\n",msg2,s2); 18 s3=get_white(msg3); 19 printf("msg3 : %s s3 : [%s]\n",msg3,s3); 20 }

22 char *get_white (char *s) 23 { 24 while (*s != '\0') { 25 if (*s == ' ' || *s == '\t' || *s == '\n') 26 return s; 27 s++; 28 }; 29 return NULL; 30 }

執行結果: msg1 : Merry Xmas s1 : [ Xmas] msg2 : line1 line2 s2 : [ ] msg3 : ChenHongShan s3 : [(null)]

8-3  指標與陣列 指標與陣列的使用,關係相當密切。陣列是一連串相同型態資料的集合,配置在連續的記憶體位址,用索引值來存取某個特定的元素。例如   int a[6],i; for (i=0;i<6;i++) a[i]=0; 將 a 整數陣列的 6 個元素都填成 0,其中 a[i] 表示 a 的第 i 個元素。若 a 的起始位址是 1000,則 &a[i] 是 a 的第 i 個元素的位址,就是 1000+i*sizeof(int),可以依此算出。

如果我們將指標指向一個陣列,那麼就可用指標的加減運算來存取陣列的某特定元素。特別是對陣列元素進行連續的存取時,例如列印陣列內容,存入陣列資料等,執行速度較快,因為指標是以記憶體位址來直接存取資料,所以效率較高。這就是為什麼會使用指標來存取陣列資料的原因。上面的例子可改用指標來達成: int a[6],i,*p; p=a; for (i=0;i<6;i++) *(p+i) = 0; 請注意 a 是陣列名稱,可代表陣列的起始位址,所以 p=a; 和 p=&a[0]; 是相同的效果,都是將p指向a陣列的開頭。而 p+i 是 p 加 i 個單位的位址,*(p+i) 就是那個元素的內容,所以 *(p+i) 就相當於 a[i],我們也可以直接寫成 p[i]。

其實上述範例用指標來做,最有效率的寫法如下: int a[b],i,*p; p=a; for (i=0;i<b;i++) *p++ = 0; 注意 *p++ 的作用是先將 p 所指的元素設定為 0 後,再將 p 指標的內容遞增一個單位,使 p 指向下一個元素。

8-3-1 指向陣列的指標 當一個指標變數指向一個陣列時,概念上就可以把指標當成是陣列來用,不管這個陣列型態是整數、字元或是其它更複雜的資料型態。例如:   int score[10],*p=score; 則我們可以用 p[i] 或 *(p+i) 來當成 score[i],其實也可以用 *(score+i) 來表示,只不過這種寫法沒有什麼意義,因為 score 本來就是一個陣列。

如果指標指向一個字串,通常會用如下宣告: char *p="Help"; 其實就是 p 指標指向一個以 '\0' 字元為結束的字元陣列,p[i] 或 *(p+i) 都是表示字串的第 i 個元素,列印整個字串可以用 printf("%s",p); 來表示,詳細的字串用法將在第九章完整地介紹。

【語法練習 8-3-1】 (1) 試宣告一個整數陣列 x ________________________ (2) 試宣告一個整數指標 p ________________________  (3) 將 p 指向 x 陣列 ________________________ (4) 印出 p 所指的第 0 個元素的內容 _______________________ (5) 用for 迴圈印出 p 所指的所有元素的內容 ________________________________________

【語法練習 8-3-2】 (1) 試宣告一個字元陣列 x ________________________ (2) 試宣告一個字元指標 p ________________________  (3) 將 p 指向 x 陣列 ________________________  (4) 印出 p 所指的第 3 個元素的內容 _______________________  (5) 用for 迴圈印出 p 所指的所有元素的內容 ________________________________________

【範例 8-3-1】 列印指標所指向的陣列 4 #define N 6 6 main() 7 { 7 { 8 int a[N]={1,3,5,7,9,11}; 9 int i, *p; 10 11 p=a; 12 for (i=0; i<N; i++) 13 printf("i=%d: %d, %d\n",i,a[i],*p++); 14 }

8-3-2 用指標傳陣列資料入函數 需要將一個陣列傳入函數時,不必將整個陣列的所有元素全部傳入,只須將陣列名稱(也就是陣列的起始位址)當成指標傳入函數即可,函數內部可藉由指標,直接存取陣列的各個元素。

【範例 8-3-2】使用指標來印出傳入函數的陣列資料 4 void print_array (int *,int); 6 main() 7 { 8 int a[ ]={1,3,5,7,9,11}; 9 int n=sizeof(a)/sizeof(int); 11 print_array(a,n); 12 } 13 void print_array (int *p, int cnt) 14 { 15 int i; 17 for (i=0; i<cnt; i++) 18 printf("%dth element : %d\n",i,*p++); 19 }

【範例 8-3-4】 設計一函數,傳入一維整數陣列,及其元素個數,用指標方式,求陣列元素的最大值,並設計一程式來加以驗証。 4 int get_max (int *,int); 5 6 main() 7 { 8 int a[]={1,-3,5,-7,9,-11}; 9 int n=sizeof(a)/sizeof(int); 10 11 printf("max value = %d\n",get_max(a,n)); 12 }

13 int get_max (int *p, int cnt) 14 { 15 int max,i; 16 17 max=p[0]; 18 for (i=1; i<cnt; i++) 19 if (p[i] > max) max=p[i]; 20 return max; 21 }

【範例 8-3-3】 設計一函數,傳入一維整數陣列,及其元素個數,用指標方式來求陣列的總和,並設計一程式來加以驗証。 4 int sum_array (int *,int); 5 6 main() 7 { 8 int a[]={1,3,5,7,9,11}; 9 int n=sizeof(a)/sizeof(int); 10 11 printf("total = %d\n",sum_array(a,n)); 12 }

13 int sum_array (int *p, int cnt) 14 { 15 int i,sum; 16 17 sum=0; 18 for (i=0; i<cnt; i++) 19 sum += *p++; 20 return sum; 21 }

8-3-3 用指標傳回陣列資料 如果函數的輸出是一個陣列,可以直接傳回指向陣列開頭的指標。不過要注意陣列的記憶體空間是否在函數外事先配置好,否則應指定陣列為 static 方可傳回,因為 static 宣告會將陣列配置在靜態變數區,資料才能保存。如果用自動變數,函數一結束,陣列空間就被全部回收了!

【範例 8-3-6】 設計一函數 get_str 由鍵盤輸入一連串字元,直到 Enter 鍵為止,將其變成字串後,傳回指向字串的指標。 3 char *get_str(); 4 5 main() 6 { 7 char *msg; 8 9 msg=get_str(); 10 printf("%s",msg); 11 }

13 char *get_str() 14 { 15 static char str[80]; /* allocate static data */ 16 int i=0; 17 char *p=str; 18 19 *p=getchar(); 20 while (*p != '\n') { 21 p++; 22 *p=getchar(); 23 } 24 *p='\0'; /* make string */ 25 return str; 26 }