指標變數課堂實習 I
命令列編譯方式
如果你希望在 cmd 視窗內編譯並執行你的程式的話,
可以把下面這段命令拷貝到一個檔案中,
並且命名為 clcc.bat,
@echo off
set ccpath=C:\Program Files\Microsoft Visual Studio 8\VC
set oldpath=%path%
set path=%path%;%ccpath%\bin
@echo on
%bcpath%\bin\cl -L%ccpath%\lib -I%ccpath%\include %1 %2 %3 %4 %5 %6 %7
@echo off
set path=%oldpath%
set ccpath=
@echo on
接下來你可以運用下面的命令來編譯/連結你的 prog1.c 程式:
此命令會產生 prog1.exe 的可執行檔案,
再輸入
就可以執行程式了。
詳細請參考 C 程式的開發流程
程式一:這個程式提供基本的功能,不用函式、陣列、及指標
#include <stdio.h>
void main(void)
{
float x, sum=0.0;
int i;
for (i=0; i<10; i++)
{
scanf("%f",&x);
sum += x;
}
printf("The sum of 10 numbers is %f\n",sum);
}
程式二:這個程式運用陣列來存放讀入的資料
#include <stdio.h>
void main(void)
{
float x[10], sum=0.0;
int i;
for (i=0; i<10; i++)
{
scanf("%f",&x[i]);
sum += x[i];
}
printf("The sum of 10 numbers is %f\n",sum);
}
紅字部份是和前一個程式不一樣的地方。
這個程式沒有必要使用陣列來存放資料,
最主要是讓你再熟悉一次陣列的用法,
程式四運用函式來讀取資料時就需要用陣列了。
程式三:讓使用者自己決定他要輸入幾個資料
#include <stdio.h>
void main(void)
{
float x[10], sum=0.0;
int i, num;
printf("Please input the number of items: ");
scanf("%d",&num);
for (i=0; i<num; i++)
{
scanf("%f",&x[i]);
sum += x[i];
}
printf("The sum of %d numbers is %f\n",num,sum);
}
程式四:讓我們把輸入資料寫成一個函式,以免干擾主程式的邏輯
#include <stdio.h>
int input(float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
if ((num=input(x)) > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
}
else
printf("You did not enter any number\n");
}
int input(float ary[])
{
int numOfItems;
int i;
printf("Please input the number of items: ");
scanf("%d",&numOfItems);
for (i=0; i<numOfItems; i++)
scanf("%f",&ary[i]);
return numOfItems;
}
在傳遞陣列到函式內使用時,
函式參數雖然宣告 float ary[],
函式內部也把 ary 當成一個陣列來使用,
但是實際上並沒有一個新的陣列 ary,
在函式內所使用到的陣列 ary 陣列根本就是 main() 函式內的 float x[10] 陣列,
ary 陣列可以看成是 x 陣列的一個別名。
嚴格來說,
在函式 input() 內 ary 只是一個浮點指標常數,
其資料為 x (變數 x[0] 之位址),
(既然只是浮點指標常數而已,
所以記憶體內沒有保留存放浮點數的陣列資料,
只保留了存放一個記憶體位址的區域),
在函式參數的地方宣告 float ary[] 和宣告 float * const ary
是完全等效的,
下一個程式就是讓你嘗試看看。
程式五:指標常數 vs. 陣列參數
#include <stdio.h>
int input(float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
if ((num=input(x)) > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
return;
}
else
printf("You did not enter any number\n");
}
int input(float * const ary)
{
int numOfItems;
int i;
printf("Please input the number of items: ");
scanf("%d",&numOfItems);
for (i=0; i<numOfItems; i++)
scanf("%f",&ary[i]);
return numOfItems;
}
請注意:
float const *ary (常數指標)和 float *const ary (指標常數)兩種宣告是不一樣的,
前一種是說 *ary 是不能改變的資料,
後一種是說 ary 內的資料是不能改變的。
float const *ary 和 const float *ary 則是完全一樣的。
程式六:既然是指標當然可以用指標的運算和存取方法
#include <stdio.h>
int input(float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
if ((num=input(x)) > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
return;
}
else
printf("You did not enter any number\n");
}
int input(float *ary)
{
int numOfItems;
int i;
printf("Please input the number of items: ");
scanf("%d",&numOfItems);
for (i=0; i<numOfItems; i++)
scanf("%f",ary+i);
return numOfItems;
}
程式七:函式利用參數 ptrNum 回傳一個資料 num
#include <stdio.h>
void input(int *, float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
input(&num, x);
if (num > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
}
else
printf("You did not enter any number\n");
return;
}
void input(int *ptrNum, float *ary)
{
int i;
printf("Please input the number of items: ");
scanf("%d",ptrNum);
for (i=0; i<*ptrNum; i++)
scanf("%f",&ary[i]);
return;
}
請注意什麼時候該用 * 號,什麼時候該用 & 號。
程式八:再一次說明既然是指標當然可以用指標的運算和存取方法
#include <stdio.h>
void input(int *, float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
input(&num, x);
if (num > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
}
else
printf("You did not enter any number\n");
}
void input(int *ptrNum, float ary[])
{
int i;
printf("Please input the number of items: ");
scanf("%d",ptrNum);
for (i=0; i<*ptrNum; i++)
scanf("%f",ary+i);
return;
}
程式九:觀念驗證
這個程式如果你懂了的話,
你應該已經知道 C 編譯器是如何對待參數的型態,
你已經完全暸解到:
記憶體 (變數) 是用來存放資料的,
不管你將它宣告成什麼型態,
只要保留的記憶體夠多,
CPU 可以把適當的資料存放進去,
等到需要使用的時候就可以再把其內存放的資料拿出來使用。
在程式中宣告變數的型態的目的,
是編譯器用來區分模凌兩可的語法用的,
是用來幫你做自動型態轉換用的,
卻無法限制 CPU 在其內要存放什麼樣子的資料。
當然你不要學這個程式,
程式是要寫來讓人家看的,
編譯器的型態檢查是幫助你寫程式的,
別玩弄它。
#include <stdio.h>
void input(int, float []);
void main(void)
{
float x[10], sum=0.0;
int i, num;
input((int)&num, x); // 將 num 的位址 &num 存放在參數變數 ptrNum 中
if (num > 0)
{
for (i=0; i<num; i++)
sum += x[i];
printf("The sum of %d numbers is %f\n",num,sum);
}
else
printf("You did not enter any number\n");
}
void input(int ptrNum, float ary[]) // 宣告一個 2 bytes 的參數變數 ptrNum
{
int i;
printf("Please input the number of items: ");
scanf("%d",ptrNum);
for (i=0; i<*(int *)ptrNum; i++) // 將參數變數 ptrNum 內存放的資料讀出來當作一個整數位址 (int *) 來用
scanf("%f",ary+i);
return;
}
以上我們假設位址是 16 bits,
int 型態變數也是 16 bits。